Annotation of embedaddon/strongswan/src/libtpmtss/tpm_tss_tss2_v1.c, revision 1.1

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

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