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