| Index: mtm/mtm_verification.c
|
| diff --git a/mtm/mtm_verification.c b/mtm/mtm_verification.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3d123ec99bde8a4bb967a8852d4a0c996fbe19ca
|
| --- /dev/null
|
| +++ b/mtm/mtm_verification.c
|
| @@ -0,0 +1,540 @@
|
| +/* Software-based Mobile Trusted Module (MTM) Emulator
|
| + * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>
|
| + * Copyright (C) 2007 Jan-Erik Ekberg <jan-erik.ekberg@nokia.com>,
|
| + * Nokia Corporation and/or its subsidiary(-ies)
|
| + *
|
| + * This module is free software; you can redistribute it and/or modify
|
| + * it under the terms of the GNU General Public License as published
|
| + * by the Free Software Foundation; either version 2 of the License,
|
| + * or (at your option) any later version.
|
| + *
|
| + * This module is distributed in the hope that it will be useful,
|
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| + * GNU General Public License for more details.
|
| + *
|
| + * $Id$
|
| + */
|
| +
|
| +#include "mtm_structures.h"
|
| +#include "mtm_commands.h"
|
| +#include "tpm/tpm_commands.h"
|
| +#include "mtm_data.h"
|
| +#include "tpm/tpm_data.h"
|
| +#include "mtm_handles.h"
|
| +#include "mtm_marshalling.h"
|
| +#include "crypto/hmac.h"
|
| +#include "crypto/rsa.h"
|
| +#include "crypto/sha1.h"
|
| +
|
| +static int copy_TPM_RIM_CERTIFICATE(TPM_RIM_CERTIFICATE* src, TPM_RIM_CERTIFICATE* dst)
|
| +{
|
| + memcpy(dst, src, sizeof(TPM_RIM_CERTIFICATE));
|
| + if (dst->extensionDigestSize > 0) {
|
| + dst->extensionDigestData = tpm_malloc(dst->extensionDigestSize);
|
| + if (dst->extensionDigestData == NULL) return -1;
|
| + memcpy(dst->extensionDigestData, src->extensionDigestData,
|
| + dst->extensionDigestSize);
|
| + } else {
|
| + dst->extensionDigestData = NULL;
|
| + }
|
| + if (dst->integrityCheckSize > 0) {
|
| + dst->integrityCheckData = tpm_malloc(dst->integrityCheckSize);
|
| + if (dst->integrityCheckData == NULL) {
|
| + tpm_free(dst->extensionDigestData);
|
| + return -1;
|
| + }
|
| + memcpy(dst->integrityCheckData, src->integrityCheckData,
|
| + dst->integrityCheckSize);
|
| + } else {
|
| + dst->integrityCheckData = NULL;
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +static int compute_rim_certificate_digest(TPM_RIM_CERTIFICATE* rimCert, BYTE *digest)
|
| +{
|
| + tpm_sha1_ctx_t sha1_ctx;
|
| + BYTE *buf, *ptr;
|
| + UINT32 buf_len, len;
|
| + UINT32 integrityCheckSize;
|
| +
|
| + /* marshal certificate */
|
| + integrityCheckSize = rimCert->integrityCheckSize;
|
| + rimCert->integrityCheckSize = 0;
|
| + buf_len = len = sizeof_TPM_RIM_CERTIFICATE((*rimCert));
|
| + buf = ptr = tpm_malloc(buf_len);
|
| + if (buf == NULL || tpm_marshal_TPM_RIM_CERTIFICATE(&ptr, &len, rimCert)) {
|
| + rimCert->integrityCheckSize = integrityCheckSize;
|
| + tpm_free(buf);
|
| + return -1;
|
| + }
|
| + rimCert->integrityCheckSize = integrityCheckSize;
|
| + /* compute hmac */
|
| + tpm_sha1_init(&sha1_ctx);
|
| + tpm_sha1_update(&sha1_ctx, buf, buf_len);
|
| + tpm_sha1_final(&sha1_ctx, digest);
|
| + tpm_free(buf);
|
| + return 0;
|
| +}
|
| +
|
| +static int compute_rim_certificate_hmac(TPM_RIM_CERTIFICATE* rimCert, BYTE *digest)
|
| +{
|
| + tpm_hmac_ctx_t hmac_ctx;
|
| + BYTE *buf, *ptr;
|
| + UINT32 buf_len, len;
|
| + UINT32 integrityCheckSize;
|
| +
|
| + /* marshal certificate */
|
| + integrityCheckSize = rimCert->integrityCheckSize;
|
| + rimCert->integrityCheckSize = 0;
|
| + buf_len = len = sizeof_TPM_RIM_CERTIFICATE((*rimCert));
|
| + buf = ptr = tpm_malloc(buf_len);
|
| + if (buf == NULL || tpm_marshal_TPM_RIM_CERTIFICATE(&ptr, &len, rimCert)) {
|
| + rimCert->integrityCheckSize = integrityCheckSize;
|
| + tpm_free(buf);
|
| + return -1;
|
| + }
|
| + rimCert->integrityCheckSize = integrityCheckSize;
|
| + /* compute hmac */
|
| + tpm_hmac_init(&hmac_ctx, mtmData.permanent.data.internalVerificationKey,
|
| + sizeof(TPM_SECRET));
|
| + tpm_hmac_update(&hmac_ctx, buf, buf_len);
|
| + tpm_hmac_final(&hmac_ctx, digest);
|
| + tpm_free(buf);
|
| + return 0;
|
| +}
|
| +
|
| +static TPM_RESULT verify_rim_certificate(TPM_RIM_CERTIFICATE *rimCert)
|
| +{
|
| + /* check parrentID */
|
| + debug("parentId = %08x", rimCert->parentId);
|
| + if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_NONE) return TPM_KEYNOTFOUND;
|
| + /* verify certificate with appropiate key */
|
| + if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_INTERNAL) {
|
| + BYTE digest[SHA1_DIGEST_LENGTH];
|
| + debug("internal verification");
|
| + if (compute_rim_certificate_hmac(rimCert, digest) != 0) {
|
| + debug("compute_rim_certificate_hmac() failed");
|
| + return TPM_FAIL;
|
| + }
|
| + /* check hmac */
|
| + if (memcmp(digest, rimCert->integrityCheckData, SHA1_DIGEST_LENGTH) != 0) {
|
| + debug("verification failed");
|
| + return TPM_AUTHFAIL;
|
| + } else {
|
| + debug("verification succeeded");
|
| + return TPM_SUCCESS;
|
| + }
|
| + } else {
|
| + BYTE digest[SHA1_DIGEST_LENGTH];
|
| + /* get verification key */
|
| + MTM_KEY_DATA *key = mtm_get_key_by_id(rimCert->parentId);
|
| + if (key == NULL) {
|
| + return TPM_KEYNOTFOUND;
|
| + }
|
| + /* compute digest */
|
| + if (compute_rim_certificate_digest(rimCert, digest) != 0) {
|
| + debug("compute_rim_certificate_digest() failed");
|
| + return TPM_FAIL;
|
| + }
|
| + /* check key properties */
|
| + if (key->keyAlgorithm != TPM_ALG_RSA
|
| + || key->keyScheme != TPM_SS_RSASSAPKCS1v15_SHA1) {
|
| + debug("invalid signature scheme");
|
| + return TPM_BAD_SCHEME;
|
| + }
|
| + /* verify signature */
|
| + if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_SHA1_RAW, digest, sizeof(digest),
|
| + rimCert->integrityCheckData) != 0) {
|
| + debug("verification failed");
|
| + return TPM_AUTHFAIL;
|
| + } else {
|
| + debug("verification succeeded");
|
| + return TPM_SUCCESS;
|
| + }
|
| + }
|
| +}
|
| +
|
| +static int compute_verification_key_digest(TPM_VERIFICATION_KEY *key, BYTE *digest)
|
| +{
|
| + tpm_sha1_ctx_t sha1_ctx;
|
| + BYTE *buf, *ptr;
|
| + UINT32 buf_len, len;
|
| + UINT32 integrityCheckSize;
|
| +
|
| + /* marshal certificate */
|
| + integrityCheckSize = key->integrityCheckSize;
|
| + key->integrityCheckSize = 0;
|
| + buf_len = len = sizeof_TPM_VERIFICATION_KEY((*key));
|
| + buf = ptr = tpm_malloc(buf_len);
|
| + if (buf == NULL || tpm_marshal_TPM_VERIFICATION_KEY(&ptr, &len, key)) {
|
| + key->integrityCheckSize = integrityCheckSize;
|
| + tpm_free(buf);
|
| + return -1;
|
| + }
|
| + key->integrityCheckSize = integrityCheckSize;
|
| + /* compute sha1 */
|
| + tpm_sha1_init(&sha1_ctx);
|
| + tpm_sha1_update(&sha1_ctx, buf, buf_len);
|
| + tpm_sha1_final(&sha1_ctx, digest);
|
| + tpm_free(buf);
|
| + return 0;
|
| +
|
| +}
|
| +
|
| +static TPM_RESULT verify_verification_key(TPM_VERIFICATION_KEY *key, MTM_KEY_DATA *parentKey)
|
| +{
|
| + BYTE digest[SHA1_DIGEST_LENGTH];
|
| +
|
| + /* compute digest */
|
| + if (compute_verification_key_digest(key, digest) != 0) {
|
| + debug("compute_verification_key_digest() failed");
|
| + return TPM_FAIL;
|
| + }
|
| + /* check key properties */
|
| + if (parentKey->keyAlgorithm != TPM_ALG_RSA
|
| + || parentKey->keyScheme != TPM_SS_RSASSAPKCS1v15_SHA1) {
|
| + debug("invalid signature scheme");
|
| + return TPM_BAD_SCHEME;
|
| + }
|
| + /* verify signature */
|
| + if (tpm_rsa_verify(&parentKey->key, RSA_SSA_PKCS1_SHA1_RAW, digest, sizeof(digest),
|
| + key->integrityCheckData) != 0) {
|
| + debug("verification failed");
|
| + return TPM_AUTHFAIL;
|
| + } else {
|
| + debug("verification succeeded");
|
| + return TPM_SUCCESS;
|
| + }
|
| +}
|
| +
|
| +static int store_verification_key(TPM_VERIFICATION_KEY *inKey, MTM_KEY_DATA *outKey)
|
| +{
|
| + outKey->usageFlags = inKey->usageFlags;
|
| + outKey->parentId = inKey->parentId;
|
| + outKey->myId = inKey->myId;
|
| + outKey->keyAlgorithm = inKey->keyAlgorithm;
|
| + outKey->keyScheme = inKey->keyScheme;
|
| + BYTE *ptr = inKey->keyData;
|
| + UINT32 len = inKey->keySize;
|
| + if (tpm_unmarshal_RSAPub(&ptr, &len, &outKey->key) != 0) return -1;
|
| + return 0;
|
| +}
|
| +
|
| +TPM_RESULT MTM_InstallRIM(TPM_RIM_CERTIFICATE *rimCertIn, TPM_AUTH *auth1,
|
| + TPM_RIM_CERTIFICATE *rimCertOut)
|
| +{
|
| + TPM_RESULT res;
|
| + TPM_ACTUAL_COUNT cntProtect;
|
| +
|
| + info("MTM_InstallRIM()");
|
| + /* 1 */
|
| + if (rimCertIn == NULL || rimCertIn->tag != TPM_TAG_RIM_CERTIFICATE)
|
| + return TPM_BAD_PARAMETER;
|
| + /* 2 */
|
| + res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, auth1->authHandle);
|
| + if (res != TPM_SUCCESS) return res;
|
| + /* 3 */
|
| + cntProtect = tpmData.permanent.data.counters[MTM_COUNTER_SELECT_RIMPROTECT].counter;
|
| + /* 5 */
|
| + rimCertIn->integrityCheckSize = SHA1_DIGEST_LENGTH;
|
| + if (copy_TPM_RIM_CERTIFICATE(rimCertIn, rimCertOut) != 0) {
|
| + debug("copy_TPM_RIM_CERTIFICATE() failed");
|
| + return TPM_FAIL;
|
| + }
|
| + /* 6, 7 */
|
| + if (rimCertIn->referenceCounter.counterSelection != MTM_COUNTER_SELECT_NONE) {
|
| + rimCertOut->referenceCounter.counterValue = cntProtect + 1;
|
| + rimCertOut->referenceCounter.counterSelection = MTM_COUNTER_SELECT_RIMPROTECT;
|
| + } else {
|
| + rimCertOut->referenceCounter.counterValue = 0;
|
| + }
|
| + /* 8 */
|
| + rimCertOut->parentId = TPM_VERIFICATION_KEY_ID_INTERNAL;
|
| + /* 10, 11, 12 */
|
| + if (compute_rim_certificate_hmac(rimCertOut, rimCertOut->integrityCheckData) != 0) {
|
| + debug("compute_rim_certificate_hmac() failed");
|
| + free_TPM_RIM_CERTIFICATE((*rimCertOut));
|
| + return TPM_FAIL;
|
| + }
|
| + /* 13 */
|
| + return TPM_SUCCESS;
|
| +}
|
| +
|
| +static TPM_VERIFICATION_KEY_HANDLE mtm_get_free_key(void)
|
| +{
|
| + int i;
|
| + for (i = 0; i < TPM_MAX_KEYS; i++) {
|
| + if (!mtmData.permanent.data.keys[i].valid) {
|
| + mtmData.permanent.data.keys[i].valid = TRUE;
|
| + return INDEX_TO_KEY_HANDLE(i);
|
| + }
|
| + }
|
| + return TPM_INVALID_HANDLE;
|
| +}
|
| +
|
| +
|
| +TPM_RESULT MTM_LoadVerificationKey(TPM_VERIFICATION_KEY_HANDLE parentKeyHandle,
|
| + TPM_VERIFICATION_KEY *verificationKey, TPM_AUTH *auth1,
|
| + TPM_VERIFICATION_KEY_HANDLE *verificationKeyHandle,
|
| + BYTE *loadMethod)
|
| +{
|
| + TPM_RESULT res;
|
| + MTM_KEY_DATA *key;
|
| +
|
| + /* 1 */
|
| + if (verificationKey == NULL || verificationKey->tag != TPM_TAG_VERIFICATION_KEY)
|
| + return TPM_BAD_PARAMETER;
|
| + /* 2 */
|
| + *verificationKeyHandle = mtm_get_free_key();
|
| + key = mtm_get_key(*verificationKeyHandle);
|
| + if (key == NULL) {
|
| + debug("no free key slot available");
|
| + return TPM_NOSPACE;
|
| + }
|
| + *loadMethod = 0;
|
| + /* 3 */
|
| + if (mtmData.stany.flags.loadVerificationRootKeyEnabled) {
|
| + debug("TPM_VERIFICATION_KEY_ROOT_LOAD");
|
| + /* set integrityCheckRootData */
|
| + if (!mtmData.permanent.data.integrityCheckRootValid) {
|
| + if (compute_verification_key_digest(verificationKey,
|
| + mtmData.permanent.data.integrityCheckRootData) != 0) {
|
| + debug("compute_verification_key_digest() failed");
|
| + memset(key, 0, sizeof(*key));
|
| + return TPM_FAIL;
|
| + }
|
| + mtmData.permanent.data.integrityCheckRootValid = TRUE;
|
| + }
|
| + *loadMethod = TPM_VERIFICATION_KEY_ROOT_LOAD;
|
| + }
|
| + /* 4 */
|
| + if (*loadMethod == 0
|
| + && mtmData.permanent.data.integrityCheckRootValid) {
|
| + BYTE digest[SHA1_DIGEST_LENGTH];
|
| + if (compute_verification_key_digest(verificationKey, digest) != 0) {
|
| + debug("compute_verification_key_digest() failed");
|
| + memset(key, 0, sizeof(*key));
|
| + return TPM_FAIL;
|
| + }
|
| + if (memcmp(mtmData.permanent.data.integrityCheckRootData,
|
| + digest, SHA1_DIGEST_LENGTH) == 0) {
|
| + debug("TPM_VERIFICATION_KEY_INTEGRITY_CHECK_ROOT_DATA_LOAD");
|
| + *loadMethod = TPM_VERIFICATION_KEY_INTEGRITY_CHECK_ROOT_DATA_LOAD;
|
| + }
|
| + }
|
| + /* 5 */
|
| + if (*loadMethod == 0
|
| + && tpmData.permanent.flags.owned && auth1->authHandle != TPM_INVALID_HANDLE) {
|
| + TPM_RESULT res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
|
| + if (res != TPM_SUCCESS) {
|
| + memset(key, 0, sizeof(*key));
|
| + return res;
|
| + }
|
| + debug("TPM_VERIFICATION_KEY_OWNER_AUTHORIZED_LOAD");
|
| + *loadMethod = TPM_VERIFICATION_KEY_OWNER_AUTHORIZED_LOAD;
|
| + }
|
| + /* 6 */
|
| + if (*loadMethod == 0) {
|
| + MTM_KEY_DATA *parentKey = mtm_get_key(parentKeyHandle);
|
| + if (parentKey == NULL) {
|
| + debug("invalid parent key handle %08x", parentKeyHandle);
|
| + memset(key, 0, sizeof(*key));
|
| + return TPM_KEYNOTFOUND;
|
| + }
|
| + /* 7a-c */
|
| + if (!(parentKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_SIGN_RIMAUTH)) {
|
| + memset(key, 0, sizeof(*key));
|
| + return TPM_INVALID_KEYUSAGE;
|
| + }
|
| + if ((verificationKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTSTRAP)
|
| + && !(parentKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTSTRAP)) {
|
| + memset(key, 0, sizeof(*key));
|
| + return TPM_INVALID_KEYUSAGE;
|
| + }
|
| + if (key->parentId != parentKey->myId) {
|
| + debug("id mismatch: parentId = %08x keyId = %08x", key->parentId, parentKey->myId);
|
| + memset(key, 0, sizeof(*key));
|
| + return TPM_AUTHFAIL;
|
| + }
|
| + /* 7d */
|
| + res = verify_verification_key(verificationKey, parentKey);
|
| + if (res != TPM_SUCCESS) {
|
| + memset(key, 0, sizeof(*key));
|
| + return res;
|
| + }
|
| + /* 7e-g */
|
| + if (verificationKey->referenceCounter.counterSelection > MTM_COUNTER_SELECT_MAX)
|
| + return TPM_BAD_COUNTER;
|
| + if (verificationKey->referenceCounter.counterSelection == MTM_COUNTER_SELECT_BOOTSTRAP) {
|
| + if (verificationKey->referenceCounter.counterValue
|
| + < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter)
|
| + return TPM_BAD_COUNTER;
|
| + }
|
| + if (verificationKey->referenceCounter.counterSelection == MTM_COUNTER_SELECT_RIMPROTECT) {
|
| + if (verificationKey->referenceCounter.counterValue
|
| + < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_RIMPROTECT].counter)
|
| + return TPM_BAD_COUNTER;
|
| + }
|
| + /* 7j */
|
| + debug("TPM_VERIFICATION_KEY_CHAIN_AUTHORIZED_LOAD");
|
| + *loadMethod = TPM_VERIFICATION_KEY_CHAIN_AUTHORIZED_LOAD;
|
| + }
|
| + /* store verification key */
|
| + if (store_verification_key(verificationKey, key) != 0) {
|
| + debug("store_verification_key() failed");
|
| + memset(key, 0, sizeof(*key));
|
| + return TPM_FAIL;
|
| + }
|
| + return TPM_SUCCESS;
|
| +}
|
| +
|
| +TPM_RESULT MTM_LoadVerificationRootKeyDisable()
|
| +{
|
| + info("MTM_LoadVerificationRootKeyDisable()");
|
| + mtmData.stany.flags.loadVerificationRootKeyEnabled = FALSE;
|
| + mtmData.permanent.data.loadVerificationKeyMethods |= TPM_VERIFICATION_KEY_ROOT_LOAD;
|
| + return TPM_SUCCESS;
|
| +}
|
| +
|
| +TPM_RESULT MTM_VerifyRIMCert(TPM_RIM_CERTIFICATE* rimCert,
|
| + TPM_VERIFICATION_KEY_HANDLE rimKeyHandle)
|
| +{
|
| + TPM_RESULT res;
|
| +
|
| + info("MTM_VerifyRIMCert()");
|
| + debug("key handle = %08x", rimKeyHandle);
|
| + /* 1 */
|
| + if (rimCert == NULL || rimCert->tag != TPM_TAG_RIM_CERTIFICATE)
|
| + return TPM_BAD_PARAMETER;
|
| + /* 2 */
|
| + if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_NONE)
|
| + return TPM_AUTHFAIL;
|
| + /* 3 */
|
| + if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_INTERNAL) {
|
| + return verify_rim_certificate(rimCert);
|
| + } else {
|
| + /* 4 */
|
| + MTM_KEY_DATA *rimKey = mtm_get_key(rimKeyHandle);
|
| + if (rimKey == NULL) return TPM_KEYNOTFOUND;
|
| + if ((rimKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_SIGN_RIMCERT) == 0)
|
| + return TPM_INVALID_KEYUSAGE;
|
| + if (rimCert->parentId != rimKey->myId) {
|
| + debug("id mismatch: parentId = %08x keyId = %08x", rimCert->parentId, rimKey->myId);
|
| + return TPM_AUTHFAIL;
|
| + }
|
| + res = verify_rim_certificate(rimCert);
|
| + if (res != TPM_SUCCESS) return res;
|
| + }
|
| + /* 5 */
|
| + if (rimCert->referenceCounter.counterSelection > MTM_COUNTER_SELECT_MAX)
|
| + return TPM_BAD_COUNTER;
|
| + /* 6 */
|
| + if (rimCert->referenceCounter.counterSelection == MTM_COUNTER_SELECT_BOOTSTRAP) {
|
| + if (rimCert->referenceCounter.counterValue
|
| + < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter)
|
| + return TPM_BAD_COUNTER;
|
| + }
|
| + /* 7 */
|
| + if (rimCert->referenceCounter.counterSelection == MTM_COUNTER_SELECT_RIMPROTECT) {
|
| + if (rimCert->referenceCounter.counterValue
|
| + < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_RIMPROTECT].counter)
|
| + return TPM_BAD_COUNTER;
|
| + }
|
| + return TPM_SUCCESS;
|
| +}
|
| +
|
| +TPM_RESULT MTM_VerifyRIMCertAndExtend(TPM_RIM_CERTIFICATE *rimCert,
|
| + TPM_VERIFICATION_KEY_HANDLE rimKey,
|
| + TPM_PCRVALUE *outDigest)
|
| +{
|
| + int i;
|
| + TPM_RESULT res;
|
| +
|
| + info("MTM_VerifyRIMCertAndExtend()");
|
| + /* 1-7 */
|
| + res = MTM_VerifyRIMCert(rimCert, rimKey);
|
| + if (res != TPM_SUCCESS) return res;
|
| + /* 8 */
|
| + for (i = 0; i < TPM_NUM_PCR / 8; i++) {
|
| + if (rimCert->state.pcrSelection.pcrSelect[i] != 0) break;
|
| + }
|
| + if (i < TPM_NUM_PCR / 8) {
|
| + TPM_COMPOSITE_HASH digest;
|
| + if (tpm_compute_pcr_digest(&rimCert->state.pcrSelection, &digest, NULL) != TPM_SUCCESS) {
|
| + debug("tpm_compute_pcr_digest() failed");
|
| + return TPM_FAIL;
|
| + }
|
| + if (memcmp(&digest, &rimCert->state.digestAtRelease, sizeof(TPM_COMPOSITE_HASH)) != 0)
|
| + return TPM_WRONGPCRVAL;
|
| + }
|
| + /* 9, 10 */
|
| + return TPM_Extend(rimCert->measurementPcrIndex, &rimCert->measurementValue, outDigest);
|
| +}
|
| +
|
| +TPM_RESULT MTM_IncrementBootstrapCounter(TPM_RIM_CERTIFICATE *rimCert,
|
| + TPM_VERIFICATION_KEY_HANDLE rimKeyHandle)
|
| +{
|
| + TPM_RESULT res;
|
| + MTM_KEY_DATA* rimKey;
|
| +
|
| + info("MTM_IncrementBootstrapCounter()");
|
| + /* 1 */
|
| + if (rimCert == NULL || rimCert->tag != TPM_TAG_RIM_CERTIFICATE)
|
| + return TPM_BAD_PARAMETER;
|
| + /* 2 */
|
| + debug("rimKeyHandle = %08x", rimKeyHandle);
|
| + rimKey = mtm_get_key(rimKeyHandle);
|
| + if (rimKey == NULL) return TPM_KEYNOTFOUND;
|
| + /* 3 */
|
| + if ((rimKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_SIGN_RIMCERT) == 0
|
| + ||(rimKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTSTRAP) == 0)
|
| + return TPM_INVALID_KEYUSAGE;
|
| + /* 4 */
|
| + if (rimCert->parentId != rimKey->myId) return TPM_AUTHFAIL;
|
| + /* 5 */
|
| + res = verify_rim_certificate(rimCert);
|
| + if (res != TPM_SUCCESS) return res;
|
| + /* 6 */
|
| + if (rimCert->referenceCounter.counterSelection > MTM_COUNTER_SELECT_MAX)
|
| + return TPM_BAD_COUNTER;
|
| + /* 7 */
|
| + if (rimCert->referenceCounter.counterSelection == MTM_COUNTER_SELECT_BOOTSTRAP) {
|
| + if (rimCert->referenceCounter.counterValue
|
| + < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter)
|
| + return TPM_BAD_COUNTER;
|
| + tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter
|
| + = rimCert->referenceCounter.counterValue;
|
| + }
|
| + return TPM_SUCCESS;
|
| +}
|
| +
|
| +TPM_RESULT MTM_SetVerifiedPCRSelection(TPM_PCR_SELECTION *verifiedSelection,
|
| + TPM_AUTH *auth1)
|
| +{
|
| + int i;
|
| + TPM_RESULT res;
|
| +
|
| + info("MTM_SetVerifiedPCRSelection()");
|
| + /* verify permission */
|
| + if (tpmData.permanent.flags.owned) {
|
| + res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
|
| + } else {
|
| + res = FALSE;
|
| + }
|
| + if (!res && !mtmData.stany.flags.loadVerificationRootKeyEnabled) {
|
| + return TPM_FAIL;
|
| + }
|
| + /* echeck if a localityModifier is set */
|
| + for (i = 0; i < TPM_NUM_PCR; i++) {
|
| + if (verifiedSelection->pcrSelect[i >> 3] & (1 << (i & 7))) {
|
| + if (tpmData.permanent.data.pcrAttrib[i].pcrResetLocal) return TPM_FAIL;
|
| + }
|
| + }
|
| + /* copy selection */
|
| + memcpy(&mtmData.permanent.data.verifiedPCRs,
|
| + verifiedSelection, sizeof(TPM_PCR_SELECTION));
|
| + return TPM_SUCCESS;
|
| +}
|
| +
|
|
|