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

1.1       misho       1: /*
1.1.1.2 ! misho       2:  * Copyright (C) 2016-2020 Andreas Steffen
1.1       misho       3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * Copyright (c) 2008 Hal Finney
                      6:  *
                      7:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      8:  * of this software and associated documentation files (the "Software"), to deal
                      9:  * in the Software without restriction, including without limitation the rights
                     10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     11:  * copies of the Software, and to permit persons to whom the Software is
                     12:  * furnished to do so, subject to the following conditions:
                     13:  *
                     14:  * The above copyright notice and this permission notice shall be included in
                     15:  * all copies or substantial portions of the Software.
                     16:  *
                     17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     20:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     22:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     23:  * THE SOFTWARE.
                     24:  */
                     25: 
                     26: #include "tpm_tss_trousers.h"
                     27: 
                     28: #ifdef TSS_TROUSERS
                     29: 
                     30: #ifdef _BASETSD_H_
                     31: /* MinGW defines _BASETSD_H_, but TSS checks for _BASETSD_H */
                     32: # define _BASETSD_H
                     33: #endif
                     34: 
                     35: #include <trousers/tss.h>
                     36: #include <trousers/trousers.h>
                     37: 
1.1.1.2 ! misho      38: #include <unistd.h>
        !            39: 
1.1       misho      40: #define LABEL  "TPM 1.2 -"
                     41: 
                     42: /* size in bytes of a TSS AIK public key blob */
                     43: #define AIK_PUBKEY_BLOB_SIZE           284
                     44: 
                     45: /* maximum number of PCR registers */
                     46: #define PCR_NUM_MAX                                    24
                     47: 
                     48: typedef struct private_tpm_tss_trousers_t private_tpm_tss_trousers_t;
                     49: typedef struct aik_t aik_t;
                     50: 
                     51: /**
                     52:  * Private data of an tpm_tss_trousers_t object.
                     53:  */
                     54: struct private_tpm_tss_trousers_t {
                     55: 
                     56:        /**
                     57:         * Public tpm_tss_trousers_t interface.
                     58:         */
                     59:        tpm_tss_trousers_t interface;
                     60: 
                     61:        /**
                     62:         * TSS context
                     63:         */
                     64:        TSS_HCONTEXT hContext;
                     65: 
                     66:        /**
                     67:         * TPM handle
                     68:         */
                     69:        TSS_HTPM hTPM;
                     70: 
                     71:        /**
                     72:         * TPM version info
                     73:         */
                     74:        chunk_t version_info;
                     75: 
                     76:        /**
                     77:         * List of AIKs retrievable by an object handle
                     78:         */
                     79:        linked_list_t *aik_list;
                     80: 
                     81: };
                     82: 
                     83: struct aik_t {
                     84:        /** AIK object handle */
                     85:        uint32_t handle;
                     86: 
                     87:        /** AIK private key blob */
                     88:        chunk_t blob;
                     89: 
                     90:        /** AIK public key */
                     91:        chunk_t pubkey;
                     92: };
                     93: 
                     94: static void free_aik(aik_t *this)
                     95: {
                     96:        free(this->blob.ptr);
                     97:        free(this->pubkey.ptr);
                     98:        free(this);
                     99: }
                    100: 
                    101: /**
                    102:  * Initialize TSS context
                    103:  *
                    104:  * TPM 1.2 Specification, Part 2 TPM Structures, 21.6 TPM_CAP_VERSION_INFO
                    105:  *
                    106:  *   typedef struct tdTPM_VERSION {
                    107:  *       TPM_VERSION_BYTE major;
                    108:  *       TPM_VERSION_BYTE minor;
                    109:  *       BYTE revMajor;
                    110:  *       BYTE revMinor;
                    111:  *   } TPM_VERSION;
                    112:  *
                    113:  *   typedef struct tdTPM_CAP_VERSION_INFO {
                    114:  *       TPM_STRUCTURE_TAG tag;
                    115:  *       TPM_VERSION version;
                    116:  *       UINT16 specLevel;
                    117:  *       BYTE errataRev;
                    118:  *       BYTE tpmVendorID[4];
                    119:  *       UINT16 vendorSpecificSize;
                    120:  *       [size_is(vendorSpecificSize)] BYTE* vendorSpecific;
                    121:  *   } TPM_CAP_VERSION_INFO;
                    122:  */
                    123: static bool initialize_context(private_tpm_tss_trousers_t *this)
                    124: {
                    125:        uint8_t *version_ptr;
                    126:        uint32_t version_len;
                    127: 
                    128:        TSS_RESULT result;
                    129:        TPM_CAP_VERSION_INFO *info;
                    130: 
                    131:        result = Tspi_Context_Create(&this->hContext);
                    132:        if (result != TSS_SUCCESS)
                    133:        {
                    134:                DBG1(DBG_PTS, "%s could not created context: 0x%x",
                    135:                                           LABEL, result);
                    136:                return FALSE;
                    137:        }
                    138: 
                    139:        result = Tspi_Context_Connect(this->hContext, NULL);
                    140:        if (result != TSS_SUCCESS)
                    141:        {
                    142:                DBG1(DBG_PTS, "%s could not connect with context: 0x%x",
                    143:                                           LABEL, result);
                    144:                return FALSE;
                    145:        }
                    146: 
                    147:        result = Tspi_Context_GetTpmObject (this->hContext, &this->hTPM);
                    148:        if (result != TSS_SUCCESS)
                    149:        {
                    150:                DBG1(DBG_PTS, "%s could not get TPM object: 0x%x",
                    151:                                           LABEL, result);
                    152:                return FALSE;
                    153:        }
                    154: 
                    155:        result = Tspi_TPM_GetCapability(this->hTPM, TSS_TPMCAP_VERSION_VAL,  0,
                    156:                                                                        NULL, &version_len, &version_ptr);
                    157:        if (result != TSS_SUCCESS)
                    158:        {
                    159:                DBG1(DBG_PTS, "%s Tspi_TPM_GetCapability failed: 0x%x",
                    160:                                                LABEL, result);
                    161:                return FALSE;
                    162:        }
                    163: 
                    164:        info = (TPM_CAP_VERSION_INFO *)version_ptr;
                    165:        DBG2(DBG_PTS, "TPM Version Info: Chip Version: %u.%u.%u.%u, "
                    166:                 "Spec Level: %u, Errata Rev: %u, Vendor ID: %.4s",
                    167:                 info->version.major, info->version.minor,
                    168:                 info->version.revMajor, info->version.revMinor,
                    169:                 untoh16(&info->specLevel), info->errataRev, info->tpmVendorID);
                    170: 
                    171:        this->version_info = chunk_clone(chunk_create(version_ptr, version_len));
                    172: 
                    173:        return TRUE;
                    174: }
                    175: 
                    176: /**
                    177:  * Finalize TSS context
                    178:  */
                    179: static void finalize_context(private_tpm_tss_trousers_t *this)
                    180: {
                    181:        if (this->hContext)
                    182:        {
                    183:                Tspi_Context_FreeMemory(this->hContext, NULL);
                    184:                Tspi_Context_Close(this->hContext);
                    185:        }
                    186: }
                    187: 
                    188: METHOD(tpm_tss_t, get_version, tpm_version_t,
                    189:        private_tpm_tss_trousers_t *this)
                    190: {
                    191:        return TPM_VERSION_1_2;
                    192: }
                    193: 
                    194: METHOD(tpm_tss_t, get_version_info, chunk_t,
                    195:        private_tpm_tss_trousers_t *this)
                    196: {
                    197:        return this->version_info;
                    198: }
                    199: 
                    200: METHOD(tpm_tss_t, generate_aik, bool,
                    201:        private_tpm_tss_trousers_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
                    202:        chunk_t *aik_pubkey, chunk_t *identity_req)
                    203: {
                    204:        chunk_t aik_pubkey_blob;
                    205:        chunk_t aik_modulus;
                    206:        chunk_t aik_exponent;
                    207: 
                    208:        TSS_RESULT   result;
                    209:        TSS_HKEY     hSRK;
                    210:        TSS_HKEY     hPCAKey;
                    211:        TSS_HPOLICY  hSrkPolicy;
                    212:        TSS_HPOLICY  hTPMPolicy;
                    213:        TSS_HKEY     hIdentKey;
                    214:        TSS_UUID     SRK_UUID = TSS_UUID_SRK;
                    215:        BYTE         secret[] = TSS_WELL_KNOWN_SECRET;
                    216:        BYTE        *IdentityReq;
                    217:        UINT32       IdentityReqLen;
                    218:        BYTE        *blob;
                    219:        UINT32       blobLen;
                    220: 
                    221:        /* get SRK plus SRK policy and set SRK secret */
                    222:        result = Tspi_Context_LoadKeyByUUID(this->hContext, TSS_PS_TYPE_SYSTEM,
                    223:                                                                                SRK_UUID, &hSRK);
                    224:        if (result != TSS_SUCCESS)
                    225:        {
                    226:                DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByUUID for SRK failed: 0x%x",
                    227:                                           LABEL, result);
                    228:                return FALSE;
                    229:        }
                    230:        result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hSrkPolicy);
                    231:        if (result != TSS_SUCCESS)
                    232:        {
                    233:                DBG1(DBG_PTS, "%s Tspi_GetPolicyObject or SRK failed: 0x%x ",
                    234:                                           LABEL, result);
                    235:                return FALSE;
                    236:        }
                    237:        result = Tspi_Policy_SetSecret(hSrkPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
                    238:        if (result != TSS_SUCCESS)
                    239:        {
                    240:                DBG1(DBG_PTS, "%s Tspi_Policy_SetSecret for SRK failed: 0x%x ",
                    241:                                           LABEL, result);
                    242:                return FALSE;
                    243:        }
                    244: 
                    245:        /* get TPM plus TPM policy and set TPM secret */
                    246:        result = Tspi_Context_GetTpmObject (this->hContext, &this->hTPM);
                    247:        if (result != TSS_SUCCESS)
                    248:        {
                    249:                DBG1(DBG_PTS, "%s Tspi_Context_GetTpmObject failed:  0x%x",
                    250:                                           LABEL, result);
                    251:                return FALSE;
                    252:        }
                    253:        result = Tspi_GetPolicyObject(this->hTPM, TSS_POLICY_USAGE, &hTPMPolicy);
                    254:        if (result != TSS_SUCCESS)
                    255:        {
                    256:                DBG1(DBG_PTS, "%s Tspi_GetPolicyObject for TPM failed: 0x%x",
                    257:                                           LABEL, result);
                    258:                return FALSE;
                    259:        }
                    260:        result = Tspi_Policy_SetSecret(hTPMPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
                    261:        if (result != TSS_SUCCESS)
                    262:        {
                    263:                DBG1(DBG_PTS,"%s Tspi_Policy_SetSecret for TPM failed: 0x%x",
                    264:                                          LABEL, result);
                    265:                return FALSE;
                    266:        }
                    267: 
                    268:        /* create context for a 2048 bit AIK */
                    269:        result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_RSAKEY,
                    270:                                        TSS_KEY_TYPE_IDENTITY | TSS_KEY_SIZE_2048 |
                    271:                                        TSS_KEY_VOLATILE | TSS_KEY_NOT_MIGRATABLE, &hIdentKey);
                    272:        if (result != TSS_SUCCESS)
                    273:        {
                    274:                DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for key failed: 0x%x",
                    275:                                           LABEL, result);
                    276:                return FALSE;
                    277:        }
                    278: 
                    279:        /* create context for the Privacy CA public key and assign modulus */
                    280:        result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_RSAKEY,
                    281:                                        TSS_KEY_TYPE_LEGACY|TSS_KEY_SIZE_2048, &hPCAKey);
                    282:        if (result != TSS_SUCCESS)
                    283:        {
                    284:                DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for PCA failed: 0x%x",
                    285:                                           LABEL, result);
                    286:                return FALSE;
                    287:        }
                    288:        result = Tspi_SetAttribData (hPCAKey, TSS_TSPATTRIB_RSAKEY_INFO,
                    289:                                        TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, ca_modulus.len,
                    290:                                        ca_modulus.ptr);
                    291:        if (result != TSS_SUCCESS)
                    292:        {
                    293:                DBG1(DBG_PTS, "%s Tspi_SetAttribData for PCA modulus failed: 0x%x",
                    294:                                           LABEL, result);
                    295:                return FALSE;
                    296:        }
                    297:        result = Tspi_SetAttribUint32(hPCAKey, TSS_TSPATTRIB_KEY_INFO,
                    298:                                        TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15);
                    299:        if (result != TSS_SUCCESS)
                    300:        {
                    301:                DBG1(DBG_PTS,"%s Tspi_SetAttribUint32 for PCA encryption scheme "
                    302:                                         "failed: 0x%x", LABEL, result);
                    303:                return FALSE;
                    304:        }
                    305: 
                    306:        /* generate AIK */
                    307:        DBG1(DBG_LIB, "Generating identity key...");
                    308:        result = Tspi_TPM_CollateIdentityRequest(this->hTPM, hSRK, hPCAKey, 0, NULL,
                    309:                                        hIdentKey, TSS_ALG_AES, &IdentityReqLen, &IdentityReq);
                    310:        if (result != TSS_SUCCESS)
                    311:        {
                    312:                DBG1(DBG_PTS, "%s Tspi_TPM_CollateIdentityRequest failed: 0x%x",
                    313:                                           LABEL, result);
                    314:                return FALSE;
                    315:        }
                    316:        *identity_req = chunk_create(IdentityReq, IdentityReqLen);
                    317:        DBG3(DBG_LIB, "%s Identity Request: %B", LABEL, identity_req);
                    318: 
                    319:        /* load identity key */
                    320:        result = Tspi_Key_LoadKey (hIdentKey, hSRK);
                    321:        if (result != TSS_SUCCESS)
                    322:        {
                    323:                DBG1(DBG_PTS, "%s Tspi_Key_LoadKey for AIK failed: 0x%x",
                    324:                                           LABEL, result);
                    325:                return FALSE;
                    326:        }
                    327: 
                    328:        /* output AIK private key in TSS blob format */
                    329:        result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
                    330:                                        TSS_TSPATTRIB_KEYBLOB_BLOB, &blobLen, &blob);
                    331:        if (result != TSS_SUCCESS)
                    332:        {
                    333:                DBG1(DBG_PTS, "%s Tspi_GetAttribData for private key blob failed: 0x%x",
                    334:                                           LABEL, result);
                    335:                return FALSE;
                    336:        }
                    337:        *aik_blob = chunk_create(blob, blobLen);
                    338:        DBG3(DBG_LIB, "%s AIK private key blob: %B", LABEL, aik_blob);
                    339: 
                    340:        /* output AIK Public Key in TSS blob format */
                    341:        result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
                    342:                                        TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blobLen, &blob);
                    343:        if (result != TSS_SUCCESS)
                    344:        {
                    345:                DBG1(DBG_PTS, "%s Tspi_GetAttribData for public key blob failed: 0x%x",
                    346:                                           LABEL, result);
                    347:                return FALSE;
                    348:        }
                    349:        aik_pubkey_blob = chunk_create(blob, blobLen);
                    350:        DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_pubkey_blob);
                    351: 
                    352:        /* create a trusted AIK public key */
                    353:        if (aik_pubkey_blob.len != AIK_PUBKEY_BLOB_SIZE)
                    354:        {
                    355:                DBG1(DBG_PTS, "%s AIK public key is not in TSS blob format",
                    356:                                           LABEL);
                    357:                return FALSE;
                    358:        }
                    359:        aik_modulus = chunk_skip(aik_pubkey_blob, AIK_PUBKEY_BLOB_SIZE - 256);
                    360:        aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
                    361: 
                    362:        /* output subjectPublicKeyInfo encoding of AIK public key */
                    363:        if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER, NULL,
                    364:                                        aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
                    365:                                        CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
                    366:        {
                    367:                DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key failed",
                    368:                                           LABEL);
                    369:                return FALSE;
                    370:        }
                    371:        return TRUE;
                    372: }
                    373: 
                    374: METHOD(tpm_tss_t, get_public, chunk_t,
                    375:        private_tpm_tss_trousers_t *this, uint32_t handle)
                    376: {
                    377:        enumerator_t *enumerator;
                    378:        chunk_t aik_pubkey = chunk_empty;
                    379:        aik_t *aik;
                    380: 
                    381:        enumerator = this->aik_list->create_enumerator(this->aik_list);
                    382:        while (enumerator->enumerate(enumerator, &aik))
                    383:        {
                    384:                if (aik->handle == handle)
                    385:                {
                    386:                        aik_pubkey = chunk_clone(aik->pubkey);
                    387:                        break;
                    388:                }
                    389:        }
                    390:        enumerator->destroy(enumerator);
                    391: 
                    392:        return aik_pubkey;
                    393: }
                    394: 
                    395: METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
                    396:        private_tpm_tss_trousers_t *this, uint32_t handle)
                    397: {
                    398:        return enumerator_create_empty();
                    399: }
                    400: 
1.1.1.2 ! misho     401: METHOD(tpm_tss_t, has_pcr_bank, bool,
        !           402:        private_tpm_tss_trousers_t *this, hash_algorithm_t alg)
        !           403: {
        !           404:        return alg == HASH_SHA1;
        !           405: }
        !           406: 
1.1       misho     407: METHOD(tpm_tss_t, read_pcr, bool,
                    408:        private_tpm_tss_trousers_t *this, uint32_t pcr_num, chunk_t *pcr_value,
                    409:        hash_algorithm_t alg)
                    410: {
                    411:        TSS_RESULT result;
                    412:        uint8_t *value;
                    413:        uint32_t len;
                    414: 
1.1.1.2 ! misho     415:        if (alg != HASH_SHA1)
        !           416:        {
        !           417:                return FALSE;
        !           418:        }
1.1       misho     419:        result = Tspi_TPM_PcrRead(this->hTPM, pcr_num, &len, &value);
                    420:        if (result != TSS_SUCCESS)
                    421:        {
                    422:                DBG1(DBG_PTS, "%s Tspi_TPM_PcrRead failed: 0x%x", LABEL, result);
                    423:                return FALSE;
                    424:        }
                    425:        *pcr_value = chunk_clone(chunk_create(value, len));
                    426: 
                    427:        return TRUE;
                    428: }
                    429: 
                    430: METHOD(tpm_tss_t, extend_pcr, bool,
                    431:        private_tpm_tss_trousers_t *this, uint32_t pcr_num, chunk_t *pcr_value,
                    432:        chunk_t data, hash_algorithm_t alg)
                    433: {
                    434:        TSS_RESULT result;
                    435:        uint32_t pcr_len;
                    436:        uint8_t *pcr_ptr;
                    437: 
1.1.1.2 ! misho     438:        if (alg != HASH_SHA1)
        !           439:        {
        !           440:                return FALSE;
        !           441:        }
1.1       misho     442:        result = Tspi_TPM_PcrExtend(this->hTPM, pcr_num, data.len, data.ptr,
                    443:                                                                NULL, &pcr_len, &pcr_ptr);
                    444:        if (result != TSS_SUCCESS)
                    445:        {
                    446:                DBG1(DBG_PTS, "%s Tspi_TPM_PcrExtend failed: 0x%x", LABEL, result);
                    447:                return FALSE;
                    448:        }
                    449:        *pcr_value = chunk_clone(chunk_create(pcr_ptr, pcr_len));
                    450: 
                    451:        return TRUE;
                    452: }
                    453: 
                    454: METHOD(tpm_tss_t, quote, bool,
                    455:        private_tpm_tss_trousers_t *this, uint32_t aik_handle, uint32_t pcr_sel,
                    456:        hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
                    457:        tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
                    458: {
                    459:        TSS_HKEY hAIK;
                    460:        TSS_HKEY hSRK;
                    461:        TSS_HPOLICY srkUsagePolicy;
                    462:        TSS_UUID SRK_UUID = TSS_UUID_SRK;
                    463:        TSS_HPCRS hPcrComposite;
                    464:        TSS_VALIDATION valData;
                    465:        TSS_RESULT result;
                    466:        uint8_t secret[] = TSS_WELL_KNOWN_SECRET;
                    467:        uint8_t *version_info, *comp_hash;
                    468:        uint32_t version_info_size, pcr;
                    469:        aik_t *aik;
                    470:        chunk_t aik_blob = chunk_empty;
                    471:        chunk_t quote_chunk, pcr_digest;
                    472:        enumerator_t *enumerator;
                    473:        bool success = FALSE;
                    474: 
1.1.1.2 ! misho     475:        if (alg != HASH_SHA1)
        !           476:        {
        !           477:                return FALSE;
        !           478:        }
        !           479: 
1.1       misho     480:        /* Retrieve SRK from TPM and set the authentication to well known secret*/
                    481:        result = Tspi_Context_LoadKeyByUUID(this->hContext, TSS_PS_TYPE_SYSTEM,
                    482:                                                                                SRK_UUID, &hSRK);
                    483:        if (result != TSS_SUCCESS)
                    484:        {
                    485:                DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByUUID for SRK failed: 0x%x",
                    486:                                           LABEL, result);
                    487:                return FALSE;
                    488:        }
                    489:        result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &srkUsagePolicy);
                    490:        if (result != TSS_SUCCESS)
                    491:        {
                    492:                DBG1(DBG_PTS, "%s Tspi_GetPolicyObject for SRK failed: 0x%x",
                    493:                                           LABEL, result);
                    494:                return FALSE;
                    495:        }
                    496:        result = Tspi_Policy_SetSecret(srkUsagePolicy, TSS_SECRET_MODE_SHA1,
                    497:                                        20, secret);
                    498:        if (result != TSS_SUCCESS)
                    499:        {
                    500:                DBG1(DBG_PTS, "%s Tspi_Policy_SetSecret for SRK failed: 0x%x",
                    501:                                           LABEL, result);
                    502:                return FALSE;
                    503:        }
                    504: 
                    505:        /* Retrieve AIK using its handle and load private key into TPM 1.2 */
                    506:        enumerator = this->aik_list->create_enumerator(this->aik_list);
                    507:        while (enumerator->enumerate(enumerator, &aik))
                    508:        {
                    509:                if (aik->handle == aik_handle)
                    510:                {
                    511:                        aik_blob = aik->blob;
                    512:                        break;
                    513:                }
                    514:        }
                    515:        enumerator->destroy(enumerator);
                    516: 
                    517:        if (aik_blob.len == 0)
                    518:        {
                    519:                DBG1(DBG_PTS, "%s AIK private key for handle 0x%80x not found", LABEL);
                    520:                return FALSE;
                    521:        }
                    522:        result = Tspi_Context_LoadKeyByBlob(this->hContext, hSRK, aik_blob.len,
                    523:                                                                                aik_blob.ptr, &hAIK);
                    524:        if (result != TSS_SUCCESS)
                    525:        {
                    526:                DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByBlob for AIK failed: 0x%x",
                    527:                                           LABEL, result);
                    528:                return FALSE;
                    529:        }
                    530: 
                    531:        /* Create PCR composite object */
                    532:        result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_PCRS,
                    533:                                        (*quote_mode == TPM_QUOTE) ? TSS_PCRS_STRUCT_INFO :
                    534:                                                                                                 TSS_PCRS_STRUCT_INFO_SHORT,
                    535:                                        &hPcrComposite);
                    536:        if (result != TSS_SUCCESS)
                    537:        {
                    538:                DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for pcrComposite failed: "
                    539:                                          "0x%x", LABEL, result);
                    540:                goto err1;
                    541:        }
                    542: 
                    543:        /* Select PCRs */
                    544:        for (pcr = 0; pcr < PCR_NUM_MAX; pcr++)
                    545:        {
                    546:                if (pcr_sel & (1 << pcr))
                    547:                {
                    548:                        result = (*quote_mode == TPM_QUOTE) ?
                    549:                                Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr) :
                    550:                                Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
                    551:                                                                                TSS_PCRS_DIRECTION_RELEASE);
                    552:                        if (result != TSS_SUCCESS)
                    553:                        {
                    554:                                DBG1(DBG_PTS, "%s Tspi_PcrComposite_SelectPcrIndex failed: "
                    555:                                                          "0x%x", LABEL, result);
                    556:                                goto err2;
                    557:                        }
                    558:                }
                    559:        }
                    560: 
                    561:        /* Set the Validation Data */
                    562:        valData.ulExternalDataLength = data.len;
                    563:        valData.rgbExternalData      = data.ptr;
                    564: 
                    565:        /* TPM Quote */
                    566:        result = (*quote_mode == TPM_QUOTE) ?
                    567:                        Tspi_TPM_Quote (this->hTPM, hAIK, hPcrComposite, &valData) :
                    568:                        Tspi_TPM_Quote2(this->hTPM, hAIK,
                    569:                                                        *quote_mode == TPM_QUOTE2_VERSION_INFO,
                    570:                                                    hPcrComposite, &valData, &version_info_size,
                    571:                                                        &version_info);
                    572:        if (result != TSS_SUCCESS)
                    573:        {
                    574:                DBG1(DBG_PTS, "%s Tspi_TPM_Quote%s failed: 0x%x", LABEL,
                    575:                                          (*quote_mode == TPM_QUOTE) ? "" : "2", result);
                    576:                goto err2;
                    577:        }
                    578: 
                    579:        if (*quote_mode == TPM_QUOTE)
                    580:        {
                    581:                /* TPM_Composite_Hash starts at byte 8 of TPM_Quote_Info structure */
                    582:                comp_hash = valData.rgbData + 8;
                    583:        }
                    584:        else
                    585:        {
                    586:                /* TPM_Composite_Hash is last 20 bytes of TPM_Quote_Info2 structure */
                    587:                comp_hash = valData.rgbData + valData.ulDataLength - version_info_size -
                    588:                                        HASH_SIZE_SHA1;
                    589:        }
                    590:        pcr_digest = chunk_create(comp_hash, HASH_SIZE_SHA1);
                    591:        DBG2(DBG_PTS, "PCR composite digest: %B", &pcr_digest);
                    592: 
                    593:        quote_chunk = chunk_create(valData.rgbData, valData.ulDataLength);
                    594:        DBG2(DBG_PTS, "TPM Quote Info: %B", &quote_chunk);
                    595: 
                    596:        *quote_info = tpm_tss_quote_info_create(*quote_mode, HASH_SHA1, pcr_digest);
                    597: 
                    598:        *quote_sig = chunk_clone(chunk_create(valData.rgbValidationData,
                    599:                                                                                  valData.ulValidationDataLength));
                    600:        DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
                    601: 
                    602:        success = TRUE;
                    603: 
                    604: err2:
                    605:        Tspi_Context_CloseObject(this->hContext, hPcrComposite);
                    606: err1:
                    607:        Tspi_Context_CloseObject(this->hContext, hAIK);
                    608: 
                    609:        return success;
                    610: }
                    611: 
                    612: METHOD(tpm_tss_t, sign, bool,
                    613:        private_tpm_tss_trousers_t *this, uint32_t hierarchy, uint32_t handle,
                    614:        signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
                    615:        chunk_t *signature)
                    616: {
                    617:        return FALSE;
                    618: }
                    619: 
                    620: METHOD(tpm_tss_t, get_random, bool,
                    621:        private_tpm_tss_trousers_t *this, size_t bytes, uint8_t *buffer)
                    622: {
                    623:        return FALSE;
                    624: }
                    625: 
                    626: METHOD(tpm_tss_t, get_data, bool,
                    627:        private_tpm_tss_trousers_t *this, uint32_t hierarchy, uint32_t handle,
                    628:        chunk_t pin, chunk_t *data)
                    629: {
                    630:        return FALSE;
                    631: }
                    632: 
1.1.1.2 ! misho     633: METHOD(tpm_tss_t, get_event_digest, bool,
        !           634:        private_tpm_tss_trousers_t *this, int fd, hash_algorithm_t alg,
        !           635:        chunk_t *digest)
        !           636: {
        !           637:        if (alg != HASH_SHA1)
        !           638:        {
        !           639:                return FALSE;
        !           640:        }
        !           641:        *digest = chunk_alloc(HASH_SIZE_SHA1);
        !           642: 
        !           643:        return read(fd, digest->ptr, digest->len) == digest->len;
        !           644: }
        !           645: 
1.1       misho     646: METHOD(tpm_tss_t, destroy, void,
                    647:        private_tpm_tss_trousers_t *this)
                    648: {
                    649:        finalize_context(this);
                    650:        this->aik_list->destroy_function(this->aik_list, (void*)free_aik);
                    651:        free(this->version_info.ptr);
                    652:        free(this);
                    653: }
                    654: 
                    655: METHOD(tpm_tss_trousers_t, load_aik, void,
                    656:        private_tpm_tss_trousers_t *this, chunk_t blob, chunk_t pubkey,
                    657:        uint32_t handle)
                    658: {
                    659:        aik_t *item;
                    660: 
                    661:        INIT(item,
                    662:                .handle = handle,
                    663:                .blob = blob,
                    664:                .pubkey = pubkey,
                    665:        );
                    666: 
                    667:        this->aik_list->insert_last(this->aik_list, item);
                    668: }
                    669: 
                    670: /**
                    671:  * See header
                    672:  */
                    673: tpm_tss_t *tpm_tss_trousers_create()
                    674: {
                    675:        private_tpm_tss_trousers_t *this;
                    676:        bool available;
                    677: 
                    678:        INIT(this,
                    679:                .interface = {
                    680:                        .public = {
                    681:                                .get_version = _get_version,
                    682:                                .get_version_info = _get_version_info,
                    683:                                .generate_aik = _generate_aik,
                    684:                                .get_public = _get_public,
                    685:                                .supported_signature_schemes = _supported_signature_schemes,
1.1.1.2 ! misho     686:                                .has_pcr_bank = _has_pcr_bank,
1.1       misho     687:                                .read_pcr = _read_pcr,
                    688:                                .extend_pcr = _extend_pcr,
                    689:                                .quote = _quote,
                    690:                                .sign = _sign,
                    691:                                .get_random = _get_random,
                    692:                                .get_data = _get_data,
1.1.1.2 ! misho     693:                                .get_event_digest = _get_event_digest,
1.1       misho     694:                                .destroy = _destroy,
                    695:                        },
                    696:                        .load_aik = _load_aik,
                    697:                },
                    698:                .aik_list = linked_list_create(),
                    699:        );
                    700: 
                    701:        available = initialize_context(this);
                    702:        DBG1(DBG_PTS, "TPM 1.2 via TrouSerS %savailable", available ? "" : "not ");
                    703: 
                    704:        if (!available)
                    705:        {
                    706:                destroy(this);
                    707:                return NULL;
                    708:        }
                    709:        return &this->interface.public;
                    710: }
                    711: 
                    712: #else /* TSS_TROUSERS */
                    713: 
                    714: tpm_tss_t *tpm_tss_trousers_create()
                    715: {
                    716:        return NULL;
                    717: }
                    718: 
                    719: #endif /* TSS_TROUSERS */
                    720: 
                    721: 
                    722: 

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