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
25 TSS_RESULT
Tspi_TPM_CreateEndorsementKey(TSS_HTPM hTPM,TSS_HKEY hKey,TSS_VALIDATION * pValidationData)26 Tspi_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
128 done:
129 free(newEK);
130
131 return result;
132 }
133
134 TSS_RESULT
Tspi_TPM_GetPubEndorsementKey(TSS_HTPM hTPM,TSS_BOOL fOwnerAuthorized,TSS_VALIDATION * pValidationData,TSS_HKEY * phEndorsementPubKey)135 Tspi_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
255 done:
256 free(pubEK);
257 return result;
258 }
259
260 #ifdef TSS_BUILD_TSS12
261 TSS_RESULT
Tspi_TPM_CreateRevocableEndorsementKey(TSS_HTPM hTPM,TSS_HKEY hKey,TSS_VALIDATION * pValidationData,UINT32 * pulEkResetDataLength,BYTE ** prgbEkResetData)262 Tspi_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
409 done:
410 free(newEK);
411
412 return result;
413 }
414
415 TSS_RESULT
Tspi_TPM_RevokeEndorsementKey(TSS_HTPM hTPM,UINT32 ulEkResetDataLength,BYTE * rgbEkResetData)416 Tspi_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