1 /* Software-based Trusted Platform Module (TPM) Emulator
2 * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>
3 *
4 * This module is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
8 *
9 * This module is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * $Id: tpm_crypto.c 444 2010-06-12 09:14:18Z mast $
15 */
16
17 #include "tpm_emulator.h"
18 #include "tpm_commands.h"
19 #include "tpm_data.h"
20 #include "tpm_handles.h"
21 #include "crypto/sha1.h"
22 #include "crypto/hmac.h"
23 #include "crypto/rc4.h"
24 #include "tpm_marshalling.h"
25
26 /*
27 * Cryptographic Functions ([TPM_Part3], Section 13)
28 */
29
30 static tpm_sha1_ctx_t sha1_ctx;
31 static BOOL sha1_ctx_valid = FALSE;
32
TPM_SHA1Start(UINT32 * maxNumBytes)33 TPM_RESULT TPM_SHA1Start(UINT32 *maxNumBytes)
34 {
35 info("TPM_SHA1Start()");
36 tpm_sha1_init(&sha1_ctx);
37 sha1_ctx_valid = TRUE;
38 /* this limit was arbitrarily chosen */
39 *maxNumBytes = 2048;
40 return TPM_SUCCESS;
41 }
42
TPM_SHA1Update(UINT32 numBytes,BYTE * hashData)43 TPM_RESULT TPM_SHA1Update(UINT32 numBytes, BYTE *hashData)
44 {
45 info("TPM_SHA1Update()");
46 if (!sha1_ctx_valid) return TPM_SHA_THREAD;
47 tpm_sha1_update(&sha1_ctx, hashData, numBytes);
48 return TPM_SUCCESS;
49 }
50
TPM_SHA1Complete(UINT32 hashDataSize,BYTE * hashData,TPM_DIGEST * hashValue)51 TPM_RESULT TPM_SHA1Complete(UINT32 hashDataSize, BYTE *hashData,
52 TPM_DIGEST *hashValue)
53 {
54 info("TPM_SHA1Complete()");
55 if (!sha1_ctx_valid) return TPM_SHA_THREAD;
56 sha1_ctx_valid = FALSE;
57 tpm_sha1_update(&sha1_ctx, hashData, hashDataSize);
58 tpm_sha1_final(&sha1_ctx, hashValue->digest);
59 return TPM_SUCCESS;
60 }
61
TPM_SHA1CompleteExtend(TPM_PCRINDEX pcrNum,UINT32 hashDataSize,BYTE * hashData,TPM_DIGEST * hashValue,TPM_PCRVALUE * outDigest)62 TPM_RESULT TPM_SHA1CompleteExtend(TPM_PCRINDEX pcrNum, UINT32 hashDataSize,
63 BYTE *hashData, TPM_DIGEST *hashValue,
64 TPM_PCRVALUE *outDigest)
65 {
66 TPM_RESULT res;
67 info("TPM_SHA1CompleteExtend()");
68 res = TPM_SHA1Complete(hashDataSize, hashData, hashValue);
69 if (res != TPM_SUCCESS) return res;
70 return TPM_Extend(pcrNum, hashValue, outDigest);
71 }
72
tpm_verify(TPM_PUBKEY_DATA * key,TPM_AUTH * auth,BOOL isInfo,BYTE * data,UINT32 dataSize,BYTE * sig,UINT32 sigSize)73 TPM_RESULT tpm_verify(TPM_PUBKEY_DATA *key, TPM_AUTH *auth, BOOL isInfo,
74 BYTE *data, UINT32 dataSize, BYTE *sig, UINT32 sigSize)
75 {
76 if (sigSize != key->key.size >> 3) return TPM_BAD_SIGNATURE;
77 if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) {
78 /* use signature scheme PKCS1_SHA1_RAW */
79 if (dataSize != 20) return TPM_BAD_PARAMETER;
80 if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_SHA1_RAW,
81 data, dataSize, sig) != 0) return TPM_BAD_SIGNATURE;
82 } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_DER) {
83 /* use signature scheme PKCS1_DER */
84 if ((dataSize + 11) > (UINT32)(key->key.size >> 3)
85 || dataSize == 0) return TPM_BAD_PARAMETER;
86 if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_DER,
87 data, dataSize, sig) != 0) return TPM_BAD_SIGNATURE;
88 } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO && !isInfo) {
89 /* use signature scheme PKCS1_SHA1 and TPM_SIGN_INFO container */
90 BYTE buf[dataSize + 30];
91 if ((dataSize + 30) > (UINT32)(key->key.size >> 3)
92 || dataSize == 0) return TPM_BAD_PARAMETER;
93 /* setup TPM_SIGN_INFO structure */
94 memcpy(&buf[0], "\x00\x05SIGN", 6);
95 memcpy(&buf[6], auth->nonceOdd.nonce, 20);
96 buf[26] = (dataSize >> 24) & 0xff;
97 buf[27] = (dataSize >> 16) & 0xff;
98 buf[28] = (dataSize >> 8) & 0xff;
99 buf[29] = (dataSize ) & 0xff;
100 memcpy(&buf[30], data, dataSize);
101 if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_SHA1,
102 data, dataSize, sig) != 0) return TPM_BAD_SIGNATURE;
103 } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO && isInfo) {
104 /* TPM_SIGN_INFO structure is already set up */
105 if (dataSize > (UINT32)(key->key.size >> 3)
106 || dataSize == 0) return TPM_BAD_PARAMETER;
107 if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_SHA1,
108 data, dataSize, sig) != 0) return TPM_BAD_SIGNATURE;
109 } else {
110 return TPM_INVALID_KEYUSAGE;
111 }
112 return TPM_SUCCESS;
113 }
114
tpm_sign(TPM_KEY_DATA * key,TPM_AUTH * auth,BOOL isInfo,BYTE * areaToSign,UINT32 areaToSignSize,BYTE ** sig,UINT32 * sigSize)115 TPM_RESULT tpm_sign(TPM_KEY_DATA *key, TPM_AUTH *auth, BOOL isInfo,
116 BYTE *areaToSign, UINT32 areaToSignSize,
117 BYTE **sig, UINT32 *sigSize)
118 {
119 if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) {
120 /* use signature scheme PKCS1_SHA1_RAW */
121 if (areaToSignSize != 20) return TPM_BAD_PARAMETER;
122 *sigSize = key->key.size >> 3;
123 *sig = tpm_malloc(*sigSize);
124 if (*sig == NULL || tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1_RAW,
125 areaToSign, areaToSignSize, *sig)) {
126 tpm_free(*sig);
127 return TPM_FAIL;
128 }
129 } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_DER) {
130 /* use signature scheme PKCS1_DER */
131 if ((areaToSignSize + 11) > (UINT32)(key->key.size >> 3)
132 || areaToSignSize == 0) return TPM_BAD_PARAMETER;
133 *sigSize = key->key.size >> 3;
134 *sig = tpm_malloc(*sigSize);
135 if (*sig == NULL || tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_DER,
136 areaToSign, areaToSignSize, *sig)) {
137 tpm_free(*sig);
138 return TPM_FAIL;
139 }
140 } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO && !isInfo) {
141 /* use signature scheme PKCS1_SHA1 and TPM_SIGN_INFO container */
142 BYTE buf[areaToSignSize + 30];
143 if ((areaToSignSize + 30) > (UINT32)(key->key.size >> 3)
144 || areaToSignSize == 0) return TPM_BAD_PARAMETER;
145 *sigSize = key->key.size >> 3;
146 *sig = tpm_malloc(*sigSize);
147 if (*sig == NULL) return TPM_FAIL;
148 /* setup TPM_SIGN_INFO structure */
149 memcpy(&buf[0], "\x00\x05SIGN", 6);
150 memcpy(&buf[6], auth->nonceOdd.nonce, 20);
151 buf[26] = (areaToSignSize >> 24) & 0xff;
152 buf[27] = (areaToSignSize >> 16) & 0xff;
153 buf[28] = (areaToSignSize >> 8) & 0xff;
154 buf[29] = (areaToSignSize ) & 0xff;
155 memcpy(&buf[30], areaToSign, areaToSignSize);
156 if (tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1,
157 buf, areaToSignSize + 30, *sig)) {
158 tpm_free(*sig);
159 return TPM_FAIL;
160 }
161 } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO && isInfo) {
162 /* TPM_SIGN_INFO structure is already set up */
163 if (areaToSignSize > (UINT32)(key->key.size >> 3)
164 || areaToSignSize == 0) return TPM_BAD_PARAMETER;
165 *sigSize = key->key.size >> 3;
166 *sig = tpm_malloc(*sigSize);
167 if (*sig == NULL) return TPM_FAIL;
168 if (tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1,
169 areaToSign, areaToSignSize, *sig)) {
170 tpm_free(*sig);
171 return TPM_FAIL;
172 }
173 } else {
174 return TPM_INVALID_KEYUSAGE;
175 }
176 return TPM_SUCCESS;
177 }
178
TPM_Sign(TPM_KEY_HANDLE keyHandle,UINT32 areaToSignSize,BYTE * areaToSign,TPM_AUTH * auth1,UINT32 * sigSize,BYTE ** sig)179 TPM_RESULT TPM_Sign(TPM_KEY_HANDLE keyHandle, UINT32 areaToSignSize,
180 BYTE *areaToSign, TPM_AUTH *auth1,
181 UINT32 *sigSize, BYTE **sig)
182 {
183 TPM_RESULT res;
184 TPM_KEY_DATA *key;
185 info("TPM_Sign()");
186 /* get key */
187 key = tpm_get_key(keyHandle);
188 if (key == NULL) return TPM_INVALID_KEYHANDLE;
189 /* verify authorization */
190 if (auth1->authHandle != TPM_INVALID_HANDLE
191 || key->authDataUsage != TPM_AUTH_NEVER) {
192 res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);
193 if (res != TPM_SUCCESS) return res;
194 }
195 if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_LEGACY)
196 return TPM_INVALID_KEYUSAGE;
197 /* sign data */
198 return tpm_sign(key, auth1, FALSE, areaToSign, areaToSignSize, sig, sigSize);
199 }
200
tpm_get_random_bytes(void * buf,size_t nbytes)201 void tpm_get_random_bytes(void *buf, size_t nbytes)
202 {
203 if (tpmConf & TPM_CONF_USE_INTERNAL_PRNG) {
204 tpm_rc4_ctx_t ctx;
205 tpm_rc4_init(&ctx, tpmData.permanent.data.rngState,
206 sizeof(tpmData.permanent.data.rngState));
207 tpm_rc4_crypt(&ctx, buf, buf, nbytes);
208 tpm_rc4_crypt(&ctx, tpmData.permanent.data.rngState,
209 tpmData.permanent.data.rngState, sizeof(tpmData.permanent.data.rngState));
210 } else {
211 tpm_get_extern_random_bytes(buf, nbytes);
212 }
213 }
214
TPM_GetRandom(UINT32 bytesRequested,UINT32 * randomBytesSize,BYTE ** randomBytes)215 TPM_RESULT TPM_GetRandom(UINT32 bytesRequested, UINT32 *randomBytesSize,
216 BYTE **randomBytes)
217 {
218 info("TPM_GetRandom()");
219 *randomBytesSize = (bytesRequested < 2048) ? bytesRequested : 2048;
220 *randomBytes = tpm_malloc(*randomBytesSize);
221 if (*randomBytes == NULL) return TPM_SIZE;
222 tpm_get_random_bytes(*randomBytes, *randomBytesSize);
223 return TPM_SUCCESS;
224 }
225
TPM_StirRandom(UINT32 dataSize,BYTE * inData)226 TPM_RESULT TPM_StirRandom(UINT32 dataSize, BYTE *inData)
227 {
228 info("TPM_StirRandom()");
229 UINT32 i, length = sizeof(tpmData.permanent.data.rngState);
230 while (dataSize > length) {
231 for (i = 0; i < length; i++) {
232 tpmData.permanent.data.rngState[i] ^= *inData++;
233 }
234 dataSize -= length;
235 }
236 for (i = 0; i < dataSize; i++) {
237 tpmData.permanent.data.rngState[i] ^= *inData++;
238 }
239 return TPM_SUCCESS;
240 }
241
TPM_CertifyKey(TPM_KEY_HANDLE certHandle,TPM_KEY_HANDLE keyHandle,TPM_NONCE * antiReplay,TPM_AUTH * auth1,TPM_AUTH * auth2,TPM_CERTIFY_INFO * certifyInfo,UINT32 * outDataSize,BYTE ** outData)242 TPM_RESULT TPM_CertifyKey(TPM_KEY_HANDLE certHandle, TPM_KEY_HANDLE keyHandle,
243 TPM_NONCE *antiReplay, TPM_AUTH *auth1,
244 TPM_AUTH *auth2, TPM_CERTIFY_INFO *certifyInfo,
245 UINT32 *outDataSize, BYTE **outData)
246 {
247 TPM_RESULT res;
248 TPM_KEY_DATA *cert, *key;
249 tpm_sha1_ctx_t sha1_ctx;
250 BYTE *buf, *p;
251 UINT32 length;
252 info("TPM_CertifyKey()");
253 /* get keys */
254 cert = tpm_get_key(certHandle);
255 if (cert == NULL) return TPM_INVALID_KEYHANDLE;
256 key = tpm_get_key(keyHandle);
257 if (key == NULL) return TPM_INVALID_KEYHANDLE;
258 /* verify authorization */
259 if (auth2->authHandle != TPM_INVALID_HANDLE
260 || cert->authDataUsage != TPM_AUTH_NEVER) {
261 res = tpm_verify_auth(auth1, cert->usageAuth, certHandle);
262 if (res != TPM_SUCCESS) return res;
263 }
264 if (auth1->authHandle != TPM_INVALID_HANDLE
265 || key->authDataUsage != TPM_AUTH_NEVER) {
266 res = tpm_verify_auth(auth2, key->usageAuth, keyHandle);
267 if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res;
268 }
269 /* verify key usage */
270 if (cert->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1
271 && cert->sigScheme != TPM_SS_RSASSAPKCS1v15_INFO) return TPM_BAD_SCHEME;
272 if (cert->keyUsage == TPM_KEY_IDENTITY
273 && (key->keyFlags & TPM_KEY_FLAG_MIGRATABLE)
274 && !(key->keyFlags & TPM_KEY_FLAG_AUTHORITY)) return TPM_MIGRATEFAIL;
275 if (key->keyFlags & TPM_KEY_FLAG_HAS_PCR) {
276 if (!(key->keyFlags & TPM_KEY_FLAG_PCR_IGNORE)) {
277 TPM_DIGEST digest;
278 res = tpm_compute_pcr_digest(&key->pcrInfo.releasePCRSelection,
279 &digest, NULL);
280 if (res != TPM_SUCCESS) return res;
281 if (memcmp(&digest, &key->pcrInfo.digestAtRelease, sizeof(TPM_DIGEST)))
282 return TPM_WRONGPCRVAL;
283 if (key->pcrInfo.tag == TPM_TAG_PCR_INFO_LONG
284 && !(key->pcrInfo.localityAtRelease
285 & (1 << tpmData.stany.flags.localityModifier)))
286 return TPM_BAD_LOCALITY;
287 }
288 /* if sizeOfSelect is two use a TPM_CERTIFY_INFO structure ... */
289 if (key->pcrInfo.releasePCRSelection.sizeOfSelect == 2) {
290 certifyInfo->tag = 0x0101;
291 certifyInfo->fill = 0x0000;
292 certifyInfo->migrationAuthoritySize = 0;
293 memcpy(&certifyInfo->PCRInfo, &key->pcrInfo, sizeof(TPM_PCR_INFO));
294 memset(&certifyInfo->PCRInfo.digestAtCreation, 0, sizeof(TPM_DIGEST));
295 certifyInfo->PCRInfoSize = sizeof(TPM_PCR_INFO);
296 /* ... otherwise use a TPM_CERTIFY_INFO2 structure */
297 } else {
298 certifyInfo->tag = TPM_TAG_CERTIFY_INFO2;
299 certifyInfo->fill = 0x0000;
300 certifyInfo->migrationAuthoritySize = 0;
301 memcpy(&certifyInfo->PCRInfo, &key->pcrInfo, sizeof(TPM_PCR_INFO));
302 certifyInfo->PCRInfoSize = sizeof(TPM_PCR_INFO);
303 }
304 } else {
305 /* setup TPM_CERTIFY_INFO structure */
306 certifyInfo->tag = 0x0101;
307 certifyInfo->fill = 0x0000;
308 certifyInfo->migrationAuthoritySize = 0;
309 certifyInfo->PCRInfoSize = 0;
310 }
311 /* setup CERTIFY_INFO[2] structure */
312 certifyInfo->keyUsage = key->keyUsage;
313 certifyInfo->keyFlags = key->keyFlags & TPM_KEY_FLAG_MASK;
314 certifyInfo->authDataUsage = key->authDataUsage;
315 certifyInfo->parentPCRStatus = key->parentPCRStatus;
316 if (tpm_setup_key_parms(key, &certifyInfo->algorithmParms)) return TPM_FAIL;
317 memcpy(&certifyInfo->data, antiReplay, sizeof(TPM_NONCE));
318 /* compute pubKeyDigest */
319 length = key->key.size >> 3;
320 buf = tpm_malloc(length);
321 if (buf == NULL) {
322 free_TPM_KEY_PARMS(certifyInfo->algorithmParms);
323 return TPM_FAIL;
324 }
325 tpm_rsa_export_modulus(&key->key, buf, NULL);
326 tpm_sha1_init(&sha1_ctx);
327 tpm_sha1_update(&sha1_ctx, buf, length);
328 tpm_sha1_final(&sha1_ctx, certifyInfo->pubkeyDigest.digest);
329 tpm_free(buf);
330 /* compute the digest of the CERTIFY_INFO[2] structure and sign it */
331 length = sizeof_TPM_CERTIFY_INFO((*certifyInfo));
332 p = buf = tpm_malloc(length);
333 if (buf == NULL
334 || tpm_marshal_TPM_CERTIFY_INFO(&p, &length, certifyInfo)) {
335 free_TPM_KEY_PARMS(certifyInfo->algorithmParms);
336 return TPM_FAIL;
337 }
338 length = sizeof_TPM_CERTIFY_INFO((*certifyInfo));
339 tpm_sha1_init(&sha1_ctx);
340 tpm_sha1_update(&sha1_ctx, buf, length);
341 tpm_sha1_final(&sha1_ctx, buf);
342 res = tpm_sign(cert, auth1, FALSE, buf, SHA1_DIGEST_LENGTH, outData, outDataSize);
343 tpm_free(buf);
344 if (res != TPM_SUCCESS) {
345 free_TPM_KEY_PARMS(certifyInfo->algorithmParms);
346 return res;
347 }
348 return TPM_SUCCESS;
349 }
350
TPM_CertifyKey2(TPM_KEY_HANDLE keyHandle,TPM_KEY_HANDLE certHandle,TPM_DIGEST * migrationPubDigest,TPM_NONCE * antiReplay,TPM_AUTH * auth1,TPM_AUTH * auth2,TPM_CERTIFY_INFO * certifyInfo,UINT32 * outDataSize,BYTE ** outData)351 TPM_RESULT TPM_CertifyKey2(TPM_KEY_HANDLE keyHandle, TPM_KEY_HANDLE certHandle,
352 TPM_DIGEST *migrationPubDigest,
353 TPM_NONCE *antiReplay, TPM_AUTH *auth1,
354 TPM_AUTH *auth2, TPM_CERTIFY_INFO *certifyInfo,
355 UINT32 *outDataSize, BYTE **outData)
356 {
357 TPM_RESULT res;
358 TPM_KEY_DATA *cert, *key;
359 tpm_sha1_ctx_t sha1_ctx;
360 BYTE *buf, *p;
361 UINT32 length;
362 info("TPM_CertifyKey2()");
363 /* get keys */
364 key = tpm_get_key(keyHandle);
365 if (key == NULL) return TPM_INVALID_KEYHANDLE;
366 cert = tpm_get_key(certHandle);
367 if (cert == NULL) return TPM_INVALID_KEYHANDLE;
368 /* verify authorization */
369 if (auth2->authHandle != TPM_INVALID_HANDLE
370 || cert->authDataUsage != TPM_AUTH_NEVER) {
371 res = tpm_verify_auth(auth2, cert->usageAuth, certHandle);
372 if (res != TPM_SUCCESS) return res;
373 }
374 if (auth1->authHandle != TPM_INVALID_HANDLE
375 || key->authDataUsage != TPM_AUTH_NEVER) {
376 res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);
377 if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res;
378 }
379 /* verify key usage */
380 if (cert->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) return TPM_BAD_SCHEME;
381 if (cert->keyUsage == TPM_KEY_IDENTITY
382 && (key->keyFlags & TPM_KEY_FLAG_MIGRATABLE)
383 && !(key->keyFlags & TPM_KEY_FLAG_AUTHORITY)) return TPM_MIGRATEFAIL;
384 if (key->keyFlags & TPM_KEY_FLAG_HAS_PCR) {
385 if (!(key->keyFlags & TPM_KEY_FLAG_PCR_IGNORE)) {
386 TPM_DIGEST digest;
387 res = tpm_compute_pcr_digest(&key->pcrInfo.releasePCRSelection,
388 &digest, NULL);
389 if (res != TPM_SUCCESS) return res;
390 if (memcmp(&digest, &key->pcrInfo.digestAtRelease, sizeof(TPM_DIGEST)))
391 return TPM_WRONGPCRVAL;
392 if (key->pcrInfo.tag == TPM_TAG_PCR_INFO_LONG
393 && !(key->pcrInfo.localityAtRelease
394 & (1 << tpmData.stany.flags.localityModifier)))
395 return TPM_BAD_LOCALITY;
396 }
397 memcpy(&certifyInfo->PCRInfo, &key->pcrInfo, sizeof(TPM_PCR_INFO));
398 certifyInfo->PCRInfoSize = sizeof(certifyInfo->PCRInfo);
399 } else {
400 certifyInfo->PCRInfoSize = 0;
401 }
402 /* setup migration authority values */
403 if (key->payload == TPM_PT_MIGRATE_RESTRICTED
404 || key->payload == TPM_PT_MIGRATE_EXTERNAL) {
405 TPM_PUBKEY pubKey;
406 TPM_DIGEST keyDigest;
407 BYTE buf[SHA1_DIGEST_LENGTH];
408 tpm_hmac_ctx_t hmac_ctx;
409 tpm_sha1_ctx_t sha1_ctx;
410 /* compute digest of public key */
411 if (tpm_extract_pubkey(key, &pubKey) != 0) {
412 debug("tpm_extract_pubkey() failed");
413 return TPM_FAIL;
414 }
415 if (tpm_compute_pubkey_digest(&pubKey, &keyDigest) != 0) {
416 debug("tpm_compute_pubkey_digest() failed.");
417 free_TPM_PUBKEY(pubKey);
418 return TPM_FAIL;
419 }
420 free_TPM_PUBKEY(pubKey);
421 /* verify migration authorization */
422 buf[0] = (TPM_TAG_CMK_MIGAUTH >> 8) & 0xff;
423 buf[1] = TPM_TAG_CMK_MIGAUTH & 0xff;
424 tpm_hmac_init(&hmac_ctx, tpmData.permanent.data.tpmProof.nonce, sizeof(TPM_NONCE));
425 tpm_hmac_update(&hmac_ctx, buf, 2);
426 tpm_hmac_update(&hmac_ctx, migrationPubDigest->digest, sizeof(TPM_DIGEST));
427 tpm_hmac_update(&hmac_ctx, keyDigest.digest, sizeof(TPM_DIGEST));
428 tpm_hmac_final(&hmac_ctx, buf);
429 if (memcmp(key->migrationAuth, buf, sizeof(TPM_SECRET)) != 0) return TPM_MA_SOURCE;
430 /* compute migrationAuthority */
431 certifyInfo->migrationAuthoritySize = SHA1_DIGEST_LENGTH;
432 certifyInfo->migrationAuthority = tpm_malloc(certifyInfo->migrationAuthoritySize);
433 if (certifyInfo->migrationAuthority == NULL) return TPM_NOSPACE;
434 tpm_sha1_init(&sha1_ctx);
435 tpm_sha1_update(&sha1_ctx, migrationPubDigest->digest, sizeof(TPM_DIGEST));
436 buf[0] = key->payload;
437 tpm_sha1_update(&sha1_ctx, buf, 1);
438 tpm_sha1_final(&sha1_ctx, certifyInfo->migrationAuthority);
439 certifyInfo->payloadType = key->payload;
440 } else {
441 certifyInfo->migrationAuthoritySize = 0;
442 certifyInfo->migrationAuthority = 0;
443 certifyInfo->payloadType = TPM_PT_ASYM;
444 }
445 /* setup CERTIFY_INFO2 structure */
446 certifyInfo->tag = TPM_TAG_CERTIFY_INFO2;
447 certifyInfo->fill = 0x0000;
448 certifyInfo->keyUsage = key->keyUsage;
449 certifyInfo->keyFlags = key->keyFlags & TPM_KEY_FLAG_MASK;
450 certifyInfo->authDataUsage = key->authDataUsage;
451 certifyInfo->parentPCRStatus = key->parentPCRStatus;
452 if (tpm_setup_key_parms(key, &certifyInfo->algorithmParms)) return TPM_FAIL;
453 memcpy(&certifyInfo->data, antiReplay, sizeof(TPM_NONCE));
454 /* compute pubKeyDigest */
455 length = key->key.size >> 3;
456 buf = tpm_malloc(length);
457 if (buf == NULL) {
458 free_TPM_KEY_PARMS(certifyInfo->algorithmParms);
459 return TPM_FAIL;
460 }
461 tpm_rsa_export_modulus(&key->key, buf, NULL);
462 tpm_sha1_init(&sha1_ctx);
463 tpm_sha1_update(&sha1_ctx, buf, length);
464 tpm_sha1_final(&sha1_ctx, certifyInfo->pubkeyDigest.digest);
465 tpm_free(buf);
466 /* compute the digest of the CERTIFY_INFO[2] structure and sign it */
467 length = sizeof_TPM_CERTIFY_INFO((*certifyInfo));
468 p = buf = tpm_malloc(length);
469 if (buf == NULL
470 || tpm_marshal_TPM_CERTIFY_INFO(&p, &length, certifyInfo)) {
471 free_TPM_KEY_PARMS(certifyInfo->algorithmParms);
472 return TPM_FAIL;
473 }
474 length = sizeof_TPM_CERTIFY_INFO((*certifyInfo));
475 tpm_sha1_init(&sha1_ctx);
476 tpm_sha1_update(&sha1_ctx, buf, length);
477 tpm_sha1_final(&sha1_ctx, buf);
478 res = tpm_sign(cert, auth2, FALSE, buf, SHA1_DIGEST_LENGTH, outData, outDataSize);
479 tpm_free(buf);
480 if (res != TPM_SUCCESS) {
481 free_TPM_KEY_PARMS(certifyInfo->algorithmParms);
482 return res;
483 }
484 return TPM_SUCCESS;
485 }
486
487