Annotation of embedaddon/strongswan/src/libtpmtss/tpm_tss_tss2_v2.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * Copyright (C) 2018 Tobias Brunner
1.1.1.2 ! misho       3:  * Copyright (C) 2018-2020 Andreas Steffen
1.1       misho       4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include "tpm_tss_tss2.h"
                     18: #include "tpm_tss_tss2_names.h"
                     19: 
                     20: #ifdef TSS_TSS2_V2
                     21: 
                     22: #include <asn1/asn1.h>
                     23: #include <asn1/oid.h>
                     24: #include <bio/bio_reader.h>
1.1.1.2 ! misho      25: #include <bio/bio_writer.h>
1.1       misho      26: #include <threading/mutex.h>
                     27: 
                     28: #include <tss2/tss2_sys.h>
                     29: 
                     30: #include <dlfcn.h>
                     31: #include <sys/types.h>
                     32: #include <sys/stat.h>
                     33: #include <unistd.h>
                     34: 
                     35: #define LABEL  "TPM 2.0 -"
                     36: 
                     37: #define PLATFORM_PCR   24
1.1.1.2 ! misho      38: #define MAX_PCR_BANKS   4
1.1       misho      39: 
                     40: typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t;
                     41: 
                     42: /**
                     43:  * Private data of an tpm_tss_tss2_t object.
                     44:  */
                     45: struct private_tpm_tss_tss2_t {
                     46: 
                     47:        /**
                     48:         * Public tpm_tss_tss2_t interface.
                     49:         */
                     50:        tpm_tss_t public;
                     51: 
                     52:        /**
                     53:         * TCTI context
                     54:         */
                     55:        TSS2_TCTI_CONTEXT *tcti_context;
                     56: 
                     57:        /**
                     58:         * SYS context
                     59:         */
                     60:        TSS2_SYS_CONTEXT  *sys_context;
                     61: 
                     62:        /**
1.1.1.2 ! misho      63:         * TPM version info
        !            64:         */
        !            65:        chunk_t version_info;
        !            66: 
        !            67:        /**
1.1       misho      68:         * Number of supported algorithms
                     69:         */
                     70:        size_t supported_algs_count;
                     71: 
                     72:        /**
                     73:         * List of supported algorithms
                     74:         */
                     75:        TPM2_ALG_ID supported_algs[TPM2_PT_ALGORITHM_SET];
                     76: 
                     77:        /**
1.1.1.2 ! misho      78:         * Number of assigned PCR banks
        !            79:         */
        !            80:        size_t assigned_pcrs_count;
        !            81: 
        !            82:        /**
        !            83:         * List of assigned PCR banks
        !            84:         */
        !            85:        TPM2_ALG_ID assigned_pcrs[MAX_PCR_BANKS];
        !            86: 
        !            87:        /**
1.1       misho      88:         * Is TPM FIPS 186-4 compliant ?
                     89:         */
                     90:        bool fips_186_4;
                     91: 
                     92:        /**
1.1.1.2 ! misho      93:         * Does the TPM use the old TCG SHA1-only event digest format
        !            94:         */
        !            95:        bool old_event_digest_format;
        !            96: 
        !            97:        /**
1.1       misho      98:         * Mutex controlling access to the TPM 2.0 context
                     99:         */
                    100:        mutex_t *mutex;
                    101: 
                    102: };
                    103: 
                    104: /**
                    105:  * Global TCTI dynamic library handle and init function
                    106:  */
                    107: static void *tcti_handle;
                    108: 
                    109: static TSS2_TCTI_INIT_FUNC tcti_init;
                    110: 
                    111: static char *tcti_opts;
                    112: 
                    113: /**
                    114:  * Empty AUTH_COMMAND
                    115:  */
                    116: static const TPMS_AUTH_COMMAND auth_cmd_empty;
                    117: 
                    118: /**
                    119:  * Convert hash algorithm to TPM2_ALG_ID
                    120:  */
                    121: static TPM2_ALG_ID hash_alg_to_tpm_alg_id(hash_algorithm_t alg)
                    122: {
                    123:        switch (alg)
                    124:        {
                    125:                case HASH_SHA1:
                    126:                        return TPM2_ALG_SHA1;
                    127:                case HASH_SHA256:
                    128:                        return TPM2_ALG_SHA256;
                    129:                case HASH_SHA384:
                    130:                        return TPM2_ALG_SHA384;
                    131:                case HASH_SHA512:
                    132:                        return TPM2_ALG_SHA512;
1.1.1.2 ! misho     133:                case HASH_SHA3_256:
        !           134:                        return TPM2_ALG_SHA3_256;
        !           135:                case HASH_SHA3_384:
        !           136:                        return TPM2_ALG_SHA3_384;
        !           137:                case HASH_SHA3_512:
        !           138:                        return TPM2_ALG_SHA3_512;
1.1       misho     139:                default:
                    140:                        return TPM2_ALG_ERROR;
                    141:        }
                    142: }
                    143: 
                    144: /**
                    145:  * Convert TPM2_ALG_ID to hash algorithm
                    146:  */
                    147: static hash_algorithm_t hash_alg_from_tpm_alg_id(TPM2_ALG_ID alg)
                    148: {
                    149:        switch (alg)
                    150:        {
                    151:                case TPM2_ALG_SHA1:
                    152:                        return HASH_SHA1;
                    153:                case TPM2_ALG_SHA256:
                    154:                        return HASH_SHA256;
                    155:                case TPM2_ALG_SHA384:
                    156:                        return HASH_SHA384;
                    157:                case TPM2_ALG_SHA512:
                    158:                        return HASH_SHA512;
1.1.1.2 ! misho     159:                case TPM2_ALG_SHA3_256:
        !           160:                        return HASH_SHA3_256;
        !           161:                case TPM2_ALG_SHA3_384:
        !           162:                        return HASH_SHA3_384;
        !           163:                case TPM2_ALG_SHA3_512:
        !           164:                        return HASH_SHA3_512;
1.1       misho     165:                default:
                    166:                        return HASH_UNKNOWN;
                    167:        }
                    168: }
                    169: 
                    170: /**
                    171:  * Check if an algorithm given by its TPM2_ALG_ID is supported by the TPM
                    172:  */
                    173: static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM2_ALG_ID alg_id)
                    174: {
                    175:        int i;
                    176: 
                    177:        if (alg_id == TPM2_ALG_ERROR)
                    178:        {
                    179:                return FALSE;
                    180:        }
                    181: 
                    182:        for (i = 0; i < this->supported_algs_count; i++)
                    183:        {
                    184:                if (this->supported_algs[i] == alg_id)
                    185:                {
                    186:                        return TRUE;
                    187:                }
                    188:        }
                    189: 
                    190:        return FALSE;
                    191: }
                    192: 
                    193: /**
1.1.1.2 ! misho     194:  * Get the TPM version_info and a list of supported algorithms
        !           195:  *
        !           196:  *                                        1                               2                               3
        !           197:  *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        !           198:  *
        !           199:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           200:  *  |  TPM 2.0 Version_Info Tag     |   Reserved    |   Locality    |
        !           201:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           202:  *  |                            Revision                           |
        !           203:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           204:  *  |                              Year                             |
        !           205:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           206:  *  |                             Vendor                            |
        !           207:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1.1       misho     208:  */
1.1.1.2 ! misho     209: #define TPM2_VERSION_INFO_TAG       0x0200
        !           210: #define TPM2_VERSION_INFO_RESERVED  0x00
        !           211: #define TPM2_VERSION_INFO_SIZE      16
        !           212: #define TPM2_DEFAULT_LOCALITY       3
        !           213: 
1.1       misho     214: static bool get_algs_capability(private_tpm_tss_tss2_t *this)
                    215: {
                    216:        TPMS_CAPABILITY_DATA cap_data;
                    217:        TPMS_TAGGED_PROPERTY tp;
                    218:        TPMI_YES_NO more_data;
                    219:        TPM2_ALG_ID alg;
1.1.1.2 ! misho     220:        bio_writer_t *writer;
1.1       misho     221:        bool fips_140_2 = FALSE;
1.1.1.2 ! misho     222:        uint32_t rval, i, offset, revision = 0, year = 0, vendor = 0;
        !           223:        uint8_t locality = TPM2_DEFAULT_LOCALITY;
1.1       misho     224:        size_t len = BUF_LEN;
                    225:        char buf[BUF_LEN], manufacturer[5], vendor_string[17];
                    226:        char *pos = buf;
                    227:        int written;
                    228: 
                    229:        /* get fixed properties */
                    230:        this->mutex->lock(this->mutex);
                    231:        rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
                    232:                                                                  TPM2_PT_FIXED, TPM2_MAX_TPM_PROPERTIES,
                    233:                                                                  &more_data, &cap_data, 0);
                    234:        this->mutex->unlock(this->mutex);
                    235:        if (rval != TPM2_RC_SUCCESS)
                    236:        {
                    237:                DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_TPM_PROPERTIES: 0x%06x",
                    238:                                           LABEL, rval);
                    239:                return FALSE;
                    240:        }
                    241:        memset(manufacturer,  '\0', sizeof(manufacturer));
                    242:        memset(vendor_string, '\0', sizeof(vendor_string));
                    243: 
                    244:        /* print fixed properties */
                    245:        for (i = 0; i < cap_data.data.tpmProperties.count; i++)
                    246:        {
                    247:                tp = cap_data.data.tpmProperties.tpmProperty[i];
                    248:                switch (tp.property)
                    249:                {
                    250:                        case TPM2_PT_REVISION:
                    251:                                revision = tp.value;
                    252:                                break;
                    253:                        case TPM2_PT_YEAR:
                    254:                                year = tp.value;
                    255:                                break;
                    256:                        case TPM2_PT_MANUFACTURER:
1.1.1.2 ! misho     257:                                vendor = tp.value;
1.1       misho     258:                                htoun32(manufacturer, tp.value);
                    259:                                break;
                    260:                        case TPM2_PT_VENDOR_STRING_1:
                    261:                        case TPM2_PT_VENDOR_STRING_2:
                    262:                        case TPM2_PT_VENDOR_STRING_3:
                    263:                        case TPM2_PT_VENDOR_STRING_4:
                    264:                                offset = 4 * (tp.property - TPM2_PT_VENDOR_STRING_1);
                    265:                                htoun32(vendor_string + offset, tp.value);
                    266:                                break;
                    267:                        case TPM2_PT_MODES:
                    268:                                if (tp.value & TPMA_MODES_FIPS_140_2)
                    269:                                {
                    270:                                        this->fips_186_4 = fips_140_2 = TRUE;
                    271:                                }
                    272:                                break;
                    273:                        default:
                    274:                                break;
                    275:                }
                    276:        }
                    277: 
                    278:        if (!fips_140_2)
                    279:        {
                    280:                this->fips_186_4 = lib->settings->get_bool(lib->settings,
                    281:                                        "%s.plugins.tpm.fips_186_4", FALSE, lib->ns);
                    282:        }
                    283:        DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u %s", LABEL,
                    284:                 manufacturer, vendor_string, (float)revision/100, year,
                    285:                 fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : ""));
                    286: 
1.1.1.2 ! misho     287:        /* determine if TPM uses old event digest format and a different locality */
        !           288:        if (streq(manufacturer, "INTC"))
        !           289:        {
        !           290:                locality = 0;
        !           291: 
        !           292:                if (revision == 116 && year == 2016)
        !           293:                {
        !           294:                        this->old_event_digest_format = TRUE;
        !           295:                }
        !           296:        }
        !           297: 
        !           298:        /* construct TPM 2.0 version_info object */
        !           299:        writer = bio_writer_create(  TPM2_VERSION_INFO_SIZE);
        !           300:        writer->write_uint16(writer, TPM2_VERSION_INFO_TAG);
        !           301:        writer->write_uint8(writer,  TPM2_VERSION_INFO_RESERVED);
        !           302:        writer->write_uint8(writer,  locality);
        !           303:        writer->write_uint32(writer, revision);
        !           304:        writer->write_uint32(writer, year);
        !           305:        writer->write_uint32(writer, vendor);
        !           306:        this->version_info = writer->extract_buf(writer);
        !           307:        writer->destroy(writer);
        !           308: 
1.1       misho     309:        /* get supported algorithms */
                    310:        this->mutex->lock(this->mutex);
                    311:        rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ALGS,
                    312:                                                0, TPM2_PT_ALGORITHM_SET, &more_data, &cap_data, 0);
                    313:        this->mutex->unlock(this->mutex);
                    314:        if (rval != TPM2_RC_SUCCESS)
                    315:        {
                    316:                DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_ALGS: 0x%06x",
                    317:                                           LABEL, rval);
                    318:                return FALSE;
                    319:        }
                    320: 
                    321:        /* Number of supported algorithms */
                    322:        this->supported_algs_count = cap_data.data.algorithms.count;
                    323: 
                    324:        /* store and print supported algorithms */
                    325:        for (i = 0; i < this->supported_algs_count; i++)
                    326:        {
                    327:                alg = cap_data.data.algorithms.algProperties[i].alg;
                    328:                this->supported_algs[i] = alg;
                    329: 
                    330:                written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
                    331:                if (written < 0 || written >= len)
                    332:                {
                    333:                        break;
                    334:                }
                    335:                pos += written;
                    336:                len -= written;
                    337:        }
                    338:        DBG2(DBG_PTS, "%s algorithms:%s", LABEL, buf);
                    339: 
                    340:        /* get supported ECC curves */
                    341:        this->mutex->lock(this->mutex);
                    342:        rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ECC_CURVES,
                    343:                                                0, TPM2_PT_LOADED_CURVES, &more_data, &cap_data, 0);
                    344:        this->mutex->unlock(this->mutex);
                    345:        if (rval != TPM2_RC_SUCCESS)
                    346:        {
1.1.1.2 ! misho     347:                DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_ECC_CURVES: 0x%06x",
1.1       misho     348:                                           LABEL, rval);
                    349:                return FALSE;
                    350:        }
                    351: 
                    352:        /* reset print buffer */
                    353:        pos = buf;
                    354:        len = BUF_LEN;
                    355: 
                    356:        /* print supported ECC curves */
                    357:        for (i = 0; i < cap_data.data.eccCurves.count; i++)
                    358:        {
                    359:                written = snprintf(pos, len, " %N", tpm_ecc_curve_names,
                    360:                                                   cap_data.data.eccCurves.eccCurves[i]);
                    361:                if (written < 0 || written >= len)
                    362:                {
                    363:                        break;
                    364:                }
                    365:                pos += written;
                    366:                len -= written;
                    367:        }
                    368:        DBG2(DBG_PTS, "%s ECC curves:%s", LABEL, buf);
                    369: 
1.1.1.2 ! misho     370:        /* get assigned PCR banks */
        !           371:        this->mutex->lock(this->mutex);
        !           372:        rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_PCRS,
        !           373:                                                0, MAX_PCR_BANKS, &more_data, &cap_data, 0);
        !           374:        this->mutex->unlock(this->mutex);
        !           375:        if (rval != TPM2_RC_SUCCESS)
        !           376:        {
        !           377:                DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_PCRS: 0x%06x",
        !           378:                                           LABEL, rval);
        !           379:                return FALSE;
        !           380:        }
        !           381: 
        !           382:        /* Number of assigned PCR banks */
        !           383:        this->assigned_pcrs_count = cap_data.data.assignedPCR.count;
        !           384: 
        !           385:        /* reset print buffer */
        !           386:        pos = buf;
        !           387:        len = BUF_LEN;
        !           388: 
        !           389:        /* store and print assigned PCR banks */
        !           390:        for (i = 0; i < cap_data.data.assignedPCR.count; i++)
        !           391:        {
        !           392:                alg = cap_data.data.assignedPCR.pcrSelections[i].hash;
        !           393:                this->assigned_pcrs[i] = alg;
        !           394:                written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
        !           395:                if (written < 0 || written >= len)
        !           396:                {
        !           397:                        break;
        !           398:                }
        !           399:                pos += written;
        !           400:                len -= written;
        !           401:        }
        !           402:        DBG2(DBG_PTS, "%s PCR banks:%s", LABEL, buf);
        !           403: 
1.1       misho     404:        return TRUE;
                    405: }
                    406: 
                    407: /**
                    408:  * Initialize TSS2 TCTI context
                    409:  */
                    410: static bool initialize_tcti_context(private_tpm_tss_tss2_t *this)
                    411: {
                    412:        size_t tcti_context_size;
                    413:        uint32_t rval;
                    414: 
                    415:        if (!tcti_init)
                    416:        {
                    417:                return FALSE;
                    418:        }
                    419: 
                    420:        /* determine size of tcti context */
                    421:        rval = tcti_init(NULL, &tcti_context_size, tcti_opts);
                    422:        if (rval != TSS2_RC_SUCCESS)
                    423:        {
                    424:                DBG1(DBG_PTS, "%s tcti init setup failed: 0x%06x",  LABEL, rval);
                    425:                return FALSE;
                    426:        }
                    427: 
                    428:        /* allocate and initialize memory for tcti context */
                    429:        this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
                    430:        memset(this->tcti_context, 0x00, tcti_context_size);
                    431: 
                    432:        /* initialize tcti context */
                    433:        rval = tcti_init(this->tcti_context, &tcti_context_size, tcti_opts);
                    434:        if (rval != TSS2_RC_SUCCESS)
                    435:        {
                    436:                DBG1(DBG_PTS, "%s tcti init allocation failed: 0x%06x", LABEL,rval);
                    437:                return FALSE;
                    438:        }
                    439:        return TRUE;
                    440: }
                    441: 
                    442: /**
                    443:  * Initialize TSS2 Sys context
                    444:  */
                    445: static bool initialize_sys_context(private_tpm_tss_tss2_t *this)
                    446: {
                    447:        uint32_t sys_context_size;
                    448:        uint32_t rval;
                    449: 
                    450:        TSS2_ABI_VERSION abi_version = {
                    451:                .tssCreator = 1,
                    452:        .tssFamily = 2,
                    453:        .tssLevel = 1,
                    454:        .tssVersion = 108
                    455:        };
                    456: 
                    457:        /* determine size of sys context */
                    458:        sys_context_size = Tss2_Sys_GetContextSize(0);
                    459: 
                    460:        /* allocate memory for sys context */
                    461:        this->sys_context = (TSS2_SYS_CONTEXT*)malloc(sys_context_size);
                    462: 
                    463:        /* initialize sys context */
                    464:        rval = Tss2_Sys_Initialize(this->sys_context, sys_context_size,
                    465:                                                           this->tcti_context, &abi_version);
                    466:        if (rval != TSS2_RC_SUCCESS)
                    467:        {
                    468:                DBG1(DBG_PTS, "%s could not get sys_context: 0x%06x",
                    469:                                           LABEL, rval);
                    470:                return FALSE;
                    471:        }
                    472: 
                    473:        /* get a list of supported algorithms and ECC curves */
                    474:        return get_algs_capability(this);
                    475: }
                    476: 
                    477: /**
                    478:  * Finalize TSS context
                    479:  */
                    480: static void finalize_context(private_tpm_tss_tss2_t *this)
                    481: {
                    482:        if (this->tcti_context)
                    483:        {
                    484:                Tss2_Tcti_Finalize(this->tcti_context);
                    485:                free(this->tcti_context);
                    486:        }
                    487:        if (this->sys_context)
                    488:        {
                    489:                Tss2_Sys_Finalize(this->sys_context);
                    490:                free(this->sys_context);
                    491:        }
                    492: }
                    493: 
                    494: METHOD(tpm_tss_t, get_version, tpm_version_t,
                    495:        private_tpm_tss_tss2_t *this)
                    496: {
                    497:        return TPM_VERSION_2_0;
                    498: }
                    499: 
                    500: METHOD(tpm_tss_t, get_version_info, chunk_t,
                    501:        private_tpm_tss_tss2_t *this)
                    502: {
1.1.1.2 ! misho     503:        return this->version_info;
1.1       misho     504: }
                    505: 
                    506: /**
                    507:  * read the public key portion of a TSS 2.0 key from NVRAM
                    508:  */
                    509: bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
                    510:        TPM2B_PUBLIC *public)
                    511: {
                    512:        uint32_t rval;
                    513: 
                    514:        TPM2B_NAME name = { sizeof(TPM2B_NAME)-2, };
                    515:        TPM2B_NAME qualified_name = { sizeof(TPM2B_NAME)-2, };
                    516:        TSS2L_SYS_AUTH_RESPONSE auth_rsp;
                    517: 
                    518: 
                    519:        /* read public key for a given object handle from TPM 2.0 NVRAM */
                    520:        this->mutex->lock(this->mutex);
                    521:        rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name,
                    522:                                                           &qualified_name, &auth_rsp);
                    523:        this->mutex->unlock(this->mutex);
                    524:        if (rval != TPM2_RC_SUCCESS)
                    525:        {
                    526:                DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x",
                    527:                                           LABEL, handle, rval);
                    528:                return FALSE;
                    529:        }
                    530:        return TRUE;
                    531: }
                    532: 
                    533: METHOD(tpm_tss_t, generate_aik, bool,
                    534:        private_tpm_tss_tss2_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
                    535:        chunk_t *aik_pubkey, chunk_t *identity_req)
                    536: {
                    537:        return FALSE;
                    538: }
                    539: 
                    540: METHOD(tpm_tss_t, get_public, chunk_t,
                    541:        private_tpm_tss_tss2_t *this, uint32_t handle)
                    542: {
                    543:        TPM2B_PUBLIC public = { 0, };
                    544:        TPM2_ALG_ID sig_alg, digest_alg;
1.1.1.2 ! misho     545:        chunk_t aik_pubkey = chunk_empty;
1.1       misho     546: 
                    547:        if (!read_public(this, handle, &public))
                    548:        {
                    549:                return chunk_empty;
                    550:        }
                    551: 
                    552:        /* convert TSS 2.0 public key blot into PKCS#1 format */
                    553:        switch (public.publicArea.type)
                    554:        {
                    555:                case TPM2_ALG_RSA:
                    556:                {
                    557:                        TPM2B_PUBLIC_KEY_RSA *rsa;
                    558:                        TPMT_RSA_SCHEME *scheme;
                    559:                        chunk_t aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
                    560:                        chunk_t aik_modulus;
                    561:                        uint32_t exponent;
                    562: 
                    563:                        scheme = &public.publicArea.parameters.rsaDetail.scheme;
                    564:                        sig_alg   = scheme->scheme;
                    565:                        digest_alg = scheme->details.anySig.hashAlg;
                    566: 
                    567:                        rsa = &public.publicArea.unique.rsa;
                    568:                        aik_modulus = chunk_create(rsa->buffer, rsa->size);
                    569:                        exponent = htonl(public.publicArea.parameters.rsaDetail.exponent);
                    570:                        if (exponent)
                    571:                        {
                    572:                                aik_exponent = chunk_from_thing(exponent);
                    573:                        }
                    574: 
                    575:                        /* subjectPublicKeyInfo encoding of RSA public key */
                    576:                        if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
                    577:                                        NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
                    578:                                        CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
                    579:                        {
                    580:                                DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of public key "
                    581:                                                          "failed", LABEL);
                    582:                                return chunk_empty;
                    583:                        }
                    584:                        break;
                    585:                }
                    586:                case TPM2_ALG_ECC:
                    587:                {
                    588:                        TPMS_ECC_POINT *ecc;
                    589:                        TPMT_ECC_SCHEME *scheme;
                    590:                        chunk_t ecc_point;
                    591:                        uint8_t *pos;
                    592: 
                    593:                        scheme = &public.publicArea.parameters.eccDetail.scheme;
                    594:                        sig_alg   = scheme->scheme;
                    595:                        digest_alg = scheme->details.anySig.hashAlg;
                    596: 
                    597:                        ecc = &public.publicArea.unique.ecc;
                    598: 
                    599:                        /* allocate space for bit string */
                    600:                        pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
                    601:                                                                        2 + ecc->x.size + ecc->y.size);
                    602:                        /* bit string length is a multiple of octets */
                    603:                        *pos++ = 0x00;
                    604:                        /* uncompressed ECC point format */
                    605:                        *pos++ = 0x04;
                    606:                        /* copy x coordinate of ECC point */
                    607:                        memcpy(pos, ecc->x.buffer, ecc->x.size);
                    608:                        pos += ecc->x.size;
                    609:                        /* copy y coordinate of ECC point */
                    610:                        memcpy(pos, ecc->y.buffer, ecc->y.size);
                    611:                        /* subjectPublicKeyInfo encoding of ECC public key */
                    612:                        aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
                    613:                                                        asn1_wrap(ASN1_SEQUENCE, "mm",
                    614:                                                                asn1_build_known_oid(OID_EC_PUBLICKEY),
                    615:                                                                asn1_build_known_oid(ecc->x.size == 32 ?
                    616:                                                                                OID_PRIME256V1 : OID_SECT384R1)),
                    617:                                                        ecc_point);
                    618:                        break;
                    619:                }
                    620:                default:
                    621:                        DBG1(DBG_PTS, "%s unsupported key type", LABEL);
                    622:                        return chunk_empty;
                    623:        }
                    624:        DBG1(DBG_PTS, "signature algorithm is %N with %N hash",
                    625:                 tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
                    626:        return aik_pubkey;
                    627: }
                    628: 
                    629: METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
                    630:        private_tpm_tss_tss2_t *this, uint32_t handle)
                    631: {
                    632:        TPM2B_PUBLIC public = { 0, };
                    633:        hash_algorithm_t digest;
                    634:        signature_params_t supported_scheme;
                    635: 
                    636:        if (!read_public(this, handle, &public))
                    637:        {
                    638:                return enumerator_create_empty();
                    639:        }
                    640: 
                    641:        switch (public.publicArea.type)
                    642:        {
                    643:                case TPM2_ALG_RSA:
                    644:                {
                    645:                        TPMS_RSA_PARMS *rsa;
                    646:                        TPMT_RSA_SCHEME *scheme;
                    647: 
                    648:                        rsa = &public.publicArea.parameters.rsaDetail;
                    649:                        scheme = &rsa->scheme;
                    650:                        digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
                    651: 
                    652:                        switch (scheme->scheme)
                    653:                        {
                    654:                                case TPM2_ALG_RSAPSS:
                    655:                                {
                    656:                                        ssize_t salt_len;
                    657: 
                    658:                                        salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT :
                    659:                                                                                                  RSA_PSS_SALT_LEN_MAX;
                    660:                                        rsa_pss_params_t pss_params = {
                    661:                                                .hash = digest,
                    662:                                                .mgf1_hash = digest,
                    663:                                                .salt_len = salt_len,
                    664:                                        };
                    665:                                        supported_scheme = (signature_params_t){
                    666:                                                .scheme = SIGN_RSA_EMSA_PSS,
                    667:                                                .params = &pss_params,
                    668:                                        };
                    669:                                        if (!rsa_pss_params_set_salt_len(&pss_params, rsa->keyBits))
                    670:                                        {
                    671:                                                return enumerator_create_empty();
                    672:                                        }
                    673:                                        break;
                    674:                                }
                    675:                                case TPM2_ALG_RSASSA:
                    676:                                        supported_scheme = (signature_params_t){
                    677:                                                .scheme = signature_scheme_from_oid(
                    678:                                                                        hasher_signature_algorithm_to_oid(digest,
                    679:                                                                                                                                          KEY_RSA)),
                    680:                                        };
                    681:                                        break;
                    682:                                default:
                    683:                                        return enumerator_create_empty();
                    684:                        }
                    685:                        break;
                    686:                }
                    687:                case TPM2_ALG_ECC:
                    688:                {
                    689:                        TPMT_ECC_SCHEME *scheme;
                    690: 
                    691:                        scheme = &public.publicArea.parameters.eccDetail.scheme;
                    692:                        digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
                    693: 
                    694:                        switch (scheme->scheme)
                    695:                        {
                    696:                                case TPM2_ALG_ECDSA:
                    697:                                        supported_scheme = (signature_params_t){
                    698:                                                .scheme = signature_scheme_from_oid(
                    699:                                                                        hasher_signature_algorithm_to_oid(digest,
                    700:                                                                                                                                        KEY_ECDSA)),
                    701:                                        };
                    702:                                        break;
                    703:                                default:
                    704:                                        return enumerator_create_empty();
                    705:                        }
                    706:                        break;
                    707:                }
                    708:                default:
                    709:                        DBG1(DBG_PTS, "%s unsupported key type", LABEL);
                    710:                        return enumerator_create_empty();
                    711:        }
                    712:        return enumerator_create_single(signature_params_clone(&supported_scheme),
                    713:                                                                        (void*)signature_params_destroy);
                    714: }
                    715: 
1.1.1.2 ! misho     716: METHOD(tpm_tss_t, has_pcr_bank, bool,
        !           717:        private_tpm_tss_tss2_t *this, hash_algorithm_t alg)
        !           718: {
        !           719:        TPM2_ALG_ID alg_id;
        !           720:        int i;
        !           721: 
        !           722:        alg_id = hash_alg_to_tpm_alg_id(alg);
        !           723: 
        !           724:        for (i = 0; i < this->assigned_pcrs_count; i++)
        !           725:        {
        !           726:                if (this->assigned_pcrs[i] == alg_id)
        !           727:                {
        !           728:                        return TRUE;
        !           729:                }
        !           730:        }
        !           731: 
        !           732:        return FALSE;
        !           733: }
        !           734: 
1.1       misho     735: /**
                    736:  * Configure a PCR Selection assuming a maximum of 24 registers
                    737:  */
                    738: static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
                    739:                                                           hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
                    740: {
                    741:        uint32_t pcr;
                    742: 
1.1.1.2 ! misho     743:        /* check if there is an assigned PCR bank for this hash algorithm */
        !           744:        if (!has_pcr_bank(this, alg))
1.1       misho     745:        {
1.1.1.2 ! misho     746:                DBG1(DBG_PTS, "%s %N hash algorithm not supported by any PCR bank",
1.1       misho     747:                         LABEL, hash_algorithm_short_names, alg);
                    748:                return FALSE;
                    749:        }
                    750: 
                    751:        /* initialize the PCR Selection structure,*/
                    752:        pcr_sel->count = 1;
1.1.1.2 ! misho     753:        pcr_sel->pcrSelections[0].hash = hash_alg_to_tpm_alg_id(alg);
        !           754: ;
1.1       misho     755:        pcr_sel->pcrSelections[0].sizeofSelect = 3;
                    756:        pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
                    757:        pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
                    758:        pcr_sel->pcrSelections[0].pcrSelect[2] = 0;
                    759: 
                    760:        /* set the selected PCRs */
                    761:        for (pcr = 0; pcr < PLATFORM_PCR; pcr++)
                    762:        {
                    763:                if (pcrs & (1 << pcr))
                    764:                {
                    765:                        pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) );
                    766:                }
                    767:        }
                    768:        return TRUE;
                    769: }
                    770: 
                    771: METHOD(tpm_tss_t, read_pcr, bool,
                    772:        private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
                    773:        hash_algorithm_t alg)
                    774: {
                    775:        TPML_PCR_SELECTION pcr_selection;
                    776:        TPML_DIGEST pcr_values;
                    777: 
                    778:        uint32_t pcr_update_counter, rval;
                    779:        uint8_t *pcr_value_ptr;
                    780:        size_t   pcr_value_len;
                    781: 
                    782:        if (pcr_num >= PLATFORM_PCR)
                    783:        {
                    784:                DBG1(DBG_PTS, "%s maximum number of supported PCR is %d",
                    785:                                           LABEL, PLATFORM_PCR);
                    786:                return FALSE;
                    787:        }
                    788: 
                    789:        if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection))
                    790:        {
                    791:                return FALSE;
                    792:        }
                    793: 
                    794:        /* initialize the PCR Digest structure */
                    795:        memset(&pcr_values, 0, sizeof(TPML_DIGEST));
                    796: 
                    797:        /* read the PCR value */
                    798:        this->mutex->lock(this->mutex);
                    799:        rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection,
                    800:                                &pcr_update_counter, &pcr_selection, &pcr_values, 0);
                    801:        this->mutex->unlock(this->mutex);
                    802:        if (rval != TPM2_RC_SUCCESS)
                    803:        {
                    804:                DBG1(DBG_PTS, "%s PCR bank could not be read: 0x%60x",
                    805:                                           LABEL, rval);
                    806:                return FALSE;
                    807:        }
                    808:        pcr_value_ptr = (uint8_t *)pcr_values.digests[0].buffer;
                    809:        pcr_value_len = (size_t)   pcr_values.digests[0].size;
                    810: 
                    811:        *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len));
                    812: 
                    813:        return TRUE;
                    814: }
                    815: 
                    816: METHOD(tpm_tss_t, extend_pcr, bool,
                    817:        private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
                    818:        chunk_t data, hash_algorithm_t alg)
                    819: {
                    820:        uint32_t rval;
                    821:        TPML_DIGEST_VALUES digest_values;
                    822:        TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
                    823:        TSS2L_SYS_AUTH_RESPONSE auth_rsp;
                    824: 
                    825:        auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
                    826: 
1.1.1.2 ! misho     827:        /* check if there is an assigned PCR bank for this hash algorithm */
        !           828:        if (!has_pcr_bank(this, alg))
1.1       misho     829:        {
1.1.1.2 ! misho     830:                DBG1(DBG_PTS, "%s %N hash algorithm not supported by any PCR bank",
1.1       misho     831:                         LABEL, hash_algorithm_short_names, alg);
                    832:                return FALSE;
                    833:        }
                    834: 
                    835:        digest_values.count = 1;
1.1.1.2 ! misho     836:        digest_values.digests[0].hashAlg = hash_alg_to_tpm_alg_id(alg);
1.1       misho     837: 
                    838:        switch (alg)
                    839:        {
                    840:                case HASH_SHA1:
                    841:                        if (data.len != HASH_SIZE_SHA1)
                    842:                        {
                    843:                                return FALSE;
                    844:                        }
                    845:                        memcpy(digest_values.digests[0].digest.sha1, data.ptr,
                    846:                                   HASH_SIZE_SHA1);
                    847:                        break;
                    848:                case HASH_SHA256:
1.1.1.2 ! misho     849:                case HASH_SHA3_256:
1.1       misho     850:                        if (data.len != HASH_SIZE_SHA256)
                    851:                        {
                    852:                                return FALSE;
                    853:                        }
                    854:                        memcpy(digest_values.digests[0].digest.sha256, data.ptr,
                    855:                                    HASH_SIZE_SHA256);
                    856:                        break;
                    857:                case HASH_SHA384:
1.1.1.2 ! misho     858:                case HASH_SHA3_384:
1.1       misho     859:                        if (data.len != HASH_SIZE_SHA384)
                    860:                        {
                    861:                                return FALSE;
                    862:                        }
                    863:                        memcpy(digest_values.digests[0].digest.sha384, data.ptr,
                    864:                                    HASH_SIZE_SHA384);
                    865:                        break;
                    866:                case HASH_SHA512:
1.1.1.2 ! misho     867:                case HASH_SHA3_512:
1.1       misho     868:                        if (data.len != HASH_SIZE_SHA512)
                    869:                        {
                    870:                                return FALSE;
                    871:                        }
                    872:                        memcpy(digest_values.digests[0].digest.sha512, data.ptr,
                    873:                                    HASH_SIZE_SHA512);
                    874:                        break;
                    875:                default:
                    876:                        return FALSE;
                    877:        }
                    878: 
                    879:        /* extend PCR */
                    880:        this->mutex->lock(this->mutex);
                    881:        rval = Tss2_Sys_PCR_Extend(this->sys_context, pcr_num, &auth_cmd,
                    882:                                                           &digest_values, &auth_rsp);
                    883:        this->mutex->unlock(this->mutex);
                    884:        if (rval != TPM2_RC_SUCCESS)
                    885:        {
                    886:                DBG1(DBG_PTS, "%s PCR %02u could not be extended: 0x%06x",
                    887:                         LABEL, pcr_num, rval);
                    888:                return FALSE;
                    889:        }
                    890: 
                    891:        /* get updated PCR value */
                    892:        return read_pcr(this, pcr_num, pcr_value, alg);
                    893: }
                    894: 
                    895: METHOD(tpm_tss_t, quote, bool,
                    896:        private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel,
                    897:        hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
                    898:        tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
                    899: {
                    900:        chunk_t quoted_chunk, qualified_signer, extra_data, clock_info,
                    901:                        firmware_version, pcr_select, pcr_digest;
                    902:        hash_algorithm_t pcr_digest_alg;
                    903:        bio_reader_t *reader;
                    904:        uint32_t rval;
                    905: 
                    906:        TPM2B_DATA qualifying_data;
                    907:        TPML_PCR_SELECTION  pcr_selection;
                    908:        TPM2B_ATTEST quoted = { sizeof(TPM2B_ATTEST)-2, };
                    909:        TPMT_SIG_SCHEME scheme;
                    910:        TPMT_SIGNATURE sig;
                    911:        TPMI_ALG_HASH hash_alg;
                    912:        TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
                    913:        TSS2L_SYS_AUTH_RESPONSE auth_rsp;
                    914: 
                    915:        auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
                    916: 
                    917:        qualifying_data.size = data.len;
                    918:        memcpy(qualifying_data.buffer, data.ptr, data.len);
                    919: 
                    920:        scheme.scheme = TPM2_ALG_NULL;
                    921:        memset(&sig, 0x00, sizeof(sig));
                    922: 
                    923:        /* set Quote mode */
                    924:        *quote_mode = TPM_QUOTE_TPM2;
                    925: 
                    926:        if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection))
                    927:        {
                    928:                return FALSE;
                    929:        }
                    930: 
                    931:        this->mutex->lock(this->mutex);
                    932:        rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &auth_cmd,
                    933:                                                  &qualifying_data, &scheme, &pcr_selection,  &quoted,
                    934:                                                  &sig, &auth_rsp);
                    935:        this->mutex->unlock(this->mutex);
                    936:        if (rval != TPM2_RC_SUCCESS)
                    937:        {
                    938:                DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval);
                    939:                return FALSE;
                    940:        }
                    941:        quoted_chunk = chunk_create(quoted.attestationData, quoted.size);
                    942: 
                    943:        reader = bio_reader_create(chunk_skip(quoted_chunk, 6));
                    944:        if (!reader->read_data16(reader, &qualified_signer) ||
                    945:                !reader->read_data16(reader, &extra_data) ||
                    946:                !reader->read_data  (reader, 17, &clock_info) ||
                    947:                !reader->read_data  (reader,  8, &firmware_version) ||
                    948:                !reader->read_data  (reader, 10, &pcr_select) ||
                    949:                !reader->read_data16(reader, &pcr_digest))
                    950:        {
                    951:                DBG1(DBG_PTS, "%s parsing of quoted struct failed", LABEL);
                    952:                reader->destroy(reader);
                    953:                return FALSE;
                    954:        }
                    955:        reader->destroy(reader);
                    956: 
                    957:        DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest);
                    958:        DBG2(DBG_PTS, "TPM Quote Info: %B", &quoted_chunk);
                    959:        DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer);
                    960:        DBG2(DBG_PTS, "extraData: %B", &extra_data);
                    961:        DBG2(DBG_PTS, "clockInfo: %B", &clock_info);
                    962:        DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version);
                    963:        DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select);
                    964: 
                    965:        /* extract signature */
                    966:        switch (sig.sigAlg)
                    967:        {
                    968:                case TPM2_ALG_RSASSA:
                    969:                case TPM2_ALG_RSAPSS:
                    970:                        *quote_sig = chunk_clone(
                    971:                                                        chunk_create(
                    972:                                                                sig.signature.rsassa.sig.buffer,
                    973:                                                                sig.signature.rsassa.sig.size));
                    974:                        hash_alg = sig.signature.rsassa.hash;
                    975:                        break;
                    976:                case TPM2_ALG_ECDSA:
                    977:                case TPM2_ALG_ECDAA:
                    978:                case TPM2_ALG_SM2:
                    979:                case TPM2_ALG_ECSCHNORR:
                    980:                        *quote_sig = chunk_cat("cc",
                    981:                                                        chunk_create(
                    982:                                                                sig.signature.ecdsa.signatureR.buffer,
                    983:                                                                sig.signature.ecdsa.signatureR.size),
                    984:                                                        chunk_create(
                    985:                                                                sig.signature.ecdsa.signatureS.buffer,
                    986:                                                                sig.signature.ecdsa.signatureS.size));
                    987:                        hash_alg = sig.signature.ecdsa.hash;
                    988:                        break;
                    989:                default:
                    990:                        DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
                    991:                                                   LABEL, tpm_alg_id_names, sig.sigAlg);
                    992:                        return FALSE;
                    993:        }
                    994: 
                    995:        DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
                    996:        pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
                    997: 
                    998:        DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
                    999: 
                   1000:        /* Create and initialize Quote Info object */
                   1001:        *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg,
                   1002:                                                                                                                 pcr_digest);
                   1003:        (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info,
                   1004:                                                                                                                 pcr_select);
                   1005:        (*quote_info)->set_version_info(*quote_info, firmware_version);
                   1006: 
                   1007:        return TRUE;
                   1008: }
                   1009: 
                   1010: METHOD(tpm_tss_t, sign, bool,
                   1011:        private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
                   1012:        signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
                   1013:        chunk_t *signature)
                   1014: {
                   1015:        key_type_t key_type;
                   1016:        hash_algorithm_t hash_alg;
                   1017:        rsa_pss_params_t *rsa_pss_params;
                   1018:        uint32_t rval;
                   1019: 
                   1020:        TPM2_ALG_ID alg_id;
                   1021:        TPM2B_MAX_BUFFER buffer;
                   1022:        TPM2B_DIGEST hash = { sizeof(TPM2B_DIGEST)-2, };
                   1023:        TPMT_TK_HASHCHECK validation;
                   1024:        TPM2B_PUBLIC public = { 0, };
                   1025:        TPMT_SIG_SCHEME sig_scheme;
                   1026:        TPMT_SIGNATURE sig;
                   1027:        TPMS_AUTH_COMMAND *cmd;
                   1028:        TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
                   1029:        TSS2L_SYS_AUTH_RESPONSE auth_rsp;
                   1030: 
                   1031:        cmd = &auth_cmd.auths[0];
                   1032:        cmd->sessionHandle = TPM2_RS_PW;
                   1033: 
                   1034:        if (pin.len > 0)
                   1035:        {
                   1036:                cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
                   1037:                memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
                   1038:        }
                   1039: 
                   1040:        if (scheme == SIGN_RSA_EMSA_PSS)
                   1041:        {
                   1042:                key_type = KEY_RSA;
                   1043:                rsa_pss_params = (rsa_pss_params_t *)params;
                   1044:                hash_alg = rsa_pss_params->hash;
                   1045:        }
                   1046:        else
                   1047:        {
                   1048:                key_type = key_type_from_signature_scheme(scheme);
                   1049:                hash_alg = hasher_from_signature_scheme(scheme, NULL);
                   1050:        }
                   1051: 
                   1052:        /* Check if hash algorithm is supported by TPM */
                   1053:        alg_id = hash_alg_to_tpm_alg_id(hash_alg);
                   1054:        if (!is_supported_alg(this, alg_id))
                   1055:        {
                   1056:                DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
                   1057:                         LABEL, hash_algorithm_short_names, hash_alg);
                   1058:                return FALSE;
                   1059:        }
                   1060: 
                   1061:        /* Get public key */
                   1062:        if (!read_public(this, handle, &public))
                   1063:        {
                   1064:                return FALSE;
                   1065:        }
                   1066: 
                   1067:        if (key_type == KEY_RSA && public.publicArea.type == TPM2_ALG_RSA)
                   1068:        {
                   1069:                if (scheme == SIGN_RSA_EMSA_PSS)
                   1070:                {
                   1071:                        sig_scheme.scheme = TPM2_ALG_RSAPSS;
                   1072:                        sig_scheme.details.rsapss.hashAlg = alg_id;
                   1073:                }
                   1074:                else
                   1075:                {
                   1076:                        sig_scheme.scheme = TPM2_ALG_RSASSA;
                   1077:                        sig_scheme.details.rsassa.hashAlg = alg_id;
                   1078:                }
                   1079:        }
                   1080:        else if (key_type == KEY_ECDSA && public.publicArea.type == TPM2_ALG_ECC)
                   1081:        {
                   1082:                sig_scheme.scheme = TPM2_ALG_ECDSA;
                   1083:                sig_scheme.details.ecdsa.hashAlg = alg_id;
                   1084: 
                   1085:        }
                   1086:        else
                   1087:        {
                   1088:                DBG1(DBG_PTS, "%s signature scheme %N not supported by TPM key",
                   1089:                         LABEL, signature_scheme_names, scheme);
                   1090:                return FALSE;
                   1091:        }
                   1092: 
                   1093:        if (data.len <= TPM2_MAX_DIGEST_BUFFER)
                   1094:        {
                   1095:                memcpy(buffer.buffer, data.ptr, data.len);
                   1096:                buffer.size = data.len;
                   1097: 
                   1098:                this->mutex->lock(this->mutex);
                   1099:                rval = Tss2_Sys_Hash(this->sys_context, 0, &buffer, alg_id, hierarchy,
                   1100:                                                         &hash, &validation, 0);
                   1101:                this->mutex->unlock(this->mutex);
                   1102:                if (rval != TPM2_RC_SUCCESS)
                   1103:                {
                   1104:                        DBG1(DBG_PTS,"%s Tss2_Sys_Hash failed: 0x%06x", LABEL, rval);
                   1105:                        return FALSE;
                   1106:                }
                   1107:        }
                   1108:        else
                   1109:        {
                   1110:            TPMI_DH_OBJECT sequence_handle;
                   1111:            TPM2B_AUTH null_auth;
                   1112: 
                   1113:                null_auth.size = 0;
                   1114:                this->mutex->lock(this->mutex);
                   1115:                rval = Tss2_Sys_HashSequenceStart(this->sys_context, 0, &null_auth,
                   1116:                                                                                  alg_id, &sequence_handle, 0);
                   1117:                if (rval != TPM2_RC_SUCCESS)
                   1118:                {
                   1119:                        DBG1(DBG_PTS,"%s Tss2_Sys_HashSequenceStart failed: 0x%06x",
                   1120:                                 LABEL, rval);
                   1121:                        this->mutex->unlock(this->mutex);
                   1122:                        return FALSE;
                   1123:                }
                   1124: 
                   1125:                while (data.len > 0)
                   1126:                {
                   1127:                        buffer.size = min(data.len, TPM2_MAX_DIGEST_BUFFER);
                   1128:                        memcpy(buffer.buffer, data.ptr, buffer.size);
                   1129:                        data.ptr += buffer.size;
                   1130:                        data.len -= buffer.size;
                   1131: 
                   1132:                        rval = Tss2_Sys_SequenceUpdate(this->sys_context, sequence_handle,
                   1133:                                                                                   &auth_cmd, &buffer, 0);
                   1134:                        if (rval != TPM2_RC_SUCCESS)
                   1135:                        {
                   1136:                                DBG1(DBG_PTS,"%s Tss2_Sys_SequenceUpdate failed: 0x%06x",
                   1137:                                         LABEL, rval);
                   1138:                                this->mutex->unlock(this->mutex);
                   1139:                                return FALSE;
                   1140:                        }
                   1141:                }
                   1142:                buffer.size = 0;
                   1143: 
                   1144:                rval = Tss2_Sys_SequenceComplete(this->sys_context, sequence_handle,
                   1145:                                                                                 &auth_cmd, &buffer, hierarchy,
                   1146:                                                                                 &hash, &validation, 0);
                   1147:                this->mutex->unlock(this->mutex);
                   1148:                if (rval != TPM2_RC_SUCCESS)
                   1149:                {
                   1150:                        DBG1(DBG_PTS,"%s Tss2_Sys_SequenceComplete failed: 0x%06x",
                   1151:                                 LABEL, rval);
                   1152:                        return FALSE;
                   1153:                }
                   1154:        }
                   1155: 
                   1156:        this->mutex->lock(this->mutex);
                   1157:        rval = Tss2_Sys_Sign(this->sys_context, handle, &auth_cmd, &hash,
                   1158:                                                 &sig_scheme, &validation, &sig, &auth_rsp);
                   1159:        this->mutex->unlock(this->mutex);
                   1160:        if (rval != TPM2_RC_SUCCESS)
                   1161:        {
                   1162:                DBG1(DBG_PTS,"%s Tss2_Sys_Sign failed: 0x%06x", LABEL, rval);
                   1163:                return FALSE;
                   1164:        }
                   1165: 
                   1166:        /* extract signature */
                   1167:        switch (scheme)
                   1168:        {
                   1169:                case SIGN_RSA_EMSA_PKCS1_SHA1:
                   1170:                case SIGN_RSA_EMSA_PKCS1_SHA2_256:
                   1171:                case SIGN_RSA_EMSA_PKCS1_SHA2_384:
                   1172:                case SIGN_RSA_EMSA_PKCS1_SHA2_512:
                   1173:                        *signature = chunk_clone(
                   1174:                                                        chunk_create(
                   1175:                                                                sig.signature.rsassa.sig.buffer,
                   1176:                                                                sig.signature.rsassa.sig.size));
                   1177:                        break;
                   1178:                case SIGN_RSA_EMSA_PSS:
                   1179:                        *signature = chunk_clone(
                   1180:                                                        chunk_create(
                   1181:                                                                sig.signature.rsapss.sig.buffer,
                   1182:                                                                sig.signature.rsapss.sig.size));
                   1183:                        break;
                   1184:                case SIGN_ECDSA_256:
                   1185:                case SIGN_ECDSA_384:
                   1186:                case SIGN_ECDSA_521:
                   1187:                        *signature = chunk_cat("cc",
                   1188:                                                        chunk_create(
                   1189:                                                                sig.signature.ecdsa.signatureR.buffer,
                   1190:                                                                sig.signature.ecdsa.signatureR.size),
                   1191:                                                        chunk_create(
                   1192:                                                                sig.signature.ecdsa.signatureS.buffer,
                   1193:                                                                sig.signature.ecdsa.signatureS.size));
                   1194:                        break;
                   1195:                case SIGN_ECDSA_WITH_SHA256_DER:
                   1196:                case SIGN_ECDSA_WITH_SHA384_DER:
                   1197:                case SIGN_ECDSA_WITH_SHA512_DER:
                   1198:                        *signature = asn1_wrap(ASN1_SEQUENCE, "mm",
                   1199:                                                        asn1_integer("c",
                   1200:                                                                chunk_create(
                   1201:                                                                        sig.signature.ecdsa.signatureR.buffer,
                   1202:                                                                        sig.signature.ecdsa.signatureR.size)),
                   1203:                                                        asn1_integer("c",
                   1204:                                                                chunk_create(
                   1205:                                                                        sig.signature.ecdsa.signatureS.buffer,
                   1206:                                                                        sig.signature.ecdsa.signatureS.size)));
                   1207:                        break;
                   1208:                default:
                   1209:                        DBG1(DBG_PTS, "%s unsupported %N signature scheme",
                   1210:                                                   LABEL, signature_scheme_names, scheme);
                   1211:                        return FALSE;
                   1212:        }
                   1213: 
                   1214:        return TRUE;
                   1215: }
                   1216: 
                   1217: METHOD(tpm_tss_t, get_random, bool,
                   1218:        private_tpm_tss_tss2_t *this, size_t bytes, uint8_t *buffer)
                   1219: {
                   1220:        size_t len, random_len= sizeof(TPM2B_DIGEST)-2;
                   1221:        TPM2B_DIGEST random = { random_len, };
                   1222:        uint8_t *pos = buffer;
                   1223:        uint32_t rval;
                   1224: 
                   1225:        while (bytes > 0)
                   1226:        {
                   1227:                len = min(bytes, random_len);
                   1228: 
                   1229:                this->mutex->lock(this->mutex);
                   1230:                rval = Tss2_Sys_GetRandom(this->sys_context, NULL, len, &random, NULL);
                   1231:                this->mutex->unlock(this->mutex);
                   1232:                if (rval != TSS2_RC_SUCCESS)
                   1233:                {
                   1234:                        DBG1(DBG_PTS,"%s Tss2_Sys_GetRandom failed: 0x%06x", LABEL, rval);
                   1235:                        return FALSE;
                   1236:            }
                   1237:                memcpy(pos, random.buffer, random.size);
                   1238:                pos   += random.size;
                   1239:                bytes -= random.size;
                   1240:        }
                   1241: 
                   1242:        return TRUE;
                   1243: }
                   1244: 
                   1245: METHOD(tpm_tss_t, get_data, bool,
                   1246:        private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
                   1247:        chunk_t pin, chunk_t *data)
                   1248: {
                   1249:        uint16_t max_data_size, nv_size, nv_offset = 0;
                   1250:        uint32_t rval;
                   1251: 
                   1252:        TPMS_CAPABILITY_DATA cap_data;
                   1253:        TPMI_YES_NO more_data;
                   1254:        TPM2B_NAME nv_name = { sizeof(TPM2B_NAME)-2, };
                   1255:        TPM2B_NV_PUBLIC nv_public = { 0, };
                   1256:        TPM2B_MAX_NV_BUFFER nv_data = { TPM2_MAX_NV_BUFFER_SIZE, };
                   1257:        TPMS_AUTH_COMMAND *cmd;
                   1258:        TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
                   1259:        TSS2L_SYS_AUTH_RESPONSE auth_rsp;
                   1260: 
                   1261:        /* query maximum TPM data transmission size */
                   1262:        this->mutex->lock(this->mutex);
                   1263:        rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
                   1264:                                TPM2_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data, 0);
                   1265:        this->mutex->unlock(this->mutex);
                   1266:        if (rval != TPM2_RC_SUCCESS)
                   1267:        {
                   1268:                DBG1(DBG_PTS,"%s Tss2_Sys_GetCapability failed for "
                   1269:                                         "TPM2_CAP_TPM_PROPERTIES: 0x%06x", LABEL, rval);
                   1270:                return FALSE;
                   1271:        }
                   1272:        max_data_size = min(cap_data.data.tpmProperties.tpmProperty[0].value,
                   1273:                                                TPM2_MAX_NV_BUFFER_SIZE);
                   1274: 
                   1275:        /* get size of NV object */
                   1276:        this->mutex->lock(this->mutex);
                   1277:        rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public,
                   1278:                                                                                                                                &nv_name, 0);
                   1279:        this->mutex->unlock(this->mutex);
                   1280:        if (rval != TPM2_RC_SUCCESS)
                   1281:        {
                   1282:                DBG1(DBG_PTS,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL, rval);
                   1283:                return FALSE;
                   1284:        }
                   1285:        nv_size = nv_public.nvPublic.dataSize;
                   1286:        *data = chunk_alloc(nv_size);
                   1287: 
                   1288:        /* prepare NV read session */
                   1289:        cmd = &auth_cmd.auths[0];
                   1290:        cmd->sessionHandle = TPM2_RS_PW;
                   1291: 
                   1292:        if (pin.len > 0)
                   1293:        {
                   1294:                cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
                   1295:                memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
                   1296:        }
                   1297: 
                   1298:        /* read NV data a maximum data size block at a time */
                   1299:        while (nv_size > 0)
                   1300:        {
                   1301:                this->mutex->lock(this->mutex);
                   1302:                rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle, &auth_cmd,
                   1303:                                        min(nv_size, max_data_size), nv_offset, &nv_data, &auth_rsp);
                   1304:                this->mutex->unlock(this->mutex);
                   1305:                if (rval != TPM2_RC_SUCCESS)
                   1306:                {
                   1307:                        DBG1(DBG_PTS,"%s Tss2_Sys_NV_Read failed: 0x%06x", LABEL, rval);
                   1308:                        chunk_free(data);
                   1309:                        return FALSE;
                   1310:                }
                   1311:                memcpy(data->ptr + nv_offset, nv_data.buffer, nv_data.size);
                   1312:                nv_offset += nv_data.size;
                   1313:                nv_size   -= nv_data.size;
                   1314:        }
                   1315: 
                   1316:        return TRUE;
                   1317: }
                   1318: 
1.1.1.2 ! misho    1319: METHOD(tpm_tss_t, get_event_digest, bool,
        !          1320:        private_tpm_tss_tss2_t *this, int fd, hash_algorithm_t alg, chunk_t *digest)
        !          1321: {
        !          1322:        uint8_t digest_buf[HASH_SIZE_SHA512];
        !          1323:        uint32_t digest_count;
        !          1324:        size_t digest_len = 0;
        !          1325:        hash_algorithm_t hash_alg;
        !          1326:        TPM2_ALG_ID alg_id;
        !          1327: 
        !          1328:        if (this->old_event_digest_format)
        !          1329:        {
        !          1330:                if (alg != HASH_SHA1)
        !          1331:                {
        !          1332:                        return FALSE;
        !          1333:                }
        !          1334:                digest_len = HASH_SIZE_SHA1;
        !          1335: 
        !          1336:                *digest = chunk_alloc(digest_len);
        !          1337: 
        !          1338:                if (read(fd, digest->ptr, digest_len) != digest_len)
        !          1339:                {
        !          1340:                        return FALSE;
        !          1341:                }
        !          1342:        }
        !          1343:        else
        !          1344:        {
        !          1345:                if (read(fd, &digest_count, 4) != 4)
        !          1346:                {
        !          1347:                        return FALSE;
        !          1348:                }
        !          1349:                while (digest_count--)
        !          1350:                {
        !          1351:                        if (read(fd, &alg_id, 2) != 2)
        !          1352:                        {
        !          1353:                                return FALSE;
        !          1354:                        }
        !          1355:                        hash_alg = hash_alg_from_tpm_alg_id(alg_id);
        !          1356: 
        !          1357:                        switch (hash_alg)
        !          1358:                        {
        !          1359:                                case HASH_SHA1:
        !          1360:                                        digest_len = HASH_SIZE_SHA1;
        !          1361:                                        break;
        !          1362:                                case HASH_SHA256:
        !          1363:                                        digest_len = HASH_SIZE_SHA256;
        !          1364:                                        break;
        !          1365:                                case HASH_SHA384:
        !          1366:                                        digest_len = HASH_SIZE_SHA384;
        !          1367:                                        break;
        !          1368:                                case HASH_SHA512:
        !          1369:                                        digest_len = HASH_SIZE_SHA512;
        !          1370:                                        break;
        !          1371:                                default:
        !          1372:                                        DBG2(DBG_PTS, "alg_id: 0x%04x", alg_id);
        !          1373:                                        return FALSE;
        !          1374:                        }
        !          1375:                        if (hash_alg == alg)
        !          1376:                        {
        !          1377:                                *digest = chunk_alloc(digest_len);
        !          1378:                                if (read(fd, digest->ptr, digest_len) != digest_len)
        !          1379:                                {
        !          1380:                                return FALSE;
        !          1381:                                }
        !          1382:                        }
        !          1383:                        else
        !          1384:                        {
        !          1385:                                /* read without storing */
        !          1386:                                if (read(fd, digest_buf, digest_len) != digest_len)
        !          1387:                                {
        !          1388:                                        return FALSE;
        !          1389:                                }
        !          1390:                        }
        !          1391:                }
        !          1392:        }
        !          1393: 
        !          1394:        return TRUE;
        !          1395: }
        !          1396: 
1.1       misho    1397: METHOD(tpm_tss_t, destroy, void,
                   1398:        private_tpm_tss_tss2_t *this)
                   1399: {
                   1400:        finalize_context(this);
                   1401:        this->mutex->destroy(this->mutex);
1.1.1.2 ! misho    1402:        free(this->version_info.ptr);
1.1       misho    1403:        free(this);
                   1404: }
                   1405: 
                   1406: /**
                   1407:  * See header
                   1408:  */
                   1409: tpm_tss_t *tpm_tss_tss2_create()
                   1410: {
                   1411:        private_tpm_tss_tss2_t *this;
                   1412:        bool available;
                   1413: 
                   1414:        INIT(this,
                   1415:                .public = {
                   1416:                        .get_version = _get_version,
                   1417:                        .get_version_info = _get_version_info,
                   1418:                        .generate_aik = _generate_aik,
                   1419:                        .get_public = _get_public,
                   1420:                        .supported_signature_schemes = _supported_signature_schemes,
1.1.1.2 ! misho    1421:                        .has_pcr_bank = _has_pcr_bank,
1.1       misho    1422:                        .read_pcr = _read_pcr,
                   1423:                        .extend_pcr = _extend_pcr,
                   1424:                        .quote = _quote,
                   1425:                        .sign = _sign,
                   1426:                        .get_random = _get_random,
                   1427:                        .get_data = _get_data,
1.1.1.2 ! misho    1428:                        .get_event_digest = _get_event_digest,
1.1       misho    1429:                        .destroy = _destroy,
                   1430:                },
                   1431:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                   1432:        );
                   1433: 
                   1434:        available = initialize_tcti_context(this);
                   1435:        if (available)
                   1436:        {
                   1437:                available = initialize_sys_context(this);
                   1438:        }
                   1439:        DBG1(DBG_PTS, "TPM 2.0 via TSS2 v2 %savailable", available ? "" : "not ");
                   1440: 
                   1441:        if (!available)
                   1442:        {
                   1443:                destroy(this);
                   1444:                return NULL;
                   1445:        }
                   1446:        return &this->public;
                   1447: }
                   1448: 
                   1449: /**
                   1450:  * See header
                   1451:  */
                   1452: bool tpm_tss_tss2_init(void)
                   1453: {
                   1454:        TSS2_TCTI_INFO_FUNC infofn;
                   1455:        const TSS2_TCTI_INFO *info;
                   1456:        char tcti_lib_format[] = "libtss2-tcti-%s.so.0";
                   1457:        char tcti_lib[BUF_LEN];
                   1458:        char *tcti_names[]   = { "device", "tabrmd", "mssim" };
                   1459:        char *tcti_options[] = { "/dev/tpmrm0", "", "" };
                   1460:        char *tcti_name;
                   1461:        bool match = FALSE;
                   1462:        struct stat st;
                   1463:        int i = 0;
                   1464: 
                   1465:        /* check for the existence of an in-kernel TPM resource manager */
                   1466:        if (stat(tcti_options[i], &st))
                   1467:        {
                   1468:                i = 1;
                   1469:        }
                   1470:        DBG2(DBG_PTS, "%s \"%s\" in-kernel resource manager is %spresent",
                   1471:                                   LABEL, tcti_options[0], i ? "not " : "");
                   1472: 
                   1473:        /* select a dynamic TCTI library (device, tabrmd or mssim) */
                   1474:        tcti_name = lib->settings->get_str(lib->settings,
                   1475:                                         "%s.plugins.tpm.tcti.name", tcti_names[i], lib->ns);
                   1476:        snprintf(tcti_lib, BUF_LEN, tcti_lib_format, tcti_name);
                   1477: 
                   1478:        for (i = 0; i < countof(tcti_names); i++)
                   1479:        {
                   1480:                if (streq(tcti_name, tcti_names[i]))
                   1481:                {
                   1482:                        match = TRUE;
                   1483:                        break;
                   1484:                }
                   1485:        }
                   1486:        if (!match)
                   1487:        {
                   1488:                DBG1(DBG_PTS, "%s \"%s\" is not a valid TCTI library name",
                   1489:                         LABEL, tcti_lib);
                   1490:                return FALSE;
                   1491:        }
                   1492: 
                   1493:        tcti_opts = lib->settings->get_str(lib->settings,
                   1494:                                         "%s.plugins.tpm.tcti.opts", tcti_options[i], lib->ns);
                   1495: 
                   1496:        /* open the selected dynamic TCTI library */
                   1497:        tcti_handle = dlopen(tcti_lib, RTLD_LAZY);
                   1498:        if (!tcti_handle)
                   1499:        {
                   1500:                DBG1(DBG_PTS, "%s could not load \"%s\"", LABEL, tcti_lib);
                   1501:                return FALSE;
                   1502:        }
                   1503: 
                   1504:        infofn = (TSS2_TCTI_INFO_FUNC)dlsym(tcti_handle, TSS2_TCTI_INFO_SYMBOL);
                   1505:     if (!infofn)
                   1506:        {
                   1507:         DBG1(DBG_PTS, "%s symbol \"%s\" not found in \"%s\"", LABEL,
                   1508:                                           TSS2_TCTI_INFO_SYMBOL, tcti_lib);
                   1509:                tpm_tss_tss2_deinit();
                   1510: 
                   1511:                return FALSE;
                   1512:     }
                   1513:        DBG2(DBG_PTS, "%s \"%s\" successfully loaded", LABEL, tcti_lib);
                   1514:        info = infofn();
                   1515:        tcti_init = info->init;
                   1516: 
                   1517:        return TRUE;
                   1518: }
                   1519: 
                   1520: /**
                   1521:  * See header
                   1522:  */
                   1523: void tpm_tss_tss2_deinit(void)
                   1524: {
                   1525:        dlclose(tcti_handle);
                   1526:        tcti_handle = NULL;
                   1527:        tcti_init   = NULL;
                   1528:        tcti_opts   = NULL;
                   1529: }
                   1530: 
                   1531: #else /* TSS_TSS2_V2 */
                   1532: 
                   1533: /**
                   1534:  * See header
                   1535:  */
                   1536: bool tpm_tss_tss2_init(void)
                   1537: {
                   1538:        return TRUE;
                   1539: }
                   1540: 
                   1541: /**
                   1542:  * See header
                   1543:  */
                   1544: void tpm_tss_tss2_deinit(void)
                   1545: {
                   1546:        /* empty */
                   1547: }
                   1548: 
                   1549: #endif /* TSS_TSS2_V2 */
                   1550: 

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