1 2/* 3 * Licensed Materials - Property of IBM 4 * 5 * trousers - An open source TCG Software Stack 6 * 7 * (C) Copyright International Business Machines Corp. 2004-2007 8 * 9 */ 10 11#include <stdlib.h> 12#include <stdio.h> 13#include <string.h> 14#include <inttypes.h> 15 16#include "trousers/tss.h" 17#include "trousers/trousers.h" 18#include "trousers_types.h" 19#include "spi_utils.h" 20#include "capabilities.h" 21#include "tsplog.h" 22#include "obj.h" 23 24 25TSS_RESULT 26Tspi_TPM_CreateEndorsementKey(TSS_HTPM hTPM, /* in */ 27 TSS_HKEY hKey, /* in */ 28 TSS_VALIDATION * pValidationData) /* in, out */ 29{ 30 TCPA_NONCE antiReplay; 31 TCPA_DIGEST digest; 32 TSS_RESULT result; 33 UINT32 ekSize; 34 BYTE *ek; 35 TSS_KEY dummyKey; 36 UINT64 offset; 37 TCPA_DIGEST hash; 38 UINT32 newEKSize; 39 BYTE *newEK; 40 TSS_HCONTEXT tspContext; 41 TCPA_PUBKEY pubEK; 42 Trspi_HashCtx hashCtx; 43 44 __tspi_memset(&pubEK, 0, sizeof(TCPA_PUBKEY)); 45 __tspi_memset(&dummyKey, 0, sizeof(TSS_KEY)); 46 47 if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext))) 48 return result; 49 50 if ((result = obj_rsakey_get_blob(hKey, &ekSize, &ek))) 51 return result; 52 53 offset = 0; 54 if ((result = UnloadBlob_TSS_KEY(&offset, ek, &dummyKey))) 55 return result; 56 57 offset = 0; 58 Trspi_LoadBlob_KEY_PARMS(&offset, ek, &dummyKey.algorithmParms); 59 free_key_refs(&dummyKey); 60 ekSize = offset; 61 62 if (pValidationData == NULL) { 63 if ((result = get_local_random(tspContext, FALSE, sizeof(TCPA_NONCE), 64 (BYTE **)antiReplay.nonce))) { 65 LogError("Failed to create random nonce"); 66 return TSPERR(TSS_E_INTERNAL_ERROR); 67 } 68 } else { 69 if (pValidationData->ulExternalDataLength < sizeof(antiReplay.nonce)) 70 return TSPERR(TSS_E_BAD_PARAMETER); 71 72 memcpy(antiReplay.nonce, pValidationData->rgbExternalData, 73 sizeof(antiReplay.nonce)); 74 } 75 76 if ((result = TCS_API(tspContext)->CreateEndorsementKeyPair(tspContext, antiReplay, ekSize, 77 ek, &newEKSize, &newEK, 78 &digest))) 79 return result; 80 81 if (pValidationData == NULL) { 82 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 83 result |= Trspi_HashUpdate(&hashCtx, newEKSize, newEK); 84 result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN, antiReplay.nonce); 85 if ((result |= Trspi_HashFinal(&hashCtx, hash.digest))) 86 goto done; 87 88 if (memcmp(hash.digest, digest.digest, TCPA_SHA1_160_HASH_LEN)) { 89 LogError("Internal verification failed"); 90 result = TSPERR(TSS_E_EK_CHECKSUM); 91 goto done; 92 } 93 } else { 94 pValidationData->rgbData = calloc_tspi(tspContext, newEKSize); 95 if (pValidationData->rgbData == NULL) { 96 LogError("malloc of %u bytes failed.", newEKSize); 97 result = TSPERR(TSS_E_OUTOFMEMORY); 98 goto done; 99 } 100 pValidationData->ulDataLength = newEKSize; 101 memcpy(pValidationData->rgbData, newEK, newEKSize); 102 memcpy(&pValidationData->rgbData[ekSize], antiReplay.nonce, 103 sizeof(antiReplay.nonce)); 104 105 pValidationData->rgbValidationData = calloc_tspi(tspContext, 106 TCPA_SHA1_160_HASH_LEN); 107 if (pValidationData->rgbValidationData == NULL) { 108 LogError("malloc of %d bytes failed.", TCPA_SHA1_160_HASH_LEN); 109 free_tspi(tspContext, pValidationData->rgbData); 110 pValidationData->rgbData = NULL; 111 pValidationData->ulDataLength = 0; 112 result = TSPERR(TSS_E_OUTOFMEMORY); 113 goto done; 114 } 115 pValidationData->ulValidationDataLength = TCPA_SHA1_160_HASH_LEN; 116 memcpy(pValidationData->rgbValidationData, digest.digest, TCPA_SHA1_160_HASH_LEN); 117 } 118 119 if ((result = obj_rsakey_set_pubkey(hKey, FALSE, newEK)) && pValidationData) { 120 free_tspi(tspContext, pValidationData->rgbValidationData); 121 free_tspi(tspContext, pValidationData->rgbData); 122 pValidationData->rgbData = NULL; 123 pValidationData->ulDataLength = 0; 124 pValidationData->rgbValidationData = NULL; 125 pValidationData->ulValidationDataLength = 0; 126 } 127 128done: 129 free(newEK); 130 131 return result; 132} 133 134TSS_RESULT 135Tspi_TPM_GetPubEndorsementKey(TSS_HTPM hTPM, /* in */ 136 TSS_BOOL fOwnerAuthorized, /* in */ 137 TSS_VALIDATION *pValidationData, /* in, out */ 138 TSS_HKEY *phEndorsementPubKey) /* out */ 139{ 140 TCPA_DIGEST digest; 141 TSS_RESULT result; 142 UINT64 offset; 143 UINT32 pubEKSize; 144 BYTE *pubEK; 145 TCPA_NONCE antiReplay; 146 TCPA_DIGEST checkSum; 147 TSS_HOBJECT retKey; 148 TSS_HCONTEXT tspContext; 149 TCPA_PUBKEY pubKey; 150 Trspi_HashCtx hashCtx; 151 152 __tspi_memset(&pubKey, 0, sizeof(TCPA_PUBKEY)); 153 154 if (phEndorsementPubKey == NULL) 155 return TSPERR(TSS_E_BAD_PARAMETER); 156 157 if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext))) 158 return result; 159 160 if (fOwnerAuthorized) 161 return owner_get_pubek(tspContext, hTPM, phEndorsementPubKey); 162 163 if (pValidationData == NULL) { 164 if ((result = get_local_random(tspContext, FALSE, sizeof(TCPA_NONCE), 165 (BYTE **)antiReplay.nonce))) { 166 LogDebug("Failed to generate random nonce"); 167 return TSPERR(TSS_E_INTERNAL_ERROR); 168 } 169 } else { 170 if (pValidationData->ulExternalDataLength < sizeof(antiReplay.nonce)) 171 return TSPERR(TSS_E_BAD_PARAMETER); 172 173 memcpy(antiReplay.nonce, pValidationData->rgbExternalData, 174 sizeof(antiReplay.nonce)); 175 } 176 177 /* call down to the TPM */ 178 if ((result = TCS_API(tspContext)->ReadPubek(tspContext, antiReplay, &pubEKSize, &pubEK, 179 &checkSum))) 180 return result; 181 182 /* validate the returned hash, or set up the return so that the user can */ 183 if (pValidationData == NULL) { 184 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 185 result |= Trspi_HashUpdate(&hashCtx, pubEKSize, pubEK); 186 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, antiReplay.nonce); 187 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 188 goto done; 189 190 /* check validation of the entire pubkey structure */ 191 if (memcmp(digest.digest, checkSum.digest, TPM_SHA1_160_HASH_LEN)) { 192 /* validation failed, unload the pubEK in order to hash 193 * just the pubKey portion of the pubEK. This is done on 194 * Atmel chips specifically. 195 */ 196 offset = 0; 197 __tspi_memset(&pubKey, 0, sizeof(TCPA_PUBKEY)); 198 if ((result = Trspi_UnloadBlob_PUBKEY(&offset, pubEK, &pubKey))) 199 goto done; 200 201 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 202 result |= Trspi_HashUpdate(&hashCtx, pubKey.pubKey.keyLength, 203 pubKey.pubKey.key); 204 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, 205 antiReplay.nonce); 206 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 207 goto done; 208 209 if (memcmp(digest.digest, checkSum.digest, TCPA_SHA1_160_HASH_LEN)) { 210 result = TSPERR(TSS_E_EK_CHECKSUM); 211 goto done; 212 } 213 } 214 } else { 215 /* validate the entire TCPA_PUBKEY structure */ 216 pValidationData->ulDataLength = pubEKSize + TCPA_SHA1_160_HASH_LEN; 217 pValidationData->rgbData = calloc_tspi(tspContext, 218 pValidationData->ulDataLength); 219 if (pValidationData->rgbData == NULL) { 220 LogError("malloc of %u bytes failed.", 221 pValidationData->ulDataLength); 222 pValidationData->ulDataLength = 0; 223 result = TSPERR(TSS_E_OUTOFMEMORY); 224 goto done; 225 } 226 227 memcpy(pValidationData->rgbData, pubEK, pubEKSize); 228 memcpy(&pValidationData->rgbData[pubEKSize], antiReplay.nonce, 229 TCPA_SHA1_160_HASH_LEN); 230 231 pValidationData->ulValidationDataLength = TCPA_SHA1_160_HASH_LEN; 232 pValidationData->rgbValidationData = calloc_tspi(tspContext, 233 TCPA_SHA1_160_HASH_LEN); 234 if (pValidationData->rgbValidationData == NULL) { 235 LogError("malloc of %d bytes failed.", TCPA_SHA1_160_HASH_LEN); 236 pValidationData->ulValidationDataLength = 0; 237 pValidationData->ulDataLength = 0; 238 free_tspi(tspContext,pValidationData->rgbData); 239 result = TSPERR(TSS_E_OUTOFMEMORY); 240 goto done; 241 } 242 243 memcpy(pValidationData->rgbValidationData, checkSum.digest, 244 TPM_SHA1_160_HASH_LEN); 245 } 246 247 if ((result = obj_rsakey_add(tspContext, TSS_KEY_SIZE_2048|TSS_KEY_TYPE_LEGACY, &retKey))) 248 goto done; 249 250 if ((result = obj_rsakey_set_pubkey(retKey, TRUE, pubEK))) 251 goto done; 252 253 *phEndorsementPubKey = retKey; 254 255done: 256 free(pubEK); 257 return result; 258} 259 260#ifdef TSS_BUILD_TSS12 261TSS_RESULT 262Tspi_TPM_CreateRevocableEndorsementKey(TSS_HTPM hTPM, /* in */ 263 TSS_HKEY hKey, /* in */ 264 TSS_VALIDATION * pValidationData,/* in, out */ 265 UINT32 * pulEkResetDataLength, /* in, out */ 266 BYTE ** prgbEkResetData) /* in, out */ 267{ 268 TPM_NONCE antiReplay; 269 TPM_DIGEST digest; 270 TSS_RESULT result; 271 UINT32 ekSize; 272 BYTE *ek; 273 TSS_KEY dummyKey; 274 UINT64 offset; 275 TSS_BOOL genResetAuth; 276 TPM_DIGEST eKResetAuth; 277 TPM_DIGEST hash; 278 UINT32 newEKSize; 279 BYTE *newEK; 280 TSS_HCONTEXT tspContext; 281 TPM_PUBKEY pubEK; 282 Trspi_HashCtx hashCtx; 283 284 __tspi_memset(&pubEK, 0, sizeof(TPM_PUBKEY)); 285 __tspi_memset(&dummyKey, 0, sizeof(TSS_KEY)); 286 __tspi_memset(&eKResetAuth, 0xff, sizeof(eKResetAuth)); 287 288 if (!pulEkResetDataLength || !prgbEkResetData) 289 return TSPERR(TSS_E_BAD_PARAMETER); 290 291 if (*pulEkResetDataLength != 0) { 292 if (*prgbEkResetData == NULL) 293 return TSPERR(TSS_E_BAD_PARAMETER); 294 295 if (*pulEkResetDataLength < sizeof(eKResetAuth.digest)) 296 return TSPERR(TSS_E_BAD_PARAMETER); 297 298 memcpy(eKResetAuth.digest, *prgbEkResetData, sizeof(eKResetAuth.digest)); 299 genResetAuth = FALSE; 300 } else { 301 if (*prgbEkResetData != NULL) 302 return TSPERR(TSS_E_BAD_PARAMETER); 303 304 genResetAuth = TRUE; 305 } 306 307 if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext))) 308 return result; 309 310 if ((result = obj_rsakey_get_blob(hKey, &ekSize, &ek))) 311 return result; 312 313 offset = 0; 314 if ((result = UnloadBlob_TSS_KEY(&offset, ek, &dummyKey))) 315 return result; 316 317 offset = 0; 318 Trspi_LoadBlob_KEY_PARMS(&offset, ek, &dummyKey.algorithmParms); 319 free_key_refs(&dummyKey); 320 ekSize = offset; 321 322 if (pValidationData == NULL) { 323 if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE), 324 (BYTE **)antiReplay.nonce))) { 325 LogError("Failed to create random nonce"); 326 return TSPERR(TSS_E_INTERNAL_ERROR); 327 } 328 } else { 329 if (pValidationData->ulExternalDataLength < sizeof(antiReplay.nonce)) 330 return TSPERR(TSS_E_BAD_PARAMETER); 331 332 memcpy(antiReplay.nonce, pValidationData->rgbExternalData, 333 sizeof(antiReplay.nonce)); 334 } 335 336 if ((result = RPC_CreateRevocableEndorsementKeyPair(tspContext, antiReplay, ekSize, ek, 337 genResetAuth, &eKResetAuth, &newEKSize, 338 &newEK, &digest))) 339 return result; 340 341 if (pValidationData == NULL) { 342 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 343 result |= Trspi_HashUpdate(&hashCtx, newEKSize, newEK); 344 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, antiReplay.nonce); 345 if ((result |= Trspi_HashFinal(&hashCtx, hash.digest))) 346 goto done; 347 348 if (memcmp(hash.digest, digest.digest, TPM_SHA1_160_HASH_LEN)) { 349 LogError("Internal verification failed"); 350 result = TSPERR(TSS_E_EK_CHECKSUM); 351 goto done; 352 } 353 } else { 354 pValidationData->rgbData = calloc_tspi(tspContext, newEKSize); 355 if (pValidationData->rgbData == NULL) { 356 LogError("malloc of %u bytes failed.", newEKSize); 357 result = TSPERR(TSS_E_OUTOFMEMORY); 358 goto done; 359 } 360 pValidationData->ulDataLength = newEKSize; 361 memcpy(pValidationData->rgbData, newEK, newEKSize); 362 memcpy(&pValidationData->rgbData[ekSize], antiReplay.nonce, 363 sizeof(antiReplay.nonce)); 364 365 pValidationData->rgbValidationData = calloc_tspi(tspContext, 366 TPM_SHA1_160_HASH_LEN); 367 if (pValidationData->rgbValidationData == NULL) { 368 LogError("malloc of %d bytes failed.", TPM_SHA1_160_HASH_LEN); 369 free_tspi(tspContext, pValidationData->rgbData); 370 pValidationData->rgbData = NULL; 371 pValidationData->ulDataLength = 0; 372 result = TSPERR(TSS_E_OUTOFMEMORY); 373 goto done; 374 } 375 pValidationData->ulValidationDataLength = TPM_SHA1_160_HASH_LEN; 376 memcpy(pValidationData->rgbValidationData, digest.digest, TPM_SHA1_160_HASH_LEN); 377 } 378 379 if ((result = obj_rsakey_set_pubkey(hKey, FALSE, newEK))) { 380 if (pValidationData) { 381 free_tspi(tspContext, pValidationData->rgbValidationData); 382 free_tspi(tspContext, pValidationData->rgbData); 383 pValidationData->rgbData = NULL; 384 pValidationData->ulDataLength = 0; 385 pValidationData->rgbValidationData = NULL; 386 pValidationData->ulValidationDataLength = 0; 387 } 388 goto done; 389 } 390 391 if (genResetAuth) { 392 if ((*prgbEkResetData = calloc_tspi(tspContext, sizeof(eKResetAuth.digest))) == NULL) { 393 LogError("malloc of %zd bytes failed.", sizeof(eKResetAuth.digest)); 394 if (pValidationData) { 395 free_tspi(tspContext, pValidationData->rgbValidationData); 396 free_tspi(tspContext, pValidationData->rgbData); 397 pValidationData->rgbData = NULL; 398 pValidationData->ulDataLength = 0; 399 pValidationData->rgbValidationData = NULL; 400 pValidationData->ulValidationDataLength = 0; 401 } 402 goto done; 403 } 404 405 memcpy(*prgbEkResetData, eKResetAuth.digest, sizeof(eKResetAuth.digest)); 406 *pulEkResetDataLength = sizeof(eKResetAuth.digest); 407 } 408 409done: 410 free(newEK); 411 412 return result; 413} 414 415TSS_RESULT 416Tspi_TPM_RevokeEndorsementKey(TSS_HTPM hTPM, /* in */ 417 UINT32 ulEkResetDataLength, /* in */ 418 BYTE * rgbEkResetData) /* in */ 419{ 420 TSS_HCONTEXT tspContext; 421 TPM_DIGEST eKResetAuth; 422 TSS_RESULT result; 423 424 if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext))) 425 return result; 426 427 if (ulEkResetDataLength < sizeof(eKResetAuth.digest) || !rgbEkResetData) 428 return TSPERR(TSS_E_BAD_PARAMETER); 429 430 memcpy(eKResetAuth.digest, rgbEkResetData, sizeof(eKResetAuth.digest)); 431 432 if ((result = RPC_RevokeEndorsementKeyPair(tspContext, &eKResetAuth))) 433 return result; 434 435 return result; 436} 437#endif 438 439