OLD | NEW |
(Empty) | |
| 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 |
| 30 static int copy_TPM_RIM_CERTIFICATE(TPM_RIM_CERTIFICATE* src, TPM_RIM_CERTIFICAT
E* 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 |
| 55 static int compute_rim_certificate_digest(TPM_RIM_CERTIFICATE* rimCert, BYTE *di
gest) |
| 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 |
| 81 static int compute_rim_certificate_hmac(TPM_RIM_CERTIFICATE* rimCert, BYTE *dige
st) |
| 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 |
| 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 |
| 159 static int compute_verification_key_digest(TPM_VERIFICATION_KEY *key, BYTE *dige
st) |
| 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 |
| 186 static TPM_RESULT verify_verification_key(TPM_VERIFICATION_KEY *key, MTM_KEY_DAT
A *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(dig
est), |
| 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 |
| 212 static int store_verification_key(TPM_VERIFICATION_KEY *inKey, MTM_KEY_DATA *out
Key) |
| 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 |
| 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->authHand
le); |
| 237 if (res != TPM_SUCCESS) return res; |
| 238 /* 3 */ |
| 239 cntProtect = tpmData.permanent.data.counters[MTM_COUNTER_SELECT_RIMPROTECT].co
unter; |
| 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_RIMPROTEC
T; |
| 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 |
| 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 |
| 278 TPM_RESULT MTM_LoadVerificationKey(TPM_VERIFICATION_KEY_HANDLE parentKeyHandle, |
| 279 TPM_VERIFICATION_KEY *verificationKey, TPM_AU
TH *auth1, |
| 280 TPM_VERIFICATION_KEY_HANDLE *verificationKeyH
andle, |
| 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_KE
Y) |
| 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_HANDL
E) { |
| 330 TPM_RESULT res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TP
M_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_BOOT
STRAP) |
| 352 && !(parentKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTST
RAP)) { |
| 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, parentKe
y->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].counte
r) |
| 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].count
er) |
| 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 |
| 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 |
| 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, rimK
ey->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_RIMPROTEC
T) { |
| 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 |
| 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) != T
PM_SUCCESS) { |
| 466 debug("tpm_compute_pcr_digest() failed"); |
| 467 return TPM_FAIL; |
| 468 } |
| 469 if (memcmp(&digest, &rimCert->state.digestAtRelease, sizeof(TPM_COMPOSITE_HA
SH)) != 0) |
| 470 return TPM_WRONGPCRVAL; |
| 471 } |
| 472 /* 9, 10 */ |
| 473 return TPM_Extend(rimCert->measurementPcrIndex, &rimCert->measurementValue, ou
tDigest); |
| 474 } |
| 475 |
| 476 TPM_RESULT MTM_IncrementBootstrapCounter(TPM_RIM_CERTIFICATE *rimCert, |
| 477 TPM_VERIFICATION_KEY_HANDLE rimKeyHandl
e) |
| 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 |
| 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_FA
IL; |
| 533 } |
| 534 } |
| 535 /* copy selection */ |
| 536 memcpy(&mtmData.permanent.data.verifiedPCRs, |
| 537 verifiedSelection, sizeof(TPM_PCR_SELECTION)); |
| 538 return TPM_SUCCESS; |
| 539 } |
| 540 |
OLD | NEW |