Annotation of embedaddon/strongswan/src/libtpmtss/tpm_tss_tss2_v2.c, revision 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>