pts_database_t *pts_db;
/**
- * Primary key for Component Functional Name database entry
+ * Primary key for AIK database entry
*/
- int cid;
+ int kid;
/**
- * Primary key for AIK database entry
+ * Primary key for IMA BIOS Component Functional Name database entry
*/
- int kid;
+ int bios_cid;
+
+ /**
+ * Primary key for IMA Runtime Component Functional Name database entry
+ */
+ int ima_cid;
+
+ /**
+ * Component is registering IMA BIOS measurements
+ */
+ bool is_bios_registering;
/**
- * Component is registering measurements
+ * Component is registering IMA boot aggregate measurement
*/
- bool is_registering;
+ bool is_ima_registering;
/**
* Measurement sequence number
*/
int count_failed;
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
};
/**
/**
* Extend measurement into PCR an create evidence
*/
-static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, pts_pcr_t *pcrs,
+static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
+ u_int8_t qualifier, pts_pcr_t *pcrs,
u_int32_t pcr, chunk_t measurement)
{
size_t pcr_len;
pts_pcr_transform_t pcr_transform;
pts_meas_algorithms_t hash_algo;
+ pts_comp_func_name_t *name;
pts_comp_evidence_t *evidence;
chunk_t pcr_before = chunk_empty, pcr_after = chunk_empty;
free(pcr_before.ptr);
return NULL;
}
- evidence = pts_comp_evidence_create(this->name->clone(this->name),
- this->depth, pcr, hash_algo, pcr_transform,
- this->measurement_time, measurement);
+ name = this->name->clone(this->name);
+ name->set_qualifier(name, qualifier);
+ evidence = pts_comp_evidence_create(name, this->depth, pcr, hash_algo,
+ pcr_transform, this->measurement_time, measurement);
if (this->pcr_info)
{
pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
/**
* Compute and check boot aggregate value by hashing PCR0 to PCR7
*/
-static void check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
+static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
{
u_int32_t i;
u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
u_char pcr_buffer[HASH_SIZE_SHA1];
chunk_t file_name, boot_aggregate;
hasher_t *hasher;
- bool pcr_ok = TRUE;
+ bool success, pcr_ok = TRUE;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!hasher)
{
DBG1(DBG_PTS, "%N hasher could not be created",
hash_algorithm_short_names, HASH_SHA1);
+ return FALSE;
}
for (i = 0; i < 8 && pcr_ok; i++)
{
if (pcr_ok)
{
+ success = chunk_equals(boot_aggregate, measurement);
DBG1(DBG_PTS, "boot aggregate value is %scorrect",
- chunk_equals(boot_aggregate, measurement) ? "":"in");
+ success ? "":"in");
+ return success;
}
else
{
DBG1(DBG_PTS, "failed to compute boot aggregate value");
+ return FALSE;
}
}
}
METHOD(pts_component_t, measure, status_t,
- pts_ita_comp_ima_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
+ pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t **evidence)
{
bios_entry_t *bios_entry;
ima_entry_t *ima_entry;
pcrs = pts->get_pcrs(pts);
- switch (this->state)
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
{
- case IMA_STATE_INIT:
- if (!load_bios_measurements(IMA_BIOS_MEASUREMENTS, this->bios_list,
- &this->measurement_time))
- {
- return FAILED;
- }
- this->state = IMA_STATE_BIOS;
- /* fall through to next state */
- case IMA_STATE_BIOS:
- status = this->bios_list->remove_first(this->bios_list,
- (void**)&bios_entry);
- if (status != SUCCESS)
- {
- DBG1(DBG_PTS, "could not retrieve bios measurement entry");
- return status;
- }
- evid = extend_pcr(this, pcrs, bios_entry->pcr,
- bios_entry->measurement);
- free(bios_entry);
+ switch (this->state)
+ {
+ case IMA_STATE_INIT:
+ if (!load_bios_measurements(IMA_BIOS_MEASUREMENTS,
+ this->bios_list, &this->measurement_time))
+ {
+ return FAILED;
+ }
+ this->bios_count = this->bios_list->get_count(this->bios_list);
+ this->state = IMA_STATE_BIOS;
+ /* fall through to next state */
+ case IMA_STATE_BIOS:
+ status = this->bios_list->remove_first(this->bios_list,
+ (void**)&bios_entry);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_PTS, "could not retrieve bios measurement entry");
+ return status;
+ }
+ evid = extend_pcr(this, qualifier, pcrs, bios_entry->pcr,
+ bios_entry->measurement);
+ free(bios_entry);
- /* break if still some BIOS measurements are left */
- if (this->bios_list->get_count(this->bios_list))
- {
+ this->state = this->bios_list->get_count(this->bios_list) ?
+ IMA_STATE_BIOS : IMA_STATE_INIT;
break;
- }
-
- /* check if IMA runtime measurements are enabled */
- if (!load_runtime_measurements(IMA_RUNTIME_MEASUREMENTS,
- this->ima_list, &this->measurement_time))
- {
+ default:
return FAILED;
- }
-
- this->state = this->ima_list->get_count(this->ima_list) ?
- IMA_STATE_BOOT_AGGREGATE : IMA_STATE_END;
- break;
- case IMA_STATE_BOOT_AGGREGATE:
- case IMA_STATE_RUNTIME:
- status = this->ima_list->remove_first(this->ima_list,
- (void**)&ima_entry);
- if (status != SUCCESS)
- {
- DBG1(DBG_PTS, "could not retrieve ima measurement entry");
- return status;
- }
- if (this->state == IMA_STATE_BOOT_AGGREGATE)
- {
- check_boot_aggregate(pcrs, ima_entry->measurement);
- }
-
- evid = extend_pcr(this, pcrs, IMA_PCR, ima_entry->measurement);
- if (evid)
- {
- evid->set_validation(evid, PTS_COMP_EVID_VALIDATION_PASSED,
- ima_entry->filename);
- }
- free(ima_entry->filename);
- free(ima_entry);
+ }
+ }
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
+ {
+ switch (this->state)
+ {
+ case IMA_STATE_INIT:
+ if (!load_runtime_measurements(IMA_RUNTIME_MEASUREMENTS,
+ this->ima_list, &this->measurement_time))
+ {
+ return FAILED;
+ }
+ this->state = IMA_STATE_BOOT_AGGREGATE;
+ /* fall through to next state */
+ case IMA_STATE_BOOT_AGGREGATE:
+ case IMA_STATE_RUNTIME:
+ status = this->ima_list->remove_first(this->ima_list,
+ (void**)&ima_entry);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_PTS, "could not retrieve ima measurement entry");
+ return status;
+ }
+ if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count)
+ {
+ if (!check_boot_aggregate(pcrs, ima_entry->measurement))
+ {
+ return FAILED;
+ }
+ }
+ evid = extend_pcr(this, qualifier, pcrs, IMA_PCR,
+ ima_entry->measurement);
+ if (evid)
+ {
+ evid->set_validation(evid, PTS_COMP_EVID_VALIDATION_PASSED,
+ ima_entry->filename);
+ }
+ free(ima_entry->filename);
+ free(ima_entry);
- this->state = this->ima_list->get_count(this->ima_list) ?
+ this->state = this->ima_list->get_count(this->ima_list) ?
IMA_STATE_RUNTIME : IMA_STATE_END;
- break;
- case IMA_STATE_END:
- break;
+ break;
+ default:
+ return FAILED;
+ }
+ }
+ else
+ {
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ return FAILED;
}
*evidence = evid;
- return evid ? ((this->state == IMA_STATE_END) ? SUCCESS : NEED_MORE) :
- FAILED;
+ if (!evid)
+ {
+ return FAILED;
+ }
+
+ return (this->state == IMA_STATE_INIT || this->state == IMA_STATE_END) ?
+ SUCCESS : NEED_MORE;
}
METHOD(pts_component_t, verify, status_t,
- pts_ita_comp_ima_t *this, pts_t *pts, pts_comp_evidence_t *evidence)
+ pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t *evidence)
{
bool has_pcr_info;
- u_int32_t extended_pcr, vid, name;
+ u_int32_t pcr, vid, name;
enum_name_t *names;
pts_meas_algorithms_t algo;
pts_pcr_transform_t transform;
status_t status;
char *uri;
+ /* some first time initializations */
+ if (!this->keyid.ptr)
+ {
+ if (!pts->get_aik_keyid(pts, &this->keyid))
+ {
+ DBG1(DBG_PTS, "AIK keyid not available");
+ return FAILED;
+ }
+ this->keyid = chunk_clone(this->keyid);
+ if (!this->pts_db)
+ {
+ DBG1(DBG_PTS, "pts database not available");
+ return FAILED;
+ }
+ }
+
pcrs = pts->get_pcrs(pts);
- measurement = evidence->get_measurement(evidence, &extended_pcr,
- &algo, &transform, &measurement_time);
+ measurement = evidence->get_measurement(evidence, &pcr, &algo, &transform,
+ &measurement_time);
- switch (this->state)
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
{
- case IMA_STATE_INIT:
- if (!pts->get_aik_keyid(pts, &this->keyid))
- {
- return FAILED;
- }
- this->keyid = chunk_clone(this->keyid);
+ switch (this->state)
+ {
+ case IMA_STATE_INIT:
+ this->name->set_qualifier(this->name, qualifier);
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->keyid, algo, &this->bios_cid,
+ &this->kid, &this->bios_count);
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ vid = this->name->get_vendor_id(this->name);
+ name = this->name->get_name(this->name);
+ names = pts_components->get_comp_func_names(pts_components, vid);
- if (!this->pts_db)
- {
- DBG1(DBG_PTS, "pts database not available");
- return FAILED;
- }
- status = this->pts_db->get_comp_measurement_count(this->pts_db,
- this->name, this->keyid, algo,
- &this->cid, &this->kid, &this->bios_count);
- if (status != SUCCESS)
- {
- return status;
- }
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
-
- if (this->bios_count)
- {
- DBG1(DBG_PTS, "checking %d %N '%N' BIOS evidence measurements",
- this->bios_count, pen_names, vid, names, name);
- }
- else
- {
- DBG1(DBG_PTS, "registering %N '%N' BIOS evidence measurements",
- pen_names, vid, names, name);
- this->is_registering = TRUE;
- }
- this->state = IMA_STATE_BIOS;
- /* fall through to next state */
- case IMA_STATE_BIOS:
- if (extended_pcr != IMA_PCR)
- {
- if (this->is_registering)
+ if (this->bios_count)
+ {
+ DBG1(DBG_PTS, "checking %d %N '%N' BIOS evidence measurements",
+ this->bios_count, pen_names, vid, names, name);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "registering %N '%N' BIOS evidence measurements",
+ pen_names, vid, names, name);
+ this->is_bios_registering = TRUE;
+ }
+
+ this->state = IMA_STATE_BIOS;
+ /* fall through to next state */
+ case IMA_STATE_BIOS:
+ if (this->is_bios_registering)
{
status = this->pts_db->insert_comp_measurement(this->pts_db,
- measurement, this->cid, this->kid,
- ++this->seq_no, extended_pcr, algo);
+ measurement, this->bios_cid, this->kid,
+ ++this->seq_no, pcr, algo);
if (status != SUCCESS)
{
return status;
else
{
status = this->pts_db->check_comp_measurement(this->pts_db,
- measurement, this->cid, this->kid,
- ++this->seq_no, extended_pcr, algo);
+ measurement, this->bios_cid, this->kid,
+ ++this->seq_no, pcr, algo);
if (status != SUCCESS)
{
return status;
}
}
break;
- }
- this->state = IMA_STATE_BOOT_AGGREGATE;
- /* fall through to next state */
- case IMA_STATE_BOOT_AGGREGATE:
- check_boot_aggregate(pcrs, measurement);
- this->state = IMA_STATE_RUNTIME;
- break;
- case IMA_STATE_RUNTIME:
- this->count++;
- if (evidence->get_validation(evidence, &uri) !=
- PTS_COMP_EVID_VALIDATION_PASSED)
- {
- DBG1(DBG_PTS, "policy URI could no be retrieved");
- this->count_failed++;
+ default:
return FAILED;
- }
- status = this->pts_db->check_file_measurement(this->pts_db,
- pts->get_platform_info(pts),
- PTS_MEAS_ALGO_SHA1_IMA,
- measurement, uri);
- switch (status)
- {
- case SUCCESS:
- DBG3(DBG_PTS, "%#B for '%s' is ok", &measurement, uri);
- this->count_ok++;
- break;
- case NOT_FOUND:
- DBG2(DBG_PTS, "%#B for '%s' not found", &measurement, uri);
- this->count_unknown++;
+ }
+ }
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
+ {
+ int ima_count;
+
+ switch (this->state)
+ {
+ case IMA_STATE_BIOS:
+ if (!check_boot_aggregate(pcrs, measurement))
+ {
+ return FAILED;
+ }
+ this->state = IMA_STATE_INIT;
+ /* fall through to next state */
+ case IMA_STATE_INIT:
+ this->name->set_qualifier(this->name, qualifier);
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->keyid, algo,
+ &this->ima_cid, &this->kid, &ima_count);
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ vid = this->name->get_vendor_id(this->name);
+ name = this->name->get_name(this->name);
+ names = pts_components->get_comp_func_names(pts_components, vid);
+
+ if (ima_count)
+ {
+ DBG1(DBG_PTS, "checking %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ status = this->pts_db->check_comp_measurement(this->pts_db,
+ measurement, this->ima_cid,
+ this->kid, 1, pcr, algo);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "registering %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ this->is_ima_registering = TRUE;
+ status = this->pts_db->insert_comp_measurement(this->pts_db,
+ measurement, this->ima_cid,
+ this->kid, 1, pcr, algo);
+ }
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ this->state = IMA_STATE_RUNTIME;
break;
- case VERIFY_ERROR:
- DBG1(DBG_PTS, "%#B for '%s' differs", &measurement, uri);
- this->count_differ++;
+ case IMA_STATE_RUNTIME:
+ this->count++;
+ if (evidence->get_validation(evidence, &uri) !=
+ PTS_COMP_EVID_VALIDATION_PASSED)
+ {
+ DBG1(DBG_PTS, "policy URI could no be retrieved");
+ this->count_failed++;
+ return FAILED;
+ }
+ status = this->pts_db->check_file_measurement(this->pts_db,
+ pts->get_platform_info(pts),
+ PTS_MEAS_ALGO_SHA1_IMA,
+ measurement, uri);
+ switch (status)
+ {
+ case SUCCESS:
+ DBG3(DBG_PTS, "%#B for '%s' is ok", &measurement, uri);
+ this->count_ok++;
+ break;
+ case NOT_FOUND:
+ DBG2(DBG_PTS, "%#B for '%s' not found", &measurement, uri);
+ this->count_unknown++;
+ break;
+ case VERIFY_ERROR:
+ DBG1(DBG_PTS, "%#B for '%s' differs", &measurement, uri);
+ this->count_differ++;
+ break;
+ case FAILED:
+ default:
+ DBG1(DBG_PTS, "%#B for '%s' failed", &measurement, uri);
+ this->count_failed++;
+ }
+
break;
- case FAILED:
default:
- DBG1(DBG_PTS, "%#B for '%s' failed", &measurement, uri);
- this->count_failed++;
+ return FAILED;
}
-
- break;
- case IMA_STATE_END:
- break;
+ }
+ else
+ {
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ return FAILED;
}
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info)
{
- if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
+ if (!chunk_equals(pcr_before, pcrs->get(pcrs, pcr)))
{
DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
- extended_pcr);
+ pcr);
}
- if (pcrs->set(pcrs, extended_pcr, pcr_after))
+ if (pcrs->set(pcrs, pcr, pcr_after))
{
return SUCCESS;
}
}
else
{
- pcr_after = pcrs->extend(pcrs, extended_pcr, measurement);
+ pcr_after = pcrs->extend(pcrs, pcr, measurement);
if (pcr_after.ptr)
{
return SUCCESS;
}
METHOD(pts_component_t, finalize, bool,
- pts_ita_comp_ima_t *this)
+ pts_ita_comp_ima_t *this, u_int8_t qualifier)
{
u_int32_t vid, name;
enum_name_t *names;
+ bool success = TRUE;
+ this->name->set_qualifier(this->name, qualifier);
vid = this->name->get_vendor_id(this->name);
name = this->name->get_name(this->name);
names = pts_components->get_comp_func_names(pts_components, vid);
- if (this->is_registering)
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
{
- /* close registration */
- this->is_registering = FALSE;
+ /* finalize BIOS measurements */
+ if (this->is_bios_registering)
+ {
+ /* close registration */
+ this->is_bios_registering = FALSE;
- DBG1(DBG_PTS, "registered %d %N '%N' BIOS evidence measurements",
- this->seq_no, pen_names, vid, names, name);
+ DBG1(DBG_PTS, "registered %d %N '%N' BIOS evidence measurements",
+ this->seq_no, pen_names, vid, names, name);
+ }
+ else if (this->seq_no < this->bios_count)
+ {
+ DBG1(DBG_PTS, "%d of %d %N '%N' BIOS evidence measurements missing",
+ this->bios_count - this->seq_no, this->bios_count,
+ pen_names, vid, names, name);
+ success = FALSE;
+ }
}
- else if (this->seq_no < this->bios_count)
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
{
- DBG1(DBG_PTS, "%d of %d %N '%N' BIOS evidence measurements missing",
- this->bios_count - this->seq_no, this->bios_count,
- pen_names, vid, names, name);
- return FALSE;
- }
+ /* finalize IMA file measurements */
+ if (this->is_ima_registering)
+ {
+ /* close registration */
+ this->is_ima_registering = FALSE;
- /* finalize IMA file measurements */
- if (this->count)
+ DBG1(DBG_PTS, "registered %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ }
+ if (this->count)
+ {
+ DBG1(DBG_PTS, "processed %d %N '%N' file evidence measurements: "
+ "%d ok, %d unknown, %d differ, %d failed",
+ this->count, pen_names, vid, names, name,
+ this->count_ok, this->count_unknown,
+ this->count_differ, this->count_failed);
+ success = !this->count_differ && !this->count_failed;
+ }
+ }
+ else
{
- DBG1(DBG_PTS, "processed %d %N '%N' file evidence measurements: "
- "%d ok, %d unknown, %d differ, %d failed",
- this->count, pen_names, vid, names, name,
- this->count_ok, this->count_unknown, this->count_differ,
- this->count_failed);
-
- return !this->count_differ && !this->count_failed;
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ success = FALSE;
}
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+
+ return success;
+}
- return TRUE;
+METHOD(pts_component_t, get_ref, pts_component_t*,
+ pts_ita_comp_ima_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
}
METHOD(pts_component_t, destroy, void,
u_int32_t vid, name;
enum_name_t *names;
- if (this->is_registering)
+ if (ref_put(&this->ref))
{
- count = this->pts_db->delete_comp_measurements(this->pts_db,
- this->cid, this->kid);
vid = this->name->get_vendor_id(this->name);
name = this->name->get_name(this->name);
names = pts_components->get_comp_func_names(pts_components, vid);
- DBG1(DBG_PTS, "deleted %d registered %N '%N' functional component "
- "evidence measurements", count, pen_names, vid, names, name);
+
+ if (this->is_bios_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->bios_cid, this->kid);
+ DBG1(DBG_PTS, "deleted %d registered %N '%N' BIOS evidence "
+ "measurements", count, pen_names, vid, names, name);
+ }
+ if (this->is_ima_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->ima_cid, this->kid);
+ DBG1(DBG_PTS, "deleted registered %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ }
+ this->bios_list->destroy_function(this->bios_list,
+ (void *)free_bios_entry);
+ this->ima_list->destroy_function(this->ima_list,
+ (void *)free_ima_entry);
+ this->name->destroy(this->name);
+ free(this->keyid.ptr);
+ free(this);
}
- this->bios_list->destroy_function(this->bios_list, (void *)free_bios_entry);
- this->ima_list->destroy_function(this->ima_list, (void *)free_ima_entry);
- this->name->destroy(this->name);
- free(this->keyid.ptr);
- free(this);
}
/**
* See header
*/
-pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t *pts_ita_comp_ima_create(u_int32_t depth,
pts_database_t *pts_db)
{
pts_ita_comp_ima_t *this;
.measure = _measure,
.verify = _verify,
.finalize = _finalize,
+ .get_ref = _get_ref,
.destroy = _destroy,
},
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_IMA,
- qualifier),
+ PTS_QUALIFIER_UNKNOWN),
.depth = depth,
.pts_db = pts_db,
.bios_list = linked_list_create(),
.ima_list = linked_list_create(),
.pcr_info = lib->settings->get_bool(lib->settings,
"libimcv.plugins.imc-attestation.pcr_info", TRUE),
+ .ref = 1,
);
return &this->public;