1 /* Software-based Mobile Trusted Module (MTM) Emulator
2  * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>
3  * Copyright (C) 2007 Jan-Erik Ekberg <jan-erik.ekberg@nokia.com>,
4  *                    Nokia Corporation and/or its subsidiary(-ies)
5  *
6  * This module is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published
8  * by the Free Software Foundation; either version 2 of the License,
9  * or (at your option) any later version.
10  *
11  * This module is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * $Id$
17  */
18 
19 #include "mtm_structures.h"
20 #include "mtm_commands.h"
21 #include "tpm/tpm_commands.h"
22 #include "mtm_data.h"
23 #include "tpm/tpm_data.h"
24 #include "mtm_handles.h"
25 #include "mtm_marshalling.h"
26 #include "crypto/hmac.h"
27 #include "crypto/rsa.h"
28 #include "crypto/sha1.h"
29 
copy_TPM_RIM_CERTIFICATE(TPM_RIM_CERTIFICATE * src,TPM_RIM_CERTIFICATE * dst)30 static int copy_TPM_RIM_CERTIFICATE(TPM_RIM_CERTIFICATE* src, TPM_RIM_CERTIFICATE* dst)
31 {
32   memcpy(dst, src, sizeof(TPM_RIM_CERTIFICATE));
33   if (dst->extensionDigestSize > 0) {
34     dst->extensionDigestData = tpm_malloc(dst->extensionDigestSize);
35     if (dst->extensionDigestData == NULL) return -1;
36     memcpy(dst->extensionDigestData, src->extensionDigestData,
37            dst->extensionDigestSize);
38   } else {
39     dst->extensionDigestData = NULL;
40   }
41   if (dst->integrityCheckSize > 0) {
42     dst->integrityCheckData = tpm_malloc(dst->integrityCheckSize);
43     if (dst->integrityCheckData == NULL) {
44       tpm_free(dst->extensionDigestData);
45       return -1;
46     }
47     memcpy(dst->integrityCheckData, src->integrityCheckData,
48            dst->integrityCheckSize);
49   } else {
50     dst->integrityCheckData = NULL;
51   }
52   return 0;
53 }
54 
compute_rim_certificate_digest(TPM_RIM_CERTIFICATE * rimCert,BYTE * digest)55 static int compute_rim_certificate_digest(TPM_RIM_CERTIFICATE* rimCert, BYTE *digest)
56 {
57   tpm_sha1_ctx_t sha1_ctx;
58   BYTE *buf, *ptr;
59   UINT32 buf_len, len;
60   UINT32 integrityCheckSize;
61 
62   /* marshal certificate */
63   integrityCheckSize = rimCert->integrityCheckSize;
64   rimCert->integrityCheckSize = 0;
65   buf_len = len = sizeof_TPM_RIM_CERTIFICATE((*rimCert));
66   buf = ptr = tpm_malloc(buf_len);
67   if (buf == NULL || tpm_marshal_TPM_RIM_CERTIFICATE(&ptr, &len, rimCert)) {
68     rimCert->integrityCheckSize = integrityCheckSize;
69     tpm_free(buf);
70     return -1;
71   }
72   rimCert->integrityCheckSize = integrityCheckSize;
73   /* compute hmac */
74   tpm_sha1_init(&sha1_ctx);
75   tpm_sha1_update(&sha1_ctx, buf, buf_len);
76   tpm_sha1_final(&sha1_ctx, digest);
77   tpm_free(buf);
78   return 0;
79 }
80 
compute_rim_certificate_hmac(TPM_RIM_CERTIFICATE * rimCert,BYTE * digest)81 static int compute_rim_certificate_hmac(TPM_RIM_CERTIFICATE* rimCert, BYTE *digest)
82 {
83   tpm_hmac_ctx_t hmac_ctx;
84   BYTE *buf, *ptr;
85   UINT32 buf_len, len;
86   UINT32 integrityCheckSize;
87 
88   /* marshal certificate */
89   integrityCheckSize = rimCert->integrityCheckSize;
90   rimCert->integrityCheckSize = 0;
91   buf_len = len = sizeof_TPM_RIM_CERTIFICATE((*rimCert));
92   buf = ptr = tpm_malloc(buf_len);
93   if (buf == NULL || tpm_marshal_TPM_RIM_CERTIFICATE(&ptr, &len, rimCert)) {
94     rimCert->integrityCheckSize = integrityCheckSize;
95     tpm_free(buf);
96     return -1;
97   }
98   rimCert->integrityCheckSize = integrityCheckSize;
99   /* compute hmac */
100   tpm_hmac_init(&hmac_ctx, mtmData.permanent.data.internalVerificationKey,
101                 sizeof(TPM_SECRET));
102   tpm_hmac_update(&hmac_ctx, buf, buf_len);
103   tpm_hmac_final(&hmac_ctx, digest);
104   tpm_free(buf);
105   return 0;
106 }
107 
verify_rim_certificate(TPM_RIM_CERTIFICATE * rimCert)108 static TPM_RESULT verify_rim_certificate(TPM_RIM_CERTIFICATE *rimCert)
109 {
110   /* check parrentID */
111   debug("parentId = %08x", rimCert->parentId);
112   if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_NONE) return TPM_KEYNOTFOUND;
113   /* verify certificate with appropiate key */
114   if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_INTERNAL) {
115     BYTE digest[SHA1_DIGEST_LENGTH];
116     debug("internal verification");
117     if (compute_rim_certificate_hmac(rimCert, digest) != 0) {
118       debug("compute_rim_certificate_hmac() failed");
119       return TPM_FAIL;
120     }
121     /* check hmac */
122     if (memcmp(digest, rimCert->integrityCheckData, SHA1_DIGEST_LENGTH) != 0) {
123       debug("verification failed");
124       return TPM_AUTHFAIL;
125     } else {
126       debug("verification succeeded");
127       return TPM_SUCCESS;
128     }
129   } else {
130     BYTE digest[SHA1_DIGEST_LENGTH];
131     /* get verification key */
132     MTM_KEY_DATA *key = mtm_get_key_by_id(rimCert->parentId);
133     if (key == NULL) {
134       return TPM_KEYNOTFOUND;
135     }
136     /* compute digest */
137     if (compute_rim_certificate_digest(rimCert, digest) != 0) {
138       debug("compute_rim_certificate_digest() failed");
139       return TPM_FAIL;
140     }
141     /* check key properties */
142     if (key->keyAlgorithm != TPM_ALG_RSA
143         || key->keyScheme != TPM_SS_RSASSAPKCS1v15_SHA1) {
144       debug("invalid signature scheme");
145       return TPM_BAD_SCHEME;
146     }
147     /* verify signature */
148     if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_SHA1_RAW, digest, sizeof(digest),
149                        rimCert->integrityCheckData) != 0) {
150       debug("verification failed");
151       return TPM_AUTHFAIL;
152     } else {
153       debug("verification succeeded");
154       return TPM_SUCCESS;
155     }
156   }
157 }
158 
compute_verification_key_digest(TPM_VERIFICATION_KEY * key,BYTE * digest)159 static int compute_verification_key_digest(TPM_VERIFICATION_KEY *key, BYTE *digest)
160 {
161   tpm_sha1_ctx_t sha1_ctx;
162   BYTE *buf, *ptr;
163   UINT32 buf_len, len;
164   UINT32 integrityCheckSize;
165 
166   /* marshal certificate */
167   integrityCheckSize = key->integrityCheckSize;
168   key->integrityCheckSize = 0;
169   buf_len = len = sizeof_TPM_VERIFICATION_KEY((*key));
170   buf = ptr = tpm_malloc(buf_len);
171   if (buf == NULL || tpm_marshal_TPM_VERIFICATION_KEY(&ptr, &len, key)) {
172     key->integrityCheckSize = integrityCheckSize;
173     tpm_free(buf);
174     return -1;
175   }
176   key->integrityCheckSize = integrityCheckSize;
177   /* compute sha1 */
178   tpm_sha1_init(&sha1_ctx);
179   tpm_sha1_update(&sha1_ctx, buf, buf_len);
180   tpm_sha1_final(&sha1_ctx, digest);
181   tpm_free(buf);
182   return 0;
183 
184 }
185 
verify_verification_key(TPM_VERIFICATION_KEY * key,MTM_KEY_DATA * parentKey)186 static TPM_RESULT verify_verification_key(TPM_VERIFICATION_KEY *key, MTM_KEY_DATA *parentKey)
187 {
188   BYTE digest[SHA1_DIGEST_LENGTH];
189 
190   /* compute digest */
191   if (compute_verification_key_digest(key, digest) != 0) {
192     debug("compute_verification_key_digest() failed");
193     return TPM_FAIL;
194   }
195   /* check key properties */
196   if (parentKey->keyAlgorithm != TPM_ALG_RSA
197       || parentKey->keyScheme != TPM_SS_RSASSAPKCS1v15_SHA1) {
198     debug("invalid signature scheme");
199     return TPM_BAD_SCHEME;
200   }
201   /* verify signature */
202   if (tpm_rsa_verify(&parentKey->key, RSA_SSA_PKCS1_SHA1_RAW, digest, sizeof(digest),
203                      key->integrityCheckData) != 0) {
204     debug("verification failed");
205     return TPM_AUTHFAIL;
206   } else {
207     debug("verification succeeded");
208     return TPM_SUCCESS;
209   }
210 }
211 
store_verification_key(TPM_VERIFICATION_KEY * inKey,MTM_KEY_DATA * outKey)212 static int store_verification_key(TPM_VERIFICATION_KEY *inKey, MTM_KEY_DATA *outKey)
213 {
214   outKey->usageFlags = inKey->usageFlags;
215   outKey->parentId = inKey->parentId;
216   outKey->myId = inKey->myId;
217   outKey->keyAlgorithm = inKey->keyAlgorithm;
218   outKey->keyScheme = inKey->keyScheme;
219   BYTE *ptr = inKey->keyData;
220   UINT32 len = inKey->keySize;
221   if (tpm_unmarshal_RSAPub(&ptr, &len, &outKey->key) != 0) return -1;
222   return 0;
223 }
224 
MTM_InstallRIM(TPM_RIM_CERTIFICATE * rimCertIn,TPM_AUTH * auth1,TPM_RIM_CERTIFICATE * rimCertOut)225 TPM_RESULT MTM_InstallRIM(TPM_RIM_CERTIFICATE *rimCertIn, TPM_AUTH *auth1,
226                           TPM_RIM_CERTIFICATE *rimCertOut)
227 {
228   TPM_RESULT res;
229   TPM_ACTUAL_COUNT cntProtect;
230 
231   info("MTM_InstallRIM()");
232   /* 1 */
233   if (rimCertIn == NULL || rimCertIn->tag != TPM_TAG_RIM_CERTIFICATE)
234     return TPM_BAD_PARAMETER;
235   /* 2 */
236   res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, auth1->authHandle);
237   if (res != TPM_SUCCESS) return res;
238   /* 3 */
239   cntProtect = tpmData.permanent.data.counters[MTM_COUNTER_SELECT_RIMPROTECT].counter;
240   /* 5 */
241   rimCertIn->integrityCheckSize = SHA1_DIGEST_LENGTH;
242   if (copy_TPM_RIM_CERTIFICATE(rimCertIn, rimCertOut) != 0) {
243     debug("copy_TPM_RIM_CERTIFICATE() failed");
244     return TPM_FAIL;
245   }
246   /* 6, 7 */
247   if (rimCertIn->referenceCounter.counterSelection != MTM_COUNTER_SELECT_NONE) {
248     rimCertOut->referenceCounter.counterValue = cntProtect + 1;
249     rimCertOut->referenceCounter.counterSelection = MTM_COUNTER_SELECT_RIMPROTECT;
250   } else {
251     rimCertOut->referenceCounter.counterValue = 0;
252   }
253   /* 8 */
254   rimCertOut->parentId = TPM_VERIFICATION_KEY_ID_INTERNAL;
255   /* 10, 11, 12 */
256   if (compute_rim_certificate_hmac(rimCertOut, rimCertOut->integrityCheckData) != 0) {
257     debug("compute_rim_certificate_hmac() failed");
258     free_TPM_RIM_CERTIFICATE((*rimCertOut));
259     return TPM_FAIL;
260   }
261   /* 13 */
262   return TPM_SUCCESS;
263 }
264 
mtm_get_free_key(void)265 static TPM_VERIFICATION_KEY_HANDLE mtm_get_free_key(void)
266 {
267   int i;
268   for (i = 0; i < TPM_MAX_KEYS; i++) {
269     if (!mtmData.permanent.data.keys[i].valid) {
270       mtmData.permanent.data.keys[i].valid = TRUE;
271       return INDEX_TO_KEY_HANDLE(i);
272     }
273   }
274   return TPM_INVALID_HANDLE;
275 }
276 
277 
MTM_LoadVerificationKey(TPM_VERIFICATION_KEY_HANDLE parentKeyHandle,TPM_VERIFICATION_KEY * verificationKey,TPM_AUTH * auth1,TPM_VERIFICATION_KEY_HANDLE * verificationKeyHandle,BYTE * loadMethod)278 TPM_RESULT MTM_LoadVerificationKey(TPM_VERIFICATION_KEY_HANDLE parentKeyHandle,
279                                    TPM_VERIFICATION_KEY *verificationKey, TPM_AUTH *auth1,
280                                    TPM_VERIFICATION_KEY_HANDLE *verificationKeyHandle,
281                              	     BYTE *loadMethod)
282 {
283   TPM_RESULT res;
284   MTM_KEY_DATA *key;
285 
286   /* 1 */
287   if (verificationKey == NULL || verificationKey->tag != TPM_TAG_VERIFICATION_KEY)
288     return TPM_BAD_PARAMETER;
289   /* 2 */
290   *verificationKeyHandle = mtm_get_free_key();
291   key = mtm_get_key(*verificationKeyHandle);
292   if (key == NULL) {
293     debug("no free key slot available");
294     return TPM_NOSPACE;
295   }
296   *loadMethod = 0;
297   /* 3 */
298   if (mtmData.stany.flags.loadVerificationRootKeyEnabled) {
299     debug("TPM_VERIFICATION_KEY_ROOT_LOAD");
300     /* set integrityCheckRootData */
301     if (!mtmData.permanent.data.integrityCheckRootValid) {
302       if (compute_verification_key_digest(verificationKey,
303             mtmData.permanent.data.integrityCheckRootData) != 0) {
304         debug("compute_verification_key_digest() failed");
305         memset(key, 0, sizeof(*key));
306         return TPM_FAIL;
307       }
308       mtmData.permanent.data.integrityCheckRootValid = TRUE;
309     }
310     *loadMethod = TPM_VERIFICATION_KEY_ROOT_LOAD;
311   }
312   /* 4 */
313   if (*loadMethod == 0
314       && mtmData.permanent.data.integrityCheckRootValid) {
315     BYTE digest[SHA1_DIGEST_LENGTH];
316     if (compute_verification_key_digest(verificationKey, digest) != 0) {
317       debug("compute_verification_key_digest() failed");
318       memset(key, 0, sizeof(*key));
319       return TPM_FAIL;
320     }
321     if (memcmp(mtmData.permanent.data.integrityCheckRootData,
322                digest, SHA1_DIGEST_LENGTH) == 0) {
323       debug("TPM_VERIFICATION_KEY_INTEGRITY_CHECK_ROOT_DATA_LOAD");
324       *loadMethod = TPM_VERIFICATION_KEY_INTEGRITY_CHECK_ROOT_DATA_LOAD;
325     }
326   }
327   /* 5 */
328   if (*loadMethod == 0
329       && tpmData.permanent.flags.owned && auth1->authHandle != TPM_INVALID_HANDLE) {
330     TPM_RESULT res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
331     if (res != TPM_SUCCESS) {
332       memset(key, 0, sizeof(*key));
333       return res;
334     }
335     debug("TPM_VERIFICATION_KEY_OWNER_AUTHORIZED_LOAD");
336     *loadMethod = TPM_VERIFICATION_KEY_OWNER_AUTHORIZED_LOAD;
337   }
338   /* 6 */
339   if (*loadMethod == 0) {
340     MTM_KEY_DATA *parentKey = mtm_get_key(parentKeyHandle);
341     if (parentKey == NULL) {
342       debug("invalid parent key handle %08x", parentKeyHandle);
343       memset(key, 0, sizeof(*key));
344       return TPM_KEYNOTFOUND;
345     }
346     /* 7a-c */
347     if (!(parentKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_SIGN_RIMAUTH)) {
348       memset(key, 0, sizeof(*key));
349       return TPM_INVALID_KEYUSAGE;
350     }
351     if ((verificationKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTSTRAP)
352         && !(parentKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTSTRAP)) {
353       memset(key, 0, sizeof(*key));
354       return TPM_INVALID_KEYUSAGE;
355     }
356     if (key->parentId != parentKey->myId) {
357       debug("id mismatch: parentId = %08x keyId = %08x", key->parentId, parentKey->myId);
358       memset(key, 0, sizeof(*key));
359       return TPM_AUTHFAIL;
360     }
361     /* 7d */
362     res = verify_verification_key(verificationKey, parentKey);
363     if (res != TPM_SUCCESS) {
364       memset(key, 0, sizeof(*key));
365       return res;
366     }
367     /* 7e-g */
368     if (verificationKey->referenceCounter.counterSelection > MTM_COUNTER_SELECT_MAX)
369       return TPM_BAD_COUNTER;
370     if (verificationKey->referenceCounter.counterSelection == MTM_COUNTER_SELECT_BOOTSTRAP) {
371       if (verificationKey->referenceCounter.counterValue
372           < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter)
373         return TPM_BAD_COUNTER;
374     }
375     if (verificationKey->referenceCounter.counterSelection == MTM_COUNTER_SELECT_RIMPROTECT) {
376       if (verificationKey->referenceCounter.counterValue
377           < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_RIMPROTECT].counter)
378         return TPM_BAD_COUNTER;
379     }
380     /* 7j */
381     debug("TPM_VERIFICATION_KEY_CHAIN_AUTHORIZED_LOAD");
382     *loadMethod = TPM_VERIFICATION_KEY_CHAIN_AUTHORIZED_LOAD;
383   }
384   /* store verification key */
385   if (store_verification_key(verificationKey, key) != 0) {
386     debug("store_verification_key() failed");
387     memset(key, 0, sizeof(*key));
388     return TPM_FAIL;
389   }
390   return TPM_SUCCESS;
391 }
392 
MTM_LoadVerificationRootKeyDisable()393 TPM_RESULT MTM_LoadVerificationRootKeyDisable()
394 {
395   info("MTM_LoadVerificationRootKeyDisable()");
396   mtmData.stany.flags.loadVerificationRootKeyEnabled = FALSE;
397   mtmData.permanent.data.loadVerificationKeyMethods |= TPM_VERIFICATION_KEY_ROOT_LOAD;
398   return TPM_SUCCESS;
399 }
400 
MTM_VerifyRIMCert(TPM_RIM_CERTIFICATE * rimCert,TPM_VERIFICATION_KEY_HANDLE rimKeyHandle)401 TPM_RESULT MTM_VerifyRIMCert(TPM_RIM_CERTIFICATE* rimCert,
402                              TPM_VERIFICATION_KEY_HANDLE rimKeyHandle)
403 {
404   TPM_RESULT res;
405 
406   info("MTM_VerifyRIMCert()");
407   debug("key handle = %08x", rimKeyHandle);
408   /* 1 */
409   if (rimCert ==  NULL || rimCert->tag != TPM_TAG_RIM_CERTIFICATE)
410     return TPM_BAD_PARAMETER;
411   /* 2 */
412   if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_NONE)
413     return TPM_AUTHFAIL;
414   /* 3 */
415   if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_INTERNAL) {
416     return verify_rim_certificate(rimCert);
417   } else {
418     /* 4 */
419     MTM_KEY_DATA *rimKey = mtm_get_key(rimKeyHandle);
420     if (rimKey == NULL) return TPM_KEYNOTFOUND;
421     if ((rimKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_SIGN_RIMCERT) == 0)
422       return TPM_INVALID_KEYUSAGE;
423     if (rimCert->parentId != rimKey->myId) {
424       debug("id mismatch: parentId = %08x keyId = %08x", rimCert->parentId, rimKey->myId);
425       return TPM_AUTHFAIL;
426     }
427     res = verify_rim_certificate(rimCert);
428     if (res != TPM_SUCCESS) return res;
429   }
430   /* 5 */
431   if (rimCert->referenceCounter.counterSelection > MTM_COUNTER_SELECT_MAX)
432     return TPM_BAD_COUNTER;
433   /* 6 */
434   if (rimCert->referenceCounter.counterSelection == MTM_COUNTER_SELECT_BOOTSTRAP) {
435     if (rimCert->referenceCounter.counterValue
436         < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter)
437       return TPM_BAD_COUNTER;
438   }
439   /* 7 */
440   if (rimCert->referenceCounter.counterSelection == MTM_COUNTER_SELECT_RIMPROTECT) {
441     if (rimCert->referenceCounter.counterValue
442         < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_RIMPROTECT].counter)
443       return TPM_BAD_COUNTER;
444   }
445   return TPM_SUCCESS;
446 }
447 
MTM_VerifyRIMCertAndExtend(TPM_RIM_CERTIFICATE * rimCert,TPM_VERIFICATION_KEY_HANDLE rimKey,TPM_PCRVALUE * outDigest)448 TPM_RESULT MTM_VerifyRIMCertAndExtend(TPM_RIM_CERTIFICATE *rimCert,
449                                       TPM_VERIFICATION_KEY_HANDLE rimKey,
450                                       TPM_PCRVALUE *outDigest)
451 {
452   int i;
453   TPM_RESULT res;
454 
455   info("MTM_VerifyRIMCertAndExtend()");
456   /* 1-7 */
457   res = MTM_VerifyRIMCert(rimCert, rimKey);
458   if (res != TPM_SUCCESS) return res;
459   /* 8 */
460   for (i = 0; i < TPM_NUM_PCR / 8; i++) {
461     if (rimCert->state.pcrSelection.pcrSelect[i] != 0) break;
462   }
463   if (i < TPM_NUM_PCR / 8) {
464     TPM_COMPOSITE_HASH digest;
465     if (tpm_compute_pcr_digest(&rimCert->state.pcrSelection, &digest, NULL) != TPM_SUCCESS) {
466       debug("tpm_compute_pcr_digest() failed");
467       return TPM_FAIL;
468     }
469     if (memcmp(&digest, &rimCert->state.digestAtRelease, sizeof(TPM_COMPOSITE_HASH)) != 0)
470       return TPM_WRONGPCRVAL;
471   }
472   /* 9, 10 */
473   return TPM_Extend(rimCert->measurementPcrIndex, &rimCert->measurementValue, outDigest);
474 }
475 
MTM_IncrementBootstrapCounter(TPM_RIM_CERTIFICATE * rimCert,TPM_VERIFICATION_KEY_HANDLE rimKeyHandle)476 TPM_RESULT MTM_IncrementBootstrapCounter(TPM_RIM_CERTIFICATE *rimCert,
477                                          TPM_VERIFICATION_KEY_HANDLE rimKeyHandle)
478 {
479   TPM_RESULT res;
480   MTM_KEY_DATA* rimKey;
481 
482   info("MTM_IncrementBootstrapCounter()");
483   /* 1 */
484   if (rimCert == NULL || rimCert->tag != TPM_TAG_RIM_CERTIFICATE)
485     return TPM_BAD_PARAMETER;
486   /* 2 */
487   debug("rimKeyHandle = %08x", rimKeyHandle);
488   rimKey = mtm_get_key(rimKeyHandle);
489   if (rimKey == NULL) return TPM_KEYNOTFOUND;
490   /* 3 */
491   if ((rimKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_SIGN_RIMCERT) == 0
492       ||(rimKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTSTRAP) == 0)
493     return TPM_INVALID_KEYUSAGE;
494   /* 4 */
495   if (rimCert->parentId != rimKey->myId) return TPM_AUTHFAIL;
496   /* 5 */
497   res = verify_rim_certificate(rimCert);
498   if (res != TPM_SUCCESS) return res;
499   /* 6 */
500   if (rimCert->referenceCounter.counterSelection > MTM_COUNTER_SELECT_MAX)
501     return TPM_BAD_COUNTER;
502   /* 7 */
503   if (rimCert->referenceCounter.counterSelection == MTM_COUNTER_SELECT_BOOTSTRAP) {
504     if (rimCert->referenceCounter.counterValue
505         < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter)
506       return TPM_BAD_COUNTER;
507     tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter
508       = rimCert->referenceCounter.counterValue;
509   }
510   return TPM_SUCCESS;
511 }
512 
MTM_SetVerifiedPCRSelection(TPM_PCR_SELECTION * verifiedSelection,TPM_AUTH * auth1)513 TPM_RESULT MTM_SetVerifiedPCRSelection(TPM_PCR_SELECTION *verifiedSelection,
514                                        TPM_AUTH *auth1)
515 {
516   int i;
517   TPM_RESULT res;
518 
519   info("MTM_SetVerifiedPCRSelection()");
520   /* verify permission */
521   if (tpmData.permanent.flags.owned) {
522     res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
523   } else {
524     res = FALSE;
525   }
526   if (!res && !mtmData.stany.flags.loadVerificationRootKeyEnabled) {
527     return TPM_FAIL;
528   }
529   /* echeck if a localityModifier is set */
530   for (i = 0; i < TPM_NUM_PCR; i++) {
531     if (verifiedSelection->pcrSelect[i >> 3] & (1 << (i & 7))) {
532 	    if (tpmData.permanent.data.pcrAttrib[i].pcrResetLocal) return TPM_FAIL;
533 	  }
534   }
535   /* copy selection */
536   memcpy(&mtmData.permanent.data.verifiedPCRs,
537          verifiedSelection, sizeof(TPM_PCR_SELECTION));
538   return TPM_SUCCESS;
539 }
540 
541