Annotation of embedaddon/strongswan/src/libimcv/pts/pts_pcr.c, revision 1.1.1.2

1.1       misho       1: /*
1.1.1.2 ! misho       2:  * Copyright (C) 2012-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 "pts_pcr.h"
                     17: 
                     18: #include <utils/debug.h>
                     19: 
                     20: #include <stdarg.h>
                     21: 
                     22: typedef struct private_pts_pcr_t private_pts_pcr_t;
                     23: 
                     24: /**
                     25:  * Private data of a pts_pcr_t object.
                     26:  *
                     27:  */
                     28: struct private_pts_pcr_t {
                     29: 
                     30:        /**
                     31:         * Public pts_pcr_t interface.
                     32:         */
                     33:        pts_pcr_t public;
                     34: 
                     35:        /**
                     36:         * Shadow PCR registers
                     37:         */
                     38:        chunk_t pcrs[PTS_PCR_MAX_NUM];
                     39: 
                     40:        /**
                     41:         * Number of extended PCR registers
                     42:         */
                     43:        uint32_t pcr_count;
                     44: 
                     45:        /**
                     46:         * Highest extended PCR register
                     47:         */
                     48:        uint32_t pcr_max;
                     49: 
                     50:        /**
                     51:         * Bitmap of extended PCR registers
                     52:         */
                     53:        uint8_t pcr_select[PTS_PCR_MAX_NUM / 8];
                     54: 
                     55:        /**
1.1.1.2 ! misho      56:         * Length in bytes of a PCR register (size of hash used)
        !            57:         */
        !            58:        size_t pcr_len;
        !            59: 
        !            60:        /**
        !            61:         * Hash algorithm of PCR bank
        !            62:         */
        !            63:        pts_meas_algorithms_t pcr_algo;
        !            64: 
        !            65:        /**
1.1       misho      66:         * Hasher used to extend shadow PCRs
                     67:         */
                     68:        hasher_t *hasher;
                     69: 
                     70: };
                     71: 
1.1.1.2 ! misho      72: METHOD(pts_pcr_t, get_pcr_algo, pts_meas_algorithms_t,
        !            73:        private_pts_pcr_t *this)
        !            74: {
        !            75:        return this->pcr_algo;
        !            76: }
        !            77: 
1.1       misho      78: METHOD(pts_pcr_t, get_count, uint32_t,
                     79:        private_pts_pcr_t *this)
                     80: {
                     81:        return this->pcr_count;
                     82: }
                     83: 
                     84: METHOD(pts_pcr_t, select_pcr, bool,
                     85:        private_pts_pcr_t *this, uint32_t pcr)
                     86: {
                     87:        uint32_t i, f;
                     88: 
                     89:        if (pcr >= PTS_PCR_MAX_NUM)
                     90:        {
                     91:                DBG1(DBG_PTS, "PCR %2u: number is larger than maximum of %u",
                     92:                                           pcr, PTS_PCR_MAX_NUM-1);
                     93:                return FALSE;
                     94:        }
                     95: 
                     96:        /* Determine PCR selection flag */
                     97:        i = pcr / 8;
                     98:        f = 1 << (pcr - 8*i);
                     99: 
                    100:        /* Has this PCR already been selected? */
                    101:        if (!(this->pcr_select[i] & f))
                    102:        {
                    103:                this->pcr_select[i] |= f;
                    104:                this->pcr_max = max(this->pcr_max, pcr);
                    105:                this->pcr_count++;
                    106:        }
                    107:        return TRUE;
                    108: }
                    109: 
                    110: METHOD(pts_pcr_t, get_selection_size, size_t,
                    111:        private_pts_pcr_t *this)
                    112: {
                    113: 
                    114:        /**
                    115:         * A TPM v1.2 has 24 PCR Registers so the bitmask field length
                    116:         * used by TrouSerS is at least 3 bytes
                    117:         */
                    118:        return PTS_PCR_MAX_NUM / 8;
                    119: }
                    120: 
                    121: typedef struct {
                    122:        /** implements enumerator_t */
                    123:        enumerator_t public;
                    124:        /** current PCR */
                    125:        uint32_t pcr;
                    126:        /** back reference to parent */
                    127:        private_pts_pcr_t *pcrs;
                    128: } pcr_enumerator_t;
                    129: 
                    130: METHOD(enumerator_t, pcr_enumerator_enumerate, bool,
                    131:        pcr_enumerator_t *this, va_list args)
                    132: {
                    133:        uint32_t i, f, *pcr;
                    134: 
                    135:        VA_ARGS_VGET(args, pcr);
                    136: 
                    137:        while (this->pcr <= this->pcrs->pcr_max)
                    138:        {
                    139:                /* Determine PCR selection flag */
                    140:                i = this->pcr / 8;
                    141:                f = 1 << (this->pcr - 8*i);
                    142: 
                    143:                /* Assign current PCR to output argument and increase */
                    144:                *pcr = this->pcr++;
                    145: 
                    146:                /* return if PCR is selected */
                    147:                if (this->pcrs->pcr_select[i] & f)
                    148:                {
                    149:                        return TRUE;
                    150:                }
                    151:        }
                    152:        return FALSE;
                    153: }
                    154: 
                    155: METHOD(pts_pcr_t, create_enumerator, enumerator_t*,
                    156:        private_pts_pcr_t *this)
                    157: {
                    158:        pcr_enumerator_t *enumerator;
                    159: 
                    160:        INIT(enumerator,
                    161:                .public = {
                    162:                        .enumerate = enumerator_enumerate_default,
                    163:                        .venumerate = _pcr_enumerator_enumerate,
                    164:                        .destroy = (void*)free,
                    165:                },
                    166:                .pcrs = this,
                    167:        );
                    168: 
                    169:        return (enumerator_t*)enumerator;
                    170: }
                    171: 
                    172: METHOD(pts_pcr_t, get, chunk_t,
                    173:        private_pts_pcr_t *this, uint32_t pcr)
                    174: {
                    175:        return (pcr < PTS_PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty;
                    176: }
                    177: 
                    178: METHOD(pts_pcr_t, set, bool,
                    179:        private_pts_pcr_t *this, uint32_t pcr, chunk_t value)
                    180: {
1.1.1.2 ! misho     181:        if (value.len != this->pcr_len)
1.1       misho     182:        {
                    183:                DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr);
                    184:                return FALSE;
                    185:        }
                    186:        if (select_pcr(this, pcr))
                    187:        {
1.1.1.2 ! misho     188:                memcpy(this->pcrs[pcr].ptr, value.ptr, this->pcr_len);
1.1       misho     189:                return TRUE;
                    190:        }
                    191:        return FALSE;
                    192: }
                    193: 
                    194: METHOD(pts_pcr_t, extend, chunk_t,
                    195:        private_pts_pcr_t *this, uint32_t pcr, chunk_t measurement)
                    196: {
1.1.1.2 ! misho     197:        if (measurement.len != this->pcr_len)
1.1       misho     198:        {
                    199:                DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr);
                    200:                return chunk_empty;
                    201:        }
                    202:        if (!select_pcr(this, pcr))
                    203:        {
                    204:                return chunk_empty;
                    205:        }
                    206:        if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) ||
                    207:                !this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr))
                    208:        {
                    209:                DBG1(DBG_PTS, "PCR %2u: not extended due to hasher problem", pcr);
                    210:                return chunk_empty;
                    211:        }
                    212:        return this->pcrs[pcr];
                    213: }
                    214: 
                    215: METHOD(pts_pcr_t, get_composite, tpm_tss_pcr_composite_t*,
                    216:        private_pts_pcr_t *this)
                    217: {
                    218:        tpm_tss_pcr_composite_t *pcr_composite;
                    219:        enumerator_t *enumerator;
                    220:        uint16_t selection_size;
                    221:        uint32_t pcr_field_size, pcr;
                    222:        u_char *pos;
                    223: 
                    224:        selection_size = get_selection_size(this);
1.1.1.2 ! misho     225:        pcr_field_size = this->pcr_count * this->pcr_len;
1.1       misho     226: 
                    227:        INIT(pcr_composite,
                    228:                .pcr_select    = chunk_alloc(selection_size),
                    229:                .pcr_composite = chunk_alloc(pcr_field_size),
                    230:        );
                    231: 
                    232:        memcpy(pcr_composite->pcr_select.ptr, this->pcr_select, selection_size);
                    233:        pos = pcr_composite->pcr_composite.ptr;
                    234: 
                    235:        enumerator = create_enumerator(this);
                    236:        while (enumerator->enumerate(enumerator, &pcr))
                    237:        {
1.1.1.2 ! misho     238:                memcpy(pos, this->pcrs[pcr].ptr, this->pcr_len);
        !           239:                pos += this->pcr_len;
1.1       misho     240:        }
                    241:        enumerator->destroy(enumerator);
                    242: 
                    243:        return pcr_composite;
                    244: }
                    245: 
                    246: METHOD(pts_pcr_t, destroy, void,
                    247:        private_pts_pcr_t *this)
                    248: {
                    249:        uint32_t i;
                    250: 
                    251:        for (i = 0; i < PTS_PCR_MAX_NUM; i++)
                    252:        {
                    253:                free(this->pcrs[i].ptr);
                    254:        }
                    255:        this->hasher->destroy(this->hasher);
                    256:        free(this);
                    257: }
                    258: 
                    259: /**
                    260:  * See header
                    261:  */
1.1.1.2 ! misho     262: pts_pcr_t *pts_pcr_create(tpm_version_t tpm_version, pts_meas_algorithms_t algo,
        !           263:                                                  uint8_t locality)
1.1       misho     264: {
                    265:        private_pts_pcr_t *this;
1.1.1.2 ! misho     266:        hash_algorithm_t hash_alg;
1.1       misho     267:        hasher_t *hasher;
                    268:        uint32_t i;
                    269: 
1.1.1.2 ! misho     270:        hash_alg = pts_meas_algo_to_hash(algo);
        !           271:        hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
1.1       misho     272:        if (!hasher)
                    273:        {
                    274:                DBG1(DBG_PTS, "%N hasher could not be created",
1.1.1.2 ! misho     275:                         hash_algorithm_short_names, hash_alg);
1.1       misho     276:                return NULL;
                    277:        }
                    278: 
                    279:        INIT(this,
                    280:                .public = {
1.1.1.2 ! misho     281:                        .get_pcr_algo = _get_pcr_algo,
1.1       misho     282:                        .get_count = _get_count,
                    283:                        .select_pcr = _select_pcr,
                    284:                        .get_selection_size = _get_selection_size,
                    285:                        .create_enumerator = _create_enumerator,
                    286:                        .get = _get,
                    287:                        .set = _set,
                    288:                        .extend = _extend,
                    289:                        .get_composite = _get_composite,
                    290:                        .destroy = _destroy,
                    291:                },
1.1.1.2 ! misho     292:                .pcr_algo = algo,
        !           293:                .pcr_len = pts_meas_algo_hash_size(algo),
1.1       misho     294:                .hasher = hasher,
                    295:        );
                    296: 
                    297:        for (i = 0; i < PTS_PCR_MAX_NUM; i++)
                    298:        {
1.1.1.2 ! misho     299:                this->pcrs[i] = chunk_alloc(this->pcr_len);
        !           300:                memset(this->pcrs[i].ptr, 0x00, this->pcr_len);
        !           301:        }
        !           302: 
        !           303:        /* Set locality indicator in PCR[0] */
        !           304:        if (tpm_version == TPM_VERSION_2_0)
        !           305:        {
        !           306:                DBG2(DBG_PTS, "TPM 2.0 - locality indicator set to %u",
        !           307:                                          (uint32_t)locality);
        !           308:                this->pcrs[0].ptr[this->pcr_len - 1] = locality;
1.1       misho     309:        }
                    310: 
                    311:        return &this->public;
                    312: }
                    313: 

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