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

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

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