xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tspi/tspi_ek.c (revision 1023804e3833a0bd94414f2545512128f6502c74)
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