Annotation of embedaddon/strongswan/src/libimcv/pts/components/ita/ita_comp_tboot.c, revision 1.1.1.2

1.1       misho       1: /*
1.1.1.2 ! misho       2:  * Copyright (C) 2011-2020 Andreas Steffen
1.1       misho       3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "ita_comp_tboot.h"
                     17: #include "ita_comp_func_name.h"
                     18: 
                     19: #include "imcv.h"
                     20: #include "pts/components/pts_component.h"
                     21: 
                     22: #include <utils/debug.h>
                     23: #include <pen/pen.h>
                     24: 
                     25: typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t;
                     26: 
                     27: /**
                     28:  * Private data of a pts_ita_comp_tboot_t object.
                     29:  *
                     30:  */
                     31: struct pts_ita_comp_tboot_t {
                     32: 
                     33:        /**
                     34:         * Public pts_component_t interface.
                     35:         */
                     36:        pts_component_t public;
                     37: 
                     38:        /**
                     39:         * Component Functional Name
                     40:         */
                     41:        pts_comp_func_name_t *name;
                     42: 
                     43:        /**
                     44:         * Sub-component depth
                     45:         */
                     46:        uint32_t depth;
                     47: 
                     48:        /**
                     49:         * PTS measurement database
                     50:         */
                     51:        pts_database_t *pts_db;
                     52: 
                     53:        /**
                     54:         * Primary key for AIK database entry
                     55:         */
                     56:        int aik_id;
                     57: 
                     58:        /**
                     59:         * Primary key for Component Functional Name database entry
                     60:         */
                     61:        int cid;
                     62: 
                     63:        /**
                     64:         * Component is registering measurements
                     65:         */
                     66:        bool is_registering;
                     67: 
                     68:        /**
                     69:         * Time of TBOOT measurement
                     70:         */
                     71:        time_t measurement_time;
                     72: 
                     73:        /**
                     74:         * Expected measurement count
                     75:         */
                     76:        int count;
                     77: 
                     78:        /**
                     79:         * Measurement sequence number
                     80:         */
                     81:        int seq_no;
                     82: 
                     83:        /**
                     84:         * Reference count
                     85:         */
                     86:        refcount_t ref;
                     87: 
                     88: };
                     89: 
                     90: METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
                     91:        pts_ita_comp_tboot_t *this)
                     92: {
                     93:        return this->name;
                     94: }
                     95: 
                     96: METHOD(pts_component_t, get_evidence_flags, uint8_t,
                     97:        pts_ita_comp_tboot_t *this)
                     98: {
                     99:        return PTS_REQ_FUNC_COMP_EVID_PCR;
                    100: }
                    101: 
                    102: METHOD(pts_component_t, get_depth, uint32_t,
                    103:        pts_ita_comp_tboot_t *this)
                    104: {
                    105:        return this->depth;
                    106: }
                    107: 
                    108: METHOD(pts_component_t, measure, status_t,
                    109:        pts_ita_comp_tboot_t *this, uint8_t qualifier, pts_t *pts,
                    110:        pts_comp_evidence_t **evidence)
                    111: 
                    112: {
                    113:        size_t pcr_len;
                    114:        pts_pcr_t *pcrs;
                    115:        pts_pcr_transform_t pcr_transform;
                    116:        pts_meas_algorithms_t hash_algo;
                    117:        pts_comp_evidence_t *evid;
                    118:        char *meas_hex, *pcr_before_hex, *pcr_after_hex;
                    119:        chunk_t measurement, pcr_before, pcr_after;
                    120:        uint32_t extended_pcr;
                    121: 
                    122:        switch (this->seq_no++)
                    123:        {
                    124:                case 0:
                    125:                        /* dummy data since currently the TBOOT log is not retrieved */
                    126:                        time(&this->measurement_time);
                    127:                        meas_hex = lib->settings->get_str(lib->settings,
                    128:                                                "%s.plugins.imc-attestation.pcr17_meas", NULL, lib->ns);
                    129:                        pcr_before_hex = lib->settings->get_str(lib->settings,
                    130:                                                "%s.plugins.imc-attestation.pcr17_before", NULL, lib->ns);
                    131:                        pcr_after_hex = lib->settings->get_str(lib->settings,
                    132:                                                "%s.plugins.imc-attestation.pcr17_after", NULL, lib->ns);
                    133:                        extended_pcr = PCR_TBOOT_POLICY;
                    134:                        break;
                    135:                case 1:
                    136:                        /* dummy data since currently the TBOOT log is not retrieved */
                    137:                        meas_hex = lib->settings->get_str(lib->settings,
                    138:                                                "%s.plugins.imc-attestation.pcr18_meas", NULL, lib->ns);
                    139:                        pcr_before_hex = lib->settings->get_str(lib->settings,
                    140:                                                "%s.plugins.imc-attestation.pcr18_before", NULL, lib->ns);
                    141:                        pcr_after_hex = lib->settings->get_str(lib->settings,
                    142:                                                "%s.plugins.imc-attestation.pcr18_after", NULL, lib->ns);
                    143:                        extended_pcr = PCR_TBOOT_MLE;
                    144:                        break;
                    145:                default:
                    146:                        return FAILED;
                    147:        }
                    148: 
                    149:        if (meas_hex == NULL || pcr_before_hex == NULL || pcr_after_hex == NULL)
                    150:        {
                    151:                return FAILED;
                    152:        }
                    153: 
                    154:        hash_algo = PTS_MEAS_ALGO_SHA1;
                    155:        pcr_len = HASH_SIZE_SHA1;
                    156:        pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
                    157: 
                    158:        /* get and check the measurement data */
                    159:        measurement = chunk_from_hex(
                    160:                                        chunk_create(meas_hex, strlen(meas_hex)), NULL);
                    161:        pcr_before = chunk_from_hex(
                    162:                                        chunk_create(pcr_before_hex, strlen(pcr_before_hex)), NULL);
                    163:        pcr_after = chunk_from_hex(
                    164:                                        chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
                    165:        if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
                    166:                measurement.len != pcr_len)
                    167:        {
                    168:                DBG1(DBG_PTS, "TBOOT measurement or PCR data have the wrong size");
                    169:                free(measurement.ptr);
                    170:                free(pcr_before.ptr);
                    171:                free(pcr_after.ptr);
                    172:                return FAILED;
                    173:        }
                    174: 
                    175:        pcrs = pts->get_pcrs(pts);
1.1.1.2 ! misho     176:        if (!pcrs)
        !           177:        {
        !           178:                return FAILED;
        !           179:        }
1.1       misho     180:        pcrs->set(pcrs, extended_pcr, pcr_after);
                    181:        evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
                    182:                                                        this->depth, extended_pcr, hash_algo, pcr_transform,
                    183:                                                        this->measurement_time, measurement);
                    184:        evid->set_pcr_info(evid, pcr_before, pcr_after);
                    185: 
                    186:        return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
                    187: }
                    188: 
                    189: METHOD(pts_component_t, verify, status_t,
                    190:        pts_ita_comp_tboot_t *this, uint8_t qualifier,pts_t *pts,
                    191:        pts_comp_evidence_t *evidence)
                    192: {
                    193:        bool has_pcr_info;
                    194:        uint32_t extended_pcr, vid, name;
                    195:        enum_name_t *names;
                    196:        pts_meas_algorithms_t algo;
                    197:        pts_pcr_transform_t transform;
                    198:        pts_pcr_t *pcrs;
                    199:        time_t measurement_time;
                    200:        chunk_t measurement, pcr_before, pcr_after;
                    201:        status_t status;
                    202: 
                    203:        this->aik_id = pts->get_aik_id(pts);
                    204:        pcrs = pts->get_pcrs(pts);
1.1.1.2 ! misho     205:        if (!pcrs)
        !           206:        {
        !           207:                return FAILED;
        !           208:        }
1.1       misho     209:        measurement = evidence->get_measurement(evidence, &extended_pcr,
                    210:                                                                &algo, &transform, &measurement_time);
                    211: 
                    212:        status = this->pts_db->get_comp_measurement_count(this->pts_db,
                    213:                                                                        this->name, this->aik_id, algo,
                    214:                                                                        &this->cid, &this->count);
                    215:        if (status != SUCCESS)
                    216:        {
                    217:                return status;
                    218:        }
                    219:        vid = this->name->get_vendor_id(this->name);
                    220:        name = this->name->get_name(this->name);
                    221:        names = imcv_pts_components->get_comp_func_names(imcv_pts_components, vid);
                    222: 
                    223:        if (this->count)
                    224:        {
                    225:                DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence "
                    226:                         "measurements", this->count, pen_names, vid, names, name);
                    227:        }
                    228:        else
                    229:        {
                    230:                DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
                    231:                         "measurements", pen_names, vid, names, name);
                    232:                this->is_registering = TRUE;
                    233:        }
                    234: 
                    235:        if (this->is_registering)
                    236:        {
                    237:                status = this->pts_db->insert_comp_measurement(this->pts_db,
                    238:                                                                measurement, this->cid, this->aik_id,
                    239:                                                                ++this->seq_no, extended_pcr, algo);
                    240:                if (status != SUCCESS)
                    241:                {
                    242:                        return status;
                    243:                }
                    244:                this->count = this->seq_no + 1;
                    245:        }
                    246:        else
                    247:        {
                    248:                status = this->pts_db->check_comp_measurement(this->pts_db,
                    249:                                                                measurement, this->cid, this->aik_id,
                    250:                                                                ++this->seq_no, extended_pcr, algo);
                    251:                if (status != SUCCESS)
                    252:                {
                    253:                        return status;
                    254:                }
                    255:        }
                    256: 
                    257:        has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
                    258:        if (has_pcr_info)
                    259:        {
                    260:                if (!chunk_equals_const(pcr_before, pcrs->get(pcrs, extended_pcr)))
                    261:                {
                    262:                        DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
                    263:                                                   extended_pcr);
                    264:                }
                    265:                if (pcrs->set(pcrs, extended_pcr, pcr_after))
                    266:                {
                    267:                        return SUCCESS;
                    268:                }
                    269:        }
                    270: 
                    271:        return SUCCESS;
                    272: }
                    273: 
                    274: METHOD(pts_component_t, finalize, bool,
                    275:        pts_ita_comp_tboot_t *this, uint8_t qualifier, bio_writer_t *result)
                    276: {
                    277:        char result_buf[BUF_LEN];
                    278: 
                    279:        if (this->is_registering)
                    280:        {
                    281:                /* close registration */
                    282:                this->is_registering = FALSE;
                    283: 
                    284:                snprintf(result_buf, BUF_LEN, "registered %d evidence measurements",
                    285:                                 this->seq_no);
                    286:        }
                    287:        else if (this->seq_no < this->count)
                    288:        {
                    289:                snprintf(result_buf, BUF_LEN, "%d of %d evidence measurements "
                    290:                                 "missing", this->count - this->seq_no, this->count);
                    291:                return FALSE;
                    292:        }
                    293:        else
                    294:        {
                    295:                snprintf(result_buf, BUF_LEN, "%d evidence measurements are ok",
                    296:                                 this->count);
                    297:        }
                    298:        DBG1(DBG_PTS, "%s", result_buf);
                    299:        result->write_data(result, chunk_from_str(result_buf));
                    300: 
                    301:        return TRUE;
                    302: }
                    303: 
                    304: METHOD(pts_component_t, get_ref, pts_component_t*,
                    305:        pts_ita_comp_tboot_t *this)
                    306: {
                    307:        ref_get(&this->ref);
                    308:        return &this->public;
                    309: }
                    310: 
                    311: METHOD(pts_component_t, destroy, void,
                    312:           pts_ita_comp_tboot_t *this)
                    313: {
                    314:        int count;
                    315:        uint32_t vid, name;
                    316:        enum_name_t *names;
                    317: 
                    318:        if (ref_put(&this->ref))
                    319:        {
                    320:                if (this->is_registering)
                    321:                {
                    322:                        count = this->pts_db->delete_comp_measurements(this->pts_db,
                    323:                                                                                                this->cid, this->aik_id);
                    324:                        vid = this->name->get_vendor_id(this->name);
                    325:                        name = this->name->get_name(this->name);
                    326:                        names = imcv_pts_components->get_comp_func_names(imcv_pts_components,
                    327:                                                                                                vid);
                    328:                        DBG1(DBG_PTS, "deleted %d registered %N '%N' functional component "
                    329:                                 "evidence measurements", count, pen_names, vid, names, name);
                    330:                }
                    331:                this->name->destroy(this->name);
                    332:                free(this);
                    333:        }
                    334: }
                    335: 
                    336: /**
                    337:  * See header
                    338:  */
                    339: pts_component_t *pts_ita_comp_tboot_create(uint32_t depth,
                    340:                                                                                   pts_database_t *pts_db)
                    341: {
                    342:        pts_ita_comp_tboot_t *this;
                    343: 
                    344:        INIT(this,
                    345:                .public = {
                    346:                        .get_comp_func_name = _get_comp_func_name,
                    347:                        .get_evidence_flags = _get_evidence_flags,
                    348:                        .get_depth = _get_depth,
                    349:                        .measure = _measure,
                    350:                        .verify = _verify,
                    351:                        .finalize = _finalize,
                    352:                        .get_ref = _get_ref,
                    353:                        .destroy = _destroy,
                    354:                },
                    355:                .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
                    356:                                                                                  PTS_ITA_QUALIFIER_FLAG_KERNEL |
                    357:                                                                                  PTS_ITA_QUALIFIER_TYPE_TRUSTED),
                    358:                .depth = depth,
                    359:                .pts_db = pts_db,
                    360:                .ref = 1,
                    361:        );
                    362: 
                    363:        return &this->public;
                    364: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>