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

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

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