Upgrade from rev 142 to rev 146

This is the diff patch between rev 142 and 146.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
This commit is contained in:
Stefan Berger 2017-07-23 16:01:39 -04:00
parent ccce8b5f49
commit 992a5bfad8
99 changed files with 3718 additions and 2327 deletions

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: AlgorithmCap.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: AlgorithmCap.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -76,100 +76,103 @@ static const ALGORITHM s_algorithms[] =
// need to be full (gaps are allowed). One day, a tool might exist to fill in the
// table from the TPM_ALG description
#ifdef TPM_ALG_RSA
{TPM_ALG_RSA, {1, 0, 0, 1, 0, 0, 0, 0, 0}},
{TPM_ALG_RSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 1, 0, 0, 0, 0, 0)},
#endif
#ifdef TPM_ALG_TDES
{TPM_ALG_TDES, {0, 1, 0, 0, 0, 0, 0, 0, 0}},
{TPM_ALG_TDES, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)},
#endif
#ifdef TPM_ALG_SHA1
{TPM_ALG_SHA1, {0, 0, 1, 0, 0, 0, 0, 0, 0}},
{TPM_ALG_SHA1, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)},
#endif
{TPM_ALG_HMAC, {0, 0, 1, 0, 0, 1, 0, 0, 0}},
{TPM_ALG_HMAC, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 1, 0, 0, 0)},
#ifdef TPM_ALG_AES
{TPM_ALG_AES, {0, 1, 0, 0, 0, 0, 0, 0, 0}},
{TPM_ALG_AES, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)},
#endif
#ifdef TPM_ALG_MGF1
{TPM_ALG_MGF1, {0, 0, 1, 0, 0, 0, 0, 1, 0}},
{TPM_ALG_MGF1, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)},
#endif
{TPM_ALG_KEYEDHASH, {0, 0, 1, 1, 0, 1, 1, 0, 0}},
{TPM_ALG_KEYEDHASH, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 1, 0, 1, 1, 0, 0)},
#ifdef TPM_ALG_XOR
{TPM_ALG_XOR, {0, 1, 1, 0, 0, 0, 0, 0, 0}},
{TPM_ALG_XOR, TPMA_ALGORITHM_INITIALIZER(0, 1, 1, 0, 0, 0, 0, 0, 0)},
#endif
#ifdef TPM_ALG_SHA256
{TPM_ALG_SHA256, {0, 0, 1, 0, 0, 0, 0, 0, 0}},
{TPM_ALG_SHA256, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)},
#endif
#ifdef TPM_ALG_SHA384
{TPM_ALG_SHA384, {0, 0, 1, 0, 0, 0, 0, 0, 0}},
{TPM_ALG_SHA384, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)},
#endif
#ifdef TPM_ALG_SHA512
{TPM_ALG_SHA512, {0, 0, 1, 0, 0, 0, 0, 0, 0}},
{TPM_ALG_SHA512, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)},
#endif
#ifdef TPM_ALG_SM3_256
{TPM_ALG_SM3_256, {0, 0, 1, 0, 0, 0, 0, 0, 0}},
{TPM_ALG_SM3_256, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)},
#endif
#ifdef TPM_ALG_SM4
{TPM_ALG_SM4, {0, 1, 0, 0, 0, 0, 0, 0, 0}},
{TPM_ALG_SM4, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)},
#endif
#ifdef TPM_ALG_RSASSA
{TPM_ALG_RSASSA, {1, 0, 0, 0, 0, 1, 0, 0, 0}},
{TPM_ALG_RSASSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)},
#endif
#ifdef TPM_ALG_RSAES
{TPM_ALG_RSAES, {1, 0, 0, 0, 0, 0, 1, 0, 0}},
{TPM_ALG_RSAES, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 1, 0, 0)},
#endif
#ifdef TPM_ALG_RSAPSS
{TPM_ALG_RSAPSS, {1, 0, 0, 0, 0, 1, 0, 0, 0}},
{TPM_ALG_RSAPSS, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)},
#endif
#ifdef TPM_ALG_OAEP
{TPM_ALG_OAEP, {1, 0, 0, 0, 0, 0, 1, 0, 0}},
{TPM_ALG_OAEP, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 1, 0, 0)},
#endif
#ifdef TPM_ALG_ECDSA
{TPM_ALG_ECDSA, {1, 0, 0, 0, 0, 1, 0, 1, 0}},
{TPM_ALG_ECDSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 1, 0)},
#endif
#ifdef TPM_ALG_ECDH
{TPM_ALG_ECDH, {1, 0, 0, 0, 0, 0, 0, 1, 0}},
{TPM_ALG_ECDH, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 0, 1, 0)},
#endif
#ifdef TPM_ALG_ECDAA
{TPM_ALG_ECDAA, {1, 0, 0, 0, 0, 1, 0, 0, 0}},
{TPM_ALG_ECDAA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)},
#endif
#ifdef TPM_ALG_SM2
{TPM_ALG_SM2, {1, 0, 0, 0, 0, 1, 0, 1, 0}},
{TPM_ALG_SM2, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 1, 0)},
#endif
#ifdef TPM_ALG_ECSCHNORR
{TPM_ALG_ECSCHNORR, {1, 0, 0, 0, 0, 1, 0, 0, 0}},
{TPM_ALG_ECSCHNORR, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)},
#endif
#ifdef TPM_ALG_ECMQV
{TPM_ALG_ECMQV, {1, 0, 0, 0, 0, 0, 0, 1, 0}},
{TPM_ALG_ECMQV, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 0, 1, 0)},
#endif
#ifdef TPM_ALG_KDF1_SP800_56A
{TPM_ALG_KDF1_SP800_56A,{0, 0, 1, 0, 0, 0, 0, 1, 0}},
{TPM_ALG_KDF1_SP800_56A, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)},
#endif
#ifdef TPM_ALG_KDF2
{TPM_ALG_KDF2, {0, 0, 1, 0, 0, 0, 0, 1, 0}},
{TPM_ALG_KDF2, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)},
#endif
#ifdef TPM_ALG_KDF1_SP800_108
{TPM_ALG_KDF1_SP800_108,{0, 0, 1, 0, 0, 0, 0, 1, 0}},
{TPM_ALG_KDF1_SP800_108, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)},
#endif
#ifdef TPM_ALG_ECC
{TPM_ALG_ECC, {1, 0, 0, 1, 0, 0, 0, 0, 0}},
{TPM_ALG_ECC, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 1, 0, 0, 0, 0, 0)},
#endif
{TPM_ALG_SYMCIPHER, {0, 0, 0, 1, 0, 0, 0, 0, 0}},
{TPM_ALG_SYMCIPHER, TPMA_ALGORITHM_INITIALIZER(0, 0, 0, 1, 0, 0, 0, 0, 0)},
#ifdef TPM_ALG_CAMELLIA
{TPM_ALG_CAMELLIA, {0, 1, 0, 0, 0, 0, 0, 0, 0}},
{TPM_ALG_CAMELLIA, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)},
#endif
#ifdef TPM_ALG_CMAC
{TPM_ALG_CMAC, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 1, 0, 0, 0)},
#endif
#ifdef TPM_ALG_CTR
{TPM_ALG_CTR, {0, 1, 0, 0, 0, 0, 1, 0, 0}},
{TPM_ALG_CTR, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},
#endif
#ifdef TPM_ALG_OFB
{TPM_ALG_OFB, {0, 1, 0, 0, 0, 0, 1, 0, 0}},
{TPM_ALG_OFB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},
#endif
#ifdef TPM_ALG_CBC
{TPM_ALG_CBC, {0, 1, 0, 0, 0, 0, 1, 0, 0}},
{TPM_ALG_CBC, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},
#endif
#ifdef TPM_ALG_CFB
{TPM_ALG_CFB, {0, 1, 0, 0, 0, 0, 1, 0, 0}},
{TPM_ALG_CFB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},
#endif
#ifdef TPM_ALG_ECB
{TPM_ALG_ECB, {0, 1, 0, 0, 0, 0, 1, 0, 0}},
{TPM_ALG_ECB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},
#endif
};
/* 9.1.3 AlgorithmCapGetImplemented() */

View File

@ -3,7 +3,7 @@
/* Code to perform the various self-test functions. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: AlgorithmTests.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: AlgorithmTests.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -319,7 +319,7 @@ TestSymmetric(
/* The tests are for public key only operations and for private key operations. Signature
verification and encryption are public key operations. They are tested by using a KVT. For
signature verification, this means that a known good signature is checked by
_cpri_ValidateSignatureRSA(). If it fails, then the TPM enters failure mode. For encryption, the
CryptRsaValidateSignature(). If it fails, then the TPM enters failure mode. For encryption, the
TPM encrypts known values using the selected scheme and checks that the returned value matches
the expected value. */
/* For private key operations, a full scheme check is used. For a signing key, a known key is used
@ -751,12 +751,15 @@ TestEcc(
}
#endif // TPM_ALG_ECC
/* 10.2.1.6.4 TestAlgorithm() */
/* Dispatches to the correct test function for the algorithm. If algorithm is not If toTest is not
NULL, then the test decisions are based on the algorithm selections in toTest. Otherwise,
g_toTest is used. When bits are clear in g_toTest they will also be cleared toTest. If there
doesn't happen to be a test for the algorithm, its associated bit quietly cleared. If alg is zero
(TPM_ALG_ERROR), then the toTest vector is cleared of any bits for which there is a test (i.e. no
tests are actually run but the vector is cleared. */
/* Dispatches to the correct test function for the algorithm or get a list of testable
algorithms. */
/* If toTest is not NULL, then the test decisions are based on the algorithm selections in
toTest. Otherwise, g_toTest is used. When bits are clear in g_toTest they will also be cleared
toTest. */
/* If there doesn't happen to be a test for the algorithm, its associated bit is quietly
cleared. */
/* If alg is zero (TPM_ALG_ERROR), then the toTest vector is cleared of any bits for which there is
no test (i.e. no tests are actually run but the vector is cleared). */
/* NOTE: toTest will only ever have bits set for implemented algorithms but alg can be anything. */
/* Error Returns Meaning */
/* TPM_RC_SUCCESS test complete */

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Asymmetric Commands */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: AsymmetricCommands.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: AsymmetricCommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -78,7 +78,7 @@ TPM2_RSA_Encrypt(
if(rsaKey->publicArea.type != TPM_ALG_RSA)
return TPM_RCS_KEY + RC_RSA_Encrypt_keyHandle;
// selected key must have the decryption attribute
if(rsaKey->publicArea.objectAttributes.decrypt != SET)
if(!IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
return TPM_RCS_ATTRIBUTES + RC_RSA_Encrypt_keyHandle;
// Is there a label?
if(!IsLabelProperlyFormatted(&in->label.b))
@ -116,8 +116,8 @@ TPM2_RSA_Decrypt(
if(rsaKey->publicArea.type != TPM_ALG_RSA)
return TPM_RCS_KEY + RC_RSA_Decrypt_keyHandle;
// The selected key must be an unrestricted decryption key
if(rsaKey->publicArea.objectAttributes.restricted == SET
|| rsaKey->publicArea.objectAttributes.decrypt == CLEAR)
if(IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, restricted)
|| !IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
return TPM_RCS_ATTRIBUTES + RC_RSA_Decrypt_keyHandle;
// NOTE: Proper operation of this command requires that the sensitive area
// of the key is loaded. This is assured because authorization is required
@ -207,8 +207,8 @@ TPM2_ECDH_ZGen(
if(eccKey->publicArea.type != TPM_ALG_ECC)
return TPM_RCS_KEY + RC_ECDH_ZGen_keyHandle;
// Selected key needs to be unrestricted with the 'decrypt' attribute
if(eccKey->publicArea.objectAttributes.restricted == SET
|| eccKey->publicArea.objectAttributes.decrypt != SET)
if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted)
|| !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
return TPM_RCS_ATTRIBUTES + RC_ECDH_ZGen_keyHandle;
// Make sure the scheme allows this use
if(eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_ECDH
@ -265,9 +265,8 @@ TPM2_ZGen_2Phase(
if(eccKey->publicArea.type != TPM_ALG_ECC)
return TPM_RCS_KEY + RC_ZGen_2Phase_keyA;
// keyA must not be restricted and must be a decrypt key
if(eccKey->publicArea.objectAttributes.restricted == SET
|| eccKey->publicArea.objectAttributes.decrypt != SET
)
if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted)
|| !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
return TPM_RCS_ATTRIBUTES + RC_ZGen_2Phase_keyA;
// if the scheme of keyA is TPM_ALG_NULL, then use the input scheme; otherwise
// the input scheme must be the same as the scheme of keyA

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Attest_spt.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: Attest_spt.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -202,6 +202,7 @@ IsSigningObject(
OBJECT *object // IN:
)
{
return ((object == NULL) || ((object->publicArea.objectAttributes.sign == SET)
&& object->publicArea.type != TPM_ALG_SYMCIPHER));
return ((object == NULL) || ((IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign)
&& object->publicArea.type != TPM_ALG_SYMCIPHER)));
}

View File

@ -3,7 +3,7 @@
/* conversion functions that will convert TPM2B to/from internal format */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: BnConvert.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: BnConvert.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -160,7 +160,7 @@ BnFromHex(
if(i == 1)
*d = FromHex(*p);
}
#if BIG_ENDIAN_TPM == NO
#if !BIG_ENDIAN_TPM
for(i = 0; i < wordCount; i++)
bn->d[i] = SWAP_CRYPT_WORD(bn->d[i]);
#endif // BIG_ENDIAN_TPM
@ -173,6 +173,9 @@ BnFromHex(
string and sets size to the normalized value. If size is an input 0, then the receiving buffer is
guaranteed to be large enough for the result and the size will be set to the size required for
bigNum (leading zeros suppressed). */
/* The conversion for a little-endian machine simply requires that all significant bytes of the
bigNum be reversed. For a big-endian machine, rather than process unpack each word individually,
the bigNum is converted to little-endian words, copied, and then converted back to big-endian. */
LIB_EXPORT BOOL
BnToBytes(
bigConst bn,
@ -198,27 +201,32 @@ BnToBytes(
}
else
{
#if BIG_ENDIAN_TPM
// Copy the constant input value into a modifiable value
BN_VAR(bnL, LARGEST_NUMBER_BITS * 2);
BnCopy(bnL, bn);
// byte swap the words in the local value to make them little-endian
for(count = 0; count < bnL->size; count++)
bnL->d[count] = SWAP_CRYPT_WORD(bnL->d[count]);
bn = (bigConst)bnL;
#endif
if(*size == 0)
*size = (NUMBYTES)requiredSize;
pAssert(requiredSize <= *size);
#if BIG_ENDIAN_TPM
// byte swap the words to make them little-endian
for(count = 0; count < bn->size; count++)
bn->d[count] = SWAP_CRYPT_WORD(bn->d[count]);
#endif
// Byte swap the number (not words but the whole value)
count = *size;
// Start from the least significant word and offset to the most significant
// byte which is in some high word
pFrom = (BYTE *)(&bn->d[0]) + requiredSize - 1;
pTo = buffer;
// If the number of output bytes is larger than the number bytes required
// for the input number, pad with zeros
for(count = *size; count > requiredSize; count--)
*pTo++ = 0;
// Move the most significant byte at the end of the BigNum to the next most
// significant byte position of the 2B and repeat for all significant bytes.
for(; requiredSize > 0; requiredSize--)
*pTo++ = *pFrom--;
#if BIG_ENDIAN_TPM
// Put the input back into big-endian format
for(count = 0; count < bn->size; count++)
bn->d[count] = SWAP_CRYPT_WORD(bn->d[count]);
#endif
}
return TRUE;
}

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: BnEccData.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: BnEccData.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,15 +55,15 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
/* 10.2.3 BnEccData.c */
#include "Tpm.h"
/* both the new, refactored code and the old code (this is necessary so that errata can be
/* both the new, re-factored code and the old code (this is necessary so that errata can be
handled). Another script (BnEccData().pl) does the conversion and generates BnEccData.c for use
in the refactored code. */
in the re-factored code. */
#if defined TPM_ALG_ECC && !defined USE_2B_ECC_DATA
const struct {
crypt_uword_t allocated;

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: BnMath.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: BnMath.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -489,14 +489,21 @@ BnGetRandomBits(
RAND_STATE *rand
)
{
TPM2B_TYPE(LARGEST, LARGEST_NUMBER);
TPM2B_LARGEST large;
// Since this could be used for ECC key generation using the extra bits method,
// make sure that the value is large enough
TPM2B_TYPE(LARGEST, LARGEST_NUMBER + 8);
TPM2B_LARGEST large;
//
large.b.size = (UINT16)BITS_TO_BYTES(bits);
DRBG_Generate(rand, large.t.buffer, large.t.size);
BnFrom2B(n, &large.b);
BnMaskBits(n, bits);
return TRUE;
if(DRBG_Generate(rand, large.t.buffer, large.t.size) == large.t.size)
{
if(BnFrom2B(n, &large.b) != NULL)
{
if(BnMaskBits(n, bits))
return TRUE;
}
}
return FALSE;
}
/* 10.2.4.3.21 BnGenerateRandomInRange() */
/* Function to generate a random number r in the range 1 <= r < limit. The function gets a random

View File

@ -3,7 +3,7 @@
/* Number of capability values that will fit into the largest data buffer */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Capabilities.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Capabilities.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -61,6 +61,7 @@
#ifndef _CAPABILITIES_H
#define _CAPABILITIES_H
#define MAX_CAP_DATA (MAX_CAP_BUFFER - sizeof(TPM_CAP)-sizeof(UINT32))
#define MAX_CAP_ALGS (MAX_CAP_DATA / sizeof(TPMS_ALG_PROPERTY))
#define MAX_CAP_HANDLES (MAX_CAP_DATA / sizeof(TPM_HANDLE))
@ -69,9 +70,6 @@
#define MAX_PCR_PROPERTIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PCR_SELECT))
#define MAX_ECC_CURVES (MAX_CAP_DATA / sizeof(TPM_ECC_CURVE))
#define MAX_TAGGED_POLICIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_POLICY))
#define MAX_AC_CAPABILITIES (MAX_CAP_DATA / sizeof(TPMS_AC_OUTPUT))
#ifdef TPM_CC_AC_GetCapability
/* This is #defined because TPMA_AC_CAPABILITIES might not be defined */
# define MAX_AC_CAPABILITIES (MAX_CAP_DATA / sizeof(TPMS_AC_OUTPUT))
#endif
#endif

View File

@ -3,7 +3,7 @@
/* Used by the simulator to mimic a hardware clock */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Clock.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Clock.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -115,7 +115,8 @@ static uint64_t tpmclock(void)
hardware events. */
/* C.3.3.2. _plat__TimerReset() */
/* This function sets current system clock time as t0 for counting TPM time. This function is called
at a power on event to reset the clock. */
at a power on event to reset the clock. When the clock is reset, the indication that the clock
was stopped is also set. */
LIB_EXPORT void
_plat__TimerReset(
void

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CommandAudit.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CommandAudit.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -214,8 +214,9 @@ CommandAuditCapGetCCList(
{
// If we have not filled up the return list, add this command
// code to its
TPM_CC cc = s_ccAttr[commandIndex].commandIndex;
if(s_ccAttr[commandIndex].V)
TPM_CC cc = GET_ATTRIBUTE(s_ccAttr[commandIndex],
TPMA_CC, commandIndex);
if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V))
cc += (1 << 29);
commandList->commandCodes[commandList->count] = cc;
commandList->count++;

View File

@ -3,7 +3,7 @@
/* Functions for testing various command properties */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CommandCodeAttributes.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CommandCodeAttributes.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -134,14 +134,16 @@ GetClosestCommandIndex(
// entry.
// Note: Put this check first so that the typical case of only one vendor-
// specific command doesn't waste any more time.
if(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE].commandIndex >= searchIndex)
if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE], TPMA_CC,
commandIndex) >= searchIndex)
{
// the vendor array is always assumed to be packed so there is
// no need to check to see if the command is implemented
return LIBRARY_COMMAND_ARRAY_SIZE;
}
// See if this is out of range on the top
if(s_ccAttr[COMMAND_COUNT - 1].commandIndex < searchIndex)
if(GET_ATTRIBUTE(s_ccAttr[COMMAND_COUNT - 1], TPMA_CC, commandIndex)
< searchIndex)
{
return UNIMPLEMENTED_COMMAND_INDEX;
}
@ -154,7 +156,8 @@ GetClosestCommandIndex(
while(min <= max)
{
commandIndex = (min + max + 1) / 2;
diff = s_ccAttr[commandIndex].commandIndex - searchIndex;
diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)
- searchIndex;
if(diff == 0)
return commandIndex;
if(diff > 0)
@ -180,7 +183,8 @@ GetClosestCommandIndex(
#endif
}
// Get here if the V-Bit was not set in 'commandCode'
if(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE - 1].commandIndex < searchIndex)
if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE - 1], TPMA_CC,
commandIndex) < searchIndex)
{
// requested index is out of the range to the top
#if VENDOR_COMMAND_ARRAY_SIZE > 0
@ -199,7 +203,7 @@ GetClosestCommandIndex(
}
// If the request is lower than any value in the array, then return
// the lowest value (needs to be an index for an implemented command
if(s_ccAttr[0].commandIndex >= searchIndex)
if(GET_ATTRIBUTE(s_ccAttr[0], TPMA_CC, commandIndex) >= searchIndex)
{
return NextImplementedIndex(0);
}
@ -221,7 +225,8 @@ GetClosestCommandIndex(
while(min <= max)
{
commandIndex = (min + max + 1) / 2;
diff = s_ccAttr[commandIndex].commandIndex - searchIndex;
diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC,
commandIndex) - searchIndex;
if(diff == 0)
return commandIndex;
if(diff > 0)
@ -283,9 +288,9 @@ CommandCodeToCommandIndex(
// requested, then the command is not implemented.
if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX)
{
if((s_ccAttr[commandIndex].commandIndex != searchIndex)
|| ((s_ccAttr[commandIndex].V == SET) && !vendor)
|| ((s_ccAttr[commandIndex].V == CLEAR) && vendor))
if((GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)
!= searchIndex)
|| (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) != vendor)
commandIndex = UNIMPLEMENTED_COMMAND_INDEX;
}
return commandIndex;
@ -316,8 +321,9 @@ GetCommandCode(
COMMAND_INDEX commandIndex // IN: the command index
)
{
TPM_CC commandCode = s_ccAttr[commandIndex].commandIndex;
if(s_ccAttr[commandIndex].V)
TPM_CC commandCode = GET_ATTRIBUTE(s_ccAttr[commandIndex],
TPMA_CC, commandIndex);
if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V))
commandCode += CC_VEND;
return commandCode;
}
@ -423,9 +429,9 @@ IsWriteOperation(
#ifdef WRITE_LOCK
return ((s_commandAttributes[commandIndex] & WRITE_LOCK) != 0);
#else
if(!s_ccAttr[commandIndex].V)
if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V))
{
switch(s_ccAttr[commandIndex].commandIndex)
switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex))
{
case TPM_CC_NV_Write:
#if CC_NV_Increment
@ -463,9 +469,9 @@ IsReadOperation(
#ifdef READ_LOCK
return ((s_commandAttributes[commandIndex] & READ_LOCK) != 0);
#else
if(!s_ccAttr[commandIndex].V)
if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V))
{
switch(s_ccAttr[commandIndex].commandIndex)
switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex))
{
case TPM_CC_NV_Read:
case TPM_CC_PolicyNV:
@ -537,6 +543,6 @@ IsVendorCommand(
COMMAND_INDEX commandIndex // IN: command index to check
)
{
return (s_ccAttr[commandIndex].V == SET);
return (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V));
}
#endif // INLINE_FUNCTIONS

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CommandDispatchData.h 828 2016-11-18 21:19:43Z kgoldman $ */
/* $Id: CommandDispatchData.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -68,6 +68,10 @@
const UNMARSHAL_t UnmarshalArray[] = {
#define TPMI_DH_CONTEXT_H_UNMARSHAL 0
(UNMARSHAL_t)TPMI_DH_CONTEXT_Unmarshal,
#if 0
#define TPMI_RH_AC_H_UNMARSHAL (TPMI_DH_CONTEXT_H_UNMARSHAL + 1)
(UNMARSHAL_t)TPMI_RH_AC_Unmarshal,
#endif
#define TPMI_RH_CLEAR_H_UNMARSHAL (TPMI_DH_CONTEXT_H_UNMARSHAL + 1)
(UNMARSHAL_t)TPMI_RH_CLEAR_Unmarshal,
#define TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL (TPMI_RH_CLEAR_H_UNMARSHAL + 1)
@ -140,7 +144,9 @@ const UNMARSHAL_t UnmarshalArray[] = {
(UNMARSHAL_t)TPM2B_SENSITIVE_DATA_Unmarshal,
#define TPM2B_TEMPLATE_P_UNMARSHAL (TPM2B_SENSITIVE_DATA_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPM2B_TEMPLATE_Unmarshal,
#define UINT8_P_UNMARSHAL (TPM2B_TEMPLATE_P_UNMARSHAL + 1)
#define TPM2B_TIMEOUT_P_UNMARSHAL (TPM2B_TEMPLATE_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPM2B_TIMEOUT_Unmarshal,
#define UINT8_P_UNMARSHAL (TPM2B_TIMEOUT_P_UNMARSHAL + 1)
(UNMARSHAL_t)UINT8_Unmarshal,
#define TPMI_DH_CONTEXT_P_UNMARSHAL (UINT8_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPMI_DH_CONTEXT_Unmarshal,
@ -172,6 +178,10 @@ const UNMARSHAL_t UnmarshalArray[] = {
(UNMARSHAL_t)TPMT_TK_HASHCHECK_Unmarshal,
#define TPMT_TK_VERIFIED_P_UNMARSHAL (TPMT_TK_HASHCHECK_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPMT_TK_VERIFIED_Unmarshal,
#if 0
#define TPM_AT_P_UNMARSHAL (TPMT_TK_VERIFIED_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPM_AT_Unmarshal,
#endif
#define TPM_CAP_P_UNMARSHAL (TPMT_TK_VERIFIED_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPM_CAP_Unmarshal,
#define TPM_CLOCK_ADJUST_P_UNMARSHAL (TPM_CAP_P_UNMARSHAL + 1)
@ -190,11 +200,13 @@ const UNMARSHAL_t UnmarshalArray[] = {
#define PARAMETER_FIRST_FLAG_TYPE (UINT64_P_UNMARSHAL + 1)
#define TPM2B_PUBLIC_P_UNMARSHAL (UINT64_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPM2B_PUBLIC_Unmarshal,
#define TPMI_ALG_HASH_P_UNMARSHAL (TPM2B_PUBLIC_P_UNMARSHAL + 1)
#define TPMI_ALG_CIPHER_MODE_P_UNMARSHAL (TPM2B_PUBLIC_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPMI_ALG_CIPHER_MODE_Unmarshal,
#define TPMI_ALG_HASH_P_UNMARSHAL (TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPMI_ALG_HASH_Unmarshal,
#define TPMI_ALG_SYM_MODE_P_UNMARSHAL (TPMI_ALG_HASH_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPMI_ALG_SYM_MODE_Unmarshal,
#define TPMI_DH_PCR_P_UNMARSHAL (TPMI_ALG_SYM_MODE_P_UNMARSHAL + 1)
#define TPMI_ALG_MAC_SCHEME_P_UNMARSHAL (TPMI_ALG_HASH_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPMI_ALG_MAC_SCHEME_Unmarshal,
#define TPMI_DH_PCR_P_UNMARSHAL (TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPMI_DH_PCR_Unmarshal,
#define TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL (TPMI_DH_PCR_P_UNMARSHAL + 1)
(UNMARSHAL_t)TPMI_ECC_KEY_EXCHANGE_Unmarshal,
@ -253,8 +265,14 @@ const MARSHAL_t MarshalArray[] = {
(MARSHAL_t)TPM2B_PUBLIC_KEY_RSA_Marshal,
#define TPM2B_SENSITIVE_DATA_P_MARSHAL (TPM2B_PUBLIC_KEY_RSA_P_MARSHAL + 1)
(MARSHAL_t)TPM2B_SENSITIVE_DATA_Marshal,
#define UINT8_P_MARSHAL (TPM2B_SENSITIVE_DATA_P_MARSHAL + 1)
#define TPM2B_TIMEOUT_P_MARSHAL (TPM2B_SENSITIVE_DATA_P_MARSHAL + 1)
(MARSHAL_t)TPM2B_TIMEOUT_Marshal,
#define UINT8_P_MARSHAL (TPM2B_TIMEOUT_P_MARSHAL + 1)
(MARSHAL_t)UINT8_Marshal,
#if 0
#define TPML_AC_CAPABILITIES_P_MARSHAL (UINT8_P_MARSHAL + 1)
(MARSHAL_t)TPML_AC_CAPABILITIES_Marshal,
#endif
#define TPML_ALG_P_MARSHAL (UINT8_P_MARSHAL + 1)
(MARSHAL_t)TPML_ALG_Marshal,
#define TPML_DIGEST_P_MARSHAL (TPML_ALG_P_MARSHAL + 1)
@ -263,6 +281,10 @@ const MARSHAL_t MarshalArray[] = {
(MARSHAL_t)TPML_DIGEST_VALUES_Marshal,
#define TPML_PCR_SELECTION_P_MARSHAL (TPML_DIGEST_VALUES_P_MARSHAL + 1)
(MARSHAL_t)TPML_PCR_SELECTION_Marshal,
#if 0
#define TPMS_AC_OUTPUT_P_MARSHAL (TPML_PCR_SELECTION_P_MARSHAL + 1)
(MARSHAL_t)TPMS_AC_OUTPUT_Marshal,
#endif
#define TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL (TPML_PCR_SELECTION_P_MARSHAL + 1)
(MARSHAL_t)TPMS_ALGORITHM_DETAIL_ECC_Marshal,
#define TPMS_CAPABILITY_DATA_P_MARSHAL (TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL + 1)
@ -288,9 +310,7 @@ const MARSHAL_t MarshalArray[] = {
#define UINT16_P_MARSHAL (UINT32_P_MARSHAL + 1)
(MARSHAL_t)UINT16_Marshal,
#define RESPONSE_PARAMETER_LAST_TYPE (UINT16_P_MARSHAL)
};
#if CC_Startup == YES
#include "Startup_fp.h"
@ -1138,7 +1158,7 @@ EncryptDecrypt_COMMAND_DESCRIPTOR_t _EncryptDecryptData = {
(UINT16)(offsetof(EncryptDecrypt_Out, ivOut))},
/* types */ {TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_YES_NO_P_UNMARSHAL,
TPMI_ALG_SYM_MODE_P_UNMARSHAL + ADD_FLAG,
TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + ADD_FLAG,
TPM2B_IV_P_UNMARSHAL,
TPM2B_MAX_BUFFER_P_UNMARSHAL,
END_OF_LIST,
@ -1177,7 +1197,7 @@ EncryptDecrypt2_COMMAND_DESCRIPTOR_t _EncryptDecrypt2Data = {
/* types */ {TPMI_DH_OBJECT_H_UNMARSHAL,
TPM2B_MAX_BUFFER_P_UNMARSHAL,
TPMI_YES_NO_P_UNMARSHAL,
TPMI_ALG_SYM_MODE_P_UNMARSHAL + ADD_FLAG,
TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + ADD_FLAG,
TPM2B_IV_P_UNMARSHAL,
END_OF_LIST,
TPM2B_MAX_BUFFER_P_MARSHAL,
@ -1254,6 +1274,38 @@ HMAC_COMMAND_DESCRIPTOR_t _HMACData = {
#else
#define _HMACDataAddress 0
#endif
#if CC_MAC == YES
#include "MAC_fp.h"
typedef TPM_RC (MAC_Entry)(
MAC_In *in,
MAC_Out *out
);
typedef const struct {
MAC_Entry *entry;
UINT16 inSize;
UINT16 outSize;
UINT16 offsetOfTypes;
UINT16 paramOffsets[2];
BYTE types[6];
} MAC_COMMAND_DESCRIPTOR_t;
MAC_COMMAND_DESCRIPTOR_t _MACData = {
/* entry */ &TPM2_MAC,
/* inSize */ (UINT16)(sizeof(MAC_In)),
/* outSize */ (UINT16)(sizeof(MAC_Out)),
/* offsetOfTypes */ offsetof(MAC_COMMAND_DESCRIPTOR_t, types),
/* offsets */ {(UINT16)(offsetof(MAC_In, buffer)),
(UINT16)(offsetof(MAC_In, inScheme))},
/* types */ {TPMI_DH_OBJECT_H_UNMARSHAL,
TPM2B_MAX_BUFFER_P_UNMARSHAL,
TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + ADD_FLAG,
END_OF_LIST,
TPM2B_DIGEST_P_MARSHAL,
END_OF_LIST}
};
#define _MACDataAddress (&_MACData)
#else
#define _MACDataAddress 0
#endif
#if CC_GetRandom == YES
#include "GetRandom_fp.h"
typedef TPM_RC (GetRandom_Entry)(
@ -1340,6 +1392,38 @@ HMAC_Start_COMMAND_DESCRIPTOR_t _HMAC_StartData = {
#else
#define _HMAC_StartDataAddress 0
#endif
#if CC_MAC_Start == YES
#include "MAC_Start_fp.h"
typedef TPM_RC (MAC_Start_Entry)(
MAC_Start_In *in,
MAC_Start_Out *out
);
typedef const struct {
MAC_Start_Entry *entry;
UINT16 inSize;
UINT16 outSize;
UINT16 offsetOfTypes;
UINT16 paramOffsets[2];
BYTE types[6];
} MAC_Start_COMMAND_DESCRIPTOR_t;
MAC_Start_COMMAND_DESCRIPTOR_t _MAC_StartData = {
/* entry */ &TPM2_MAC_Start,
/* inSize */ (UINT16)(sizeof(MAC_Start_In)),
/* outSize */ (UINT16)(sizeof(MAC_Start_Out)),
/* offsetOfTypes */ offsetof(MAC_Start_COMMAND_DESCRIPTOR_t, types),
/* offsets */ {(UINT16)(offsetof(MAC_Start_In, auth)),
(UINT16)(offsetof(MAC_Start_In, inScheme))},
/* types */ {TPMI_DH_OBJECT_H_UNMARSHAL,
TPM2B_DIGEST_P_UNMARSHAL,
TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + ADD_FLAG,
END_OF_LIST,
UINT32_H_MARSHAL,
END_OF_LIST}
};
#define _MAC_StartDataAddress (&_MAC_StartData)
#else
#define _MAC_StartDataAddress 0
#endif
#if CC_HashSequenceStart == YES
#include "HashSequenceStart_fp.h"
typedef TPM_RC (HashSequenceStart_Entry)(
@ -2100,7 +2184,7 @@ PolicySigned_COMMAND_DESCRIPTOR_t _PolicySignedData = {
UINT32_P_UNMARSHAL,
TPMT_SIGNATURE_P_UNMARSHAL,
END_OF_LIST,
TPM2B_DIGEST_P_MARSHAL,
TPM2B_TIMEOUT_P_MARSHAL,
TPMT_TK_AUTH_P_MARSHAL,
END_OF_LIST}
};
@ -2140,7 +2224,7 @@ PolicySecret_COMMAND_DESCRIPTOR_t _PolicySecretData = {
TPM2B_DIGEST_P_UNMARSHAL,
UINT32_P_UNMARSHAL,
END_OF_LIST,
TPM2B_DIGEST_P_MARSHAL,
TPM2B_TIMEOUT_P_MARSHAL,
TPMT_TK_AUTH_P_MARSHAL,
END_OF_LIST}
};
@ -2172,7 +2256,7 @@ PolicyTicket_COMMAND_DESCRIPTOR_t _PolicyTicketData = {
(UINT16)(offsetof(PolicyTicket_In, authName)),
(UINT16)(offsetof(PolicyTicket_In, ticket))},
/* types */ {TPMI_SH_POLICY_H_UNMARSHAL,
TPM2B_DIGEST_P_UNMARSHAL,
TPM2B_TIMEOUT_P_UNMARSHAL,
TPM2B_DIGEST_P_UNMARSHAL,
TPM2B_DIGEST_P_UNMARSHAL,
TPM2B_NAME_P_UNMARSHAL,
@ -3802,6 +3886,108 @@ NV_Certify_COMMAND_DESCRIPTOR_t _NV_CertifyData = {
#else
#define _NV_CertifyDataAddress 0
#endif
#if CC_AC_GetCapability == YES
#include "AC_GetCapability_fp.h"
typedef TPM_RC (AC_GetCapability_Entry)(
AC_GetCapability_In *in,
AC_GetCapability_Out *out
);
typedef const struct {
AC_GetCapability_Entry *entry;
UINT16 inSize;
UINT16 outSize;
UINT16 offsetOfTypes;
UINT16 paramOffsets[3];
BYTE types[7];
} AC_GetCapability_COMMAND_DESCRIPTOR_t;
AC_GetCapability_COMMAND_DESCRIPTOR_t _AC_GetCapabilityData = {
/* entry */ &TPM2_AC_GetCapability,
/* inSize */ (UINT16)(sizeof(AC_GetCapability_In)),
/* outSize */ (UINT16)(sizeof(AC_GetCapability_Out)),
/* offsetOfTypes */ offsetof(AC_GetCapability_COMMAND_DESCRIPTOR_t, types),
/* offsets */ {(UINT16)(offsetof(AC_GetCapability_In, capability)),
(UINT16)(offsetof(AC_GetCapability_In, count)),
(UINT16)(offsetof(AC_GetCapability_Out, capabilitiesData))},
/* types */ {TPMI_RH_AC_H_UNMARSHAL,
TPM_AT_P_UNMARSHAL,
UINT32_P_UNMARSHAL,
END_OF_LIST,
UINT8_P_MARSHAL,
TPML_AC_CAPABILITIES_P_MARSHAL,
END_OF_LIST}
};
#define _AC_GetCapabilityDataAddress (&_AC_GetCapabilityData)
#else
#define _AC_GetCapabilityDataAddress 0
#endif
#if CC_AC_Send == YES
#include "AC_Send_fp.h"
typedef TPM_RC (AC_Send_Entry)(
AC_Send_In *in,
AC_Send_Out *out
);
typedef const struct {
AC_Send_Entry *entry;
UINT16 inSize;
UINT16 outSize;
UINT16 offsetOfTypes;
UINT16 paramOffsets[3];
BYTE types[7];
} AC_Send_COMMAND_DESCRIPTOR_t;
AC_Send_COMMAND_DESCRIPTOR_t _AC_SendData = {
/* entry */ &TPM2_AC_Send,
/* inSize */ (UINT16)(sizeof(AC_Send_In)),
/* outSize */ (UINT16)(sizeof(AC_Send_Out)),
/* offsetOfTypes */ offsetof(AC_Send_COMMAND_DESCRIPTOR_t, types),
/* offsets */ {(UINT16)(offsetof(AC_Send_In, authHandle)),
(UINT16)(offsetof(AC_Send_In, ac)),
(UINT16)(offsetof(AC_Send_In, acDataIn))},
/* types */ {TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_AC_H_UNMARSHAL,
TPM2B_MAX_BUFFER_P_UNMARSHAL,
END_OF_LIST,
TPMS_AC_OUTPUT_P_MARSHAL,
END_OF_LIST}
};
#define _AC_SendDataAddress (&_AC_SendData)
#else
#define _AC_SendDataAddress 0
#endif
#if CC_Policy_AC_SendSelect == YES
#include "Policy_AC_SendSelect_fp.h"
typedef TPM_RC (Policy_AC_SendSelect_Entry)(
Policy_AC_SendSelect_In *in
);
typedef const struct {
Policy_AC_SendSelect_Entry *entry;
UINT16 inSize;
UINT16 outSize;
UINT16 offsetOfTypes;
UINT16 paramOffsets[4];
BYTE types[7];
} Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t;
Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t _Policy_AC_SendSelectData = {
/* entry */ &TPM2_Policy_AC_SendSelect,
/* inSize */ (UINT16)(sizeof(Policy_AC_SendSelect_In)),
/* outSize */ 0,
/* offsetOfTypes */ offsetof(Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t, types),
/* offsets */ {(UINT16)(offsetof(Policy_AC_SendSelect_In, objectName)),
(UINT16)(offsetof(Policy_AC_SendSelect_In, authHandleName)),
(UINT16)(offsetof(Policy_AC_SendSelect_In, acName)),
(UINT16)(offsetof(Policy_AC_SendSelect_In, includeObject))},
/* types */ {TPMI_SH_POLICY_H_UNMARSHAL,
TPM2B_NAME_P_UNMARSHAL,
TPM2B_NAME_P_UNMARSHAL,
TPM2B_NAME_P_UNMARSHAL,
TPMI_YES_NO_P_UNMARSHAL,
END_OF_LIST,
END_OF_LIST}
};
#define _Policy_AC_SendSelectDataAddress (&_Policy_AC_SendSelectData)
#else
#define _Policy_AC_SendSelectDataAddress 0
#endif
#if CC_Vendor_TCG_Test == YES
#include "Vendor_TCG_Test_fp.h"
typedef TPM_RC (Vendor_TCG_Test_Entry)(
@ -3994,9 +4180,17 @@ COMMAND_DESCRIPTOR_t *s_CommandDataArray[] = {
#if (PAD_LIST || CC_ECDH_ZGen)
(COMMAND_DESCRIPTOR_t *)_ECDH_ZGenDataAddress,
#endif
#if (PAD_LIST || CC_HMAC)
#if (PAD_LIST || (CC_HMAC || CC_MAC))
# if CC_HMAC
(COMMAND_DESCRIPTOR_t *)_HMACDataAddress,
#endif
# endif
# if CC_MAC
(COMMAND_DESCRIPTOR_t *)_MACDataAddress,
# endif
# if (CC_HMAC || CC_MAC) > 1
# error "More than one aliased command defined"
# endif
#endif // CC_HMAC CC_MAC
#if (PAD_LIST || CC_Import)
(COMMAND_DESCRIPTOR_t *)_ImportDataAddress,
#endif
@ -4012,9 +4206,17 @@ COMMAND_DESCRIPTOR_t *s_CommandDataArray[] = {
#if (PAD_LIST)
(COMMAND_DESCRIPTOR_t *)0,
#endif
#if (PAD_LIST || CC_HMAC_Start)
#if (PAD_LIST || (CC_HMAC_Start || CC_MAC_Start))
# if CC_HMAC_Start
(COMMAND_DESCRIPTOR_t *)_HMAC_StartDataAddress,
#endif
# endif
# if CC_MAC_Start
(COMMAND_DESCRIPTOR_t *)_MAC_StartDataAddress,
# endif
# if (CC_HMAC_Start || CC_MAC_Start) > 1
# error "More than one aliased command defined"
# endif
#endif // CC_HMAC_Start CC_MAC_Start
#if (PAD_LIST || CC_SequenceUpdate)
(COMMAND_DESCRIPTOR_t *)_SequenceUpdateDataAddress,
#endif
@ -4183,6 +4385,15 @@ COMMAND_DESCRIPTOR_t *s_CommandDataArray[] = {
#if (PAD_LIST || CC_EncryptDecrypt2)
(COMMAND_DESCRIPTOR_t *)_EncryptDecrypt2DataAddress,
#endif
#if (PAD_LIST || CC_AC_GetCapability)
(COMMAND_DESCRIPTOR_t *)_AC_GetCapabilityDataAddress,
#endif // CC_AC_GetCapability
#if (PAD_LIST || CC_AC_Send)
(COMMAND_DESCRIPTOR_t *)_AC_SendDataAddress,
#endif // CC_AC_Send
#if (PAD_LIST || CC_Policy_AC_SendSelect)
(COMMAND_DESCRIPTOR_t *)_Policy_AC_SendSelectDataAddress,
#endif // CC_Policy_AC_SendSelect
#if (PAD_LIST || CC_Vendor_TCG_Test)
(COMMAND_DESCRIPTOR_t *)_Vendor_TCG_TestDataAddress,
#endif

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CompilerDependencies.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CompilerDependencies.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Context Management */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: ContextCommands.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: ContextCommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -63,6 +63,9 @@
#include "ContextSave_fp.h"
#ifdef TPM_CC_ContextSave // Conditional expansion of this file
#include "Context_spt_fp.h"
/* Error Returns Meaning */
/* TPM_RC_CONTEXT_GAP a contextID could not be assigned for a session context save */
/* TPM_RC_TOO_MANY_CONTEXTS no more contexts can be saved as the counter has maxed out */
TPM_RC
TPM2_ContextSave(
ContextSave_In *in, // IN: input parameter list
@ -82,7 +85,18 @@ TPM2_ContextSave(
// the update of state reset data. If the state is orderly and
// cannot be changed, exit early.
RETURN_IF_ORDERLY;
// Internal Data Update
// This implementation does not do things in quite the same way as described in
// Part 2 of the specification. In Part 2, it indicates that the
// TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is
// implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to
// determine the amount of data in the encrypted data. That part is not
// independently sized. This makes the actual size 2 bytes smaller than
// calculated using Part 2. Since this is opaque to the caller, it is not
// necessary to fix. The actual size is returned by TPM2_GetCapabilties().
// Initialize output handle. At the end of command action, the output
// handle of an object will be replaced, while the output handle
// for a session will be the same as input
@ -215,7 +229,6 @@ TPM2_ContextLoad(
ContextLoad_Out *out // OUT: output parameter list
)
{
// Local Variables
TPM_RC result;
TPM2B_DIGEST integrityToCompare;
TPM2B_DIGEST integrity;
@ -225,6 +238,9 @@ TPM2_ContextLoad(
TPM2B_SYM_KEY symKey;
TPM2B_IV iv;
// Input Validation
// See discussion about the context format in TPM2_ContextSave Detailed Actions
// IF this is a session context, make sure that the sequence number is
// consistent with the version in the slot
// Check context blob size
@ -297,7 +313,7 @@ TPM2_ContextLoad(
RETURN_IF_ORDERLY;
// Check if input handle points to a valid saved session and that the
// sequence number makes sense
if(!SequenceNumbereForSavedContextIsValid(&in->context))
if(!SequenceNumberForSavedContextIsValid(&in->context))
return TPM_RCS_HANDLE + RC_ContextLoad_context;
// Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error
// may be returned at this point

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Context_spt.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: Context_spt.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -75,7 +75,7 @@ ComputeContextProtectionKey(
{
UINT16 symKeyBits; // number of bits in the parent's
// symmetric key
TPM2B_AUTH *proof = NULL; // the proof value to use. Is null for
TPM2B_PROOF *proof = NULL; // the proof value to use. Is null for
// everything but a primary object in
// the Endorsement Hierarchy
BYTE kdfResult[sizeof(TPMU_HA) * 2];// Value produced by the KDF
@ -119,7 +119,7 @@ ComputeContextIntegrity(
)
{
HMAC_STATE hmacState;
TPM2B_AUTH *proof;
TPM2B_PROOF *proof;
UINT16 integritySize;
// Get proof value
proof = HierarchyGetProof(contextBlob->hierarchy);

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptSelfTest.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptSelfTest.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -189,7 +189,7 @@ CryptInitializeToTest(
}
/* 10.2.7.2.5 CryptTestAlgorithm() */
/* Only point of contact with the actual self tests. If a self-test fails, there is no return and
the TPM goes into failure mode. The call to TestAlgorithm() uses an algorithms selector and a bit
the TPM goes into failure mode. The call to TestAlgorithm() uses an algorithm selector and a bit
vector. When the test is run, the corresponding bit in toTest and in g_toTest is CLEAR. If toTest
is NULL, then only the bit in g_toTest is CLEAR. There is a special case for the call to
TestAlgorithm(). When alg is TPM_ALG_ERROR, TestAlgorithm() will CLEAR any bit in toTest for

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Interfaces to the CryptoEngine() */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptUtil.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptUtil.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -129,6 +129,7 @@ CryptHMACVerifySignature(
/* 10.2.6.3.3 CryptGenerateKeyedHash() */
/* This function creates a keyedHash object. */
/* Error Returns Meaning */
/* TPM_RC_NO_RESULT cannot get values from random number generator */
/* TPM_RC_SIZE sensitive data size is larger than allowed for the scheme */
static TPM_RC
CryptGenerateKeyedHash(
@ -163,8 +164,8 @@ CryptGenerateKeyedHash(
//If the user provided the key, check that it is a proper size
if(sensitiveCreate->data.t.size != 0)
{
if(publicArea->objectAttributes.decrypt
|| publicArea->objectAttributes.sign)
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
|| IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
{
if(sensitiveCreate->data.t.size > hashBlockSize)
return TPM_RC_SIZE;
@ -180,12 +181,12 @@ CryptGenerateKeyedHash(
}
else
{
// If the TPM is going to generate the data, then set the size to be the
// The TPM is going to generate the data, so set the size to be the
// size of the digest of the algorithm
int sizeInBits = digestSize * 8;
TPM2B_SENSITIVE_DATA *key = &sensitive->sensitive.bits;
key->t.size = CryptRandMinMax(key->t.buffer, sizeInBits, sizeInBits / 2,
rand);
sensitive->sensitive.bits.t.size =
DRBG_Generate(rand, sensitive->sensitive.bits.t.buffer, digestSize);
if(sensitive->sensitive.bits.t.size == 0)
return TPM_RC_NO_RESULT;
}
return TPM_RC_SUCCESS;
}
@ -240,7 +241,7 @@ void
ParmEncryptSym(
TPM_ALG_ID symAlg, // IN: symmetric algorithm
TPM_ALG_ID hash, // IN: hash algorithm for KDFa
UINT16 keySizeInBits, // IN: AES key size in bits
UINT16 keySizeInBits, // IN: AES symmetric key size in bits
TPM2B *key, // IN: KDF HMAC key
TPM2B *nonceCaller, // IN: nonce caller
TPM2B *nonceTpm, // IN: nonce TPM
@ -271,9 +272,10 @@ ParmEncryptSym(
/* This function generates a symmetric cipher key. The derivation process is determined by the type
of the provided rand */
/* Error Returns Meaning */
/* TPM_RCS_KEY_SIZE key size in the public area does not match the size in the sensitive creation
/* TPM_RC_NO_RESULT cannot get a random value */
/* TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive creation
area */
/* TPM_RCS_KEY provided key value is not allowed */
/* TPM_RC_KEY provided key value is not allowed */
static TPM_RC
CryptGenerateKeySymmetric(
TPMT_PUBLIC *publicArea, // IN/OUT: The public area template
@ -307,9 +309,13 @@ CryptGenerateKeySymmetric(
#endif
else
{
sensitive->sensitive.sym.t.size = CryptRandMinMax(
sensitive->sensitive.sym.t.buffer, keyBits, keyBits / 2, rand);
result = TPM_RC_SUCCESS;
{
sensitive->sensitive.sym.t.size =
DRBG_Generate(rand, sensitive->sensitive.sym.t.buffer,
BITS_TO_BYTES(keyBits));
result = (sensitive->sensitive.sym.t.size == 0)
? TPM_RC_NO_RESULT : TPM_RC_SUCCESS;
}
}
return result;
}
@ -475,7 +481,7 @@ CryptSecretEncrypt(
// The encryption scheme is OAEP using the nameAlg of the encrypt key.
scheme.scheme = TPM_ALG_OAEP;
scheme.details.anySig.hashAlg = encryptKey->publicArea.nameAlg;
if(encryptKey->publicArea.objectAttributes.decrypt != SET)
if(!IS_ATTRIBUTE(encryptKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
return TPM_RC_ATTRIBUTES;
switch(encryptKey->publicArea.type)
{
@ -678,8 +684,7 @@ CryptSecretDecrypt(
// seed = XOR(secret, hash, key, nonceCaller, nullNonce)
// where:
// secret the secret parameter from the TPM2_StartAuthHMAC
// command
// which contains the seed value
// command that contains the seed value
// hash nameAlg of tpmKey
// key the key or data value in the object referenced by
// entityHandle in the TPM2_StartAuthHMAC command
@ -779,7 +784,7 @@ CryptParameterEncryption(
{
FAIL(FATAL_ERROR_INTERNAL);
}
// Compute encryption key by concatenating sessionAuth with extra key
// Compute encryption key by concatenating sessionKey with extra key
MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
if(session->symmetric.algorithm == TPM_ALG_XOR)
@ -869,8 +874,8 @@ CryptComputeSymmetricUnique(
{
// For parents (symmetric and derivation), use an HMAC to compute
// the 'unique' field
if(publicArea->objectAttributes.restricted
&& publicArea->objectAttributes.decrypt)
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
&& IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt))
{
// Unique field is HMAC(sensitive->seedValue, sensitive->sensitive)
HMAC_STATE hmacState;
@ -906,12 +911,13 @@ CryptComputeSymmetricUnique(
use seed, label and context with context being the hash of the template. If the Primary Object is
in the Endorsement hierarchy, it will also populate proof with ehProof. */
/* For derived keys, seed will be the secret value from the parent, label and context will be set
according to the parameters of TPM2_Derive() and hashAlg will be set which causes the RAND_STATE
according to the parameters of TPM2_CreateLoaded() and hashAlg will be set which causes the RAND_STATE
to be a KDF generator. */
/* Error Returns Meaning */
/* TPM_RC_KEY a provided key is not an allowed value */
/* TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive creation
area for a symmetric key */
/* TPM_RC_NO_RESULT unable to get random values (only in derivation) */
/* TPM_RC_RANGE for an RSA key, the exponent is not supported */
/* TPM_RC_SIZE sensitive data size is larger than allowed for the scheme for a keyed hash object */
/* TPM_RC_VALUE exponent is not prime or could not find a prime using the provided parameters for an
@ -933,7 +939,8 @@ CryptCreateObject(
object->sensitive.authValue = sensitiveCreate->userAuth;
// If the TPM is the source of the data, set the size of the provided data to
// zero so that there's no confusion about what to do.
if(object->publicArea.objectAttributes.sensitiveDataOrigin)
if(IS_ATTRIBUTE(object->publicArea.objectAttributes,
TPMA_OBJECT, sensitiveDataOrigin))
sensitiveCreate->data.t.size = 0;
// Generate the key and unique fields for the asymmetric keys and just the
// sensitive value for symmetric object
@ -971,18 +978,20 @@ CryptCreateObject(
return result;
// Create the sensitive seed value
// If this is a primary key in the endorsement hierarchy, stir the DRBG state
// This implementation uses the proof of the storage hierarchy but the
// proof of the endorsement hierarchy would also work
// This implementation uses both shProof and ehProof to make sure that there
// is no leakage of either.
if(object->attributes.primary && object->attributes.epsHierarchy)
DRBG_AdditionalData((DRBG_STATE *)rand, &gp.shProof.b);
// Set the seed value to the size of the digest produced by the nameAlg
object->sensitive.seedValue.b.size
= CryptHashGetDigestSize(publicArea->nameAlg);
object->sensitive.seedValue.t.size = CryptRandMinMax(
object->sensitive.seedValue.t.buffer,
object->sensitive.seedValue.t.size * 8,
object->sensitive.seedValue.t.size * 8 / 2, rand);
// For symmetric values, need to compute the unique value
{
DRBG_AdditionalData((DRBG_STATE *)rand, &gp.shProof.b);
DRBG_AdditionalData((DRBG_STATE *)rand, &gp.ehProof.b);
}
// Generate a seedValue that is the size of the digest produced by nameAlg
object->sensitive.seedValue.t.size =
DRBG_Generate(rand, object->sensitive.seedValue.t.buffer,
CryptHashGetDigestSize(publicArea->nameAlg));
if(object->sensitive.seedValue.t.size == 0)
return TPM_RC_NO_RESULT;
// For symmetric objects, need to compute the unique value for the public area
if(publicArea->type == TPM_ALG_SYMCIPHER
|| publicArea->type == TPM_ALG_KEYEDHASH)
{
@ -992,9 +1001,9 @@ CryptCreateObject(
else
{
// if this is an asymmetric key and it isn't a parent, then
// can get rid of the seed.
if(publicArea->objectAttributes.sign
|| !publicArea->objectAttributes.restricted)
// get rid of the seed.
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)
|| !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
memset(&object->sensitive.seedValue, 0,
sizeof(object->sensitive.seedValue));
}
@ -1648,8 +1657,13 @@ CryptValidateKeys(
if(publicArea->nameAlg != TPM_ALG_NULL)
{
TPM2B_DIGEST compare;
#if 1
if(sensitive->seedValue.t.size != digestSize)
return TPM_RCS_KEY_SIZE;
#else
if((sensitive->seedValue.t.size > digestSize)
|| (sensitive->seedValue.t.size < digestSize/2))
#endif
return TPM_RCS_KEY_SIZE;
CryptComputeSymmetricUnique(publicArea, sensitive, &compare);
if(!MemoryEqual2B(&unique->sym.b, &compare.b))
return TPM_RC_BINDING;
@ -1659,8 +1673,8 @@ CryptValidateKeys(
}
// For a parent, need to check that the seedValue is the correct size for
// protections. It should be at least half the size of the nameAlg
if(publicArea->objectAttributes.restricted
&& publicArea->objectAttributes.decrypt
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
&& IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
&& sensitive != NULL
&& publicArea->nameAlg != TPM_ALG_NULL)
{
@ -1682,3 +1696,140 @@ CryptAlgsSetImplemented(
{
AlgorithmGetImplementedVector(&g_implementedAlgorithms);
}
/* 10.2.6.6.21 CryptSelectMac() */
/* This function is used to set the MAC scheme based on the key parameters and the input scheme. */
/* Error Returns Meaning */
/* TPM_RC_SCHEME the scheme is not a valid mac scheme */
/* TPM_RC_TYPE the input key is not a type that supports a mac */
/* TPM_RC_VALUE the input scheme and the key scheme are not compatible */
TPM_RC
CryptSelectMac(
TPMT_PUBLIC *publicArea,
TPMI_ALG_MAC_SCHEME *inMac
)
{
TPM_ALG_ID macAlg = TPM_ALG_NULL;
switch(publicArea->type)
{
case TPM_ALG_KEYEDHASH:
{
// Local value to keep lines from getting too long
TPMT_KEYEDHASH_SCHEME *scheme;
scheme = &publicArea->parameters.keyedHashDetail.scheme;
// Expect that the scheme is either HMAC or NULL
if(scheme->scheme != TPM_ALG_NULL)
macAlg = scheme->details.hmac.hashAlg;
break;
}
case TPM_ALG_SYMCIPHER:
{
TPMT_SYM_DEF_OBJECT *scheme;
scheme = &publicArea->parameters.symDetail.sym;
// Expect that the scheme is either valid symmetric cipher or NULL
if(scheme->algorithm != TPM_ALG_NULL)
macAlg = scheme->mode.sym;
break;
}
default:
return TPM_RCS_TYPE;
}
// If the input value is not TPM_ALG_NULL ...
if(*inMac != TPM_ALG_NULL)
{
// ... then either the scheme in the key must be TPM_ALG_NULL or the input
// value must match
if((macAlg != TPM_ALG_NULL) && (*inMac != macAlg))
return TPM_RCS_VALUE;
}
else
{
// Since the input value is TPM_ALG_NULL, then the key value can't be
// TPM_ALG_NULL
if(macAlg == TPM_ALG_NULL)
return TPM_RCS_VALUE;
*inMac = macAlg;
}
if(!CryptMacIsValidForKey(publicArea->type, *inMac, FALSE))
return TPM_RCS_SCHEME;
return TPM_RC_SUCCESS;
}
/* 10.2.6.6.22 CryptMacIsValidForKey() */
/* Check to see if the key type is compatible with the mac type */
BOOL
CryptMacIsValidForKey(
TPM_ALG_ID keyType,
TPM_ALG_ID macAlg,
BOOL flag
)
{
switch(keyType)
{
case TPM_ALG_KEYEDHASH:
return CryptHashIsValidAlg(macAlg, flag);
break;
case TPM_ALG_SYMCIPHER:
return CryptSmacIsValidAlg(macAlg, flag);
break;
default:
break;
}
return FALSE;
}
/* 10.2.6.6.23 CryptSmacIsValidAlg() */
/* This function is used to test if an algorithm is a supported SMAC algorithm. It needs to be
updated as new algorithms are added. */
BOOL
CryptSmacIsValidAlg(
TPM_ALG_ID alg,
BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid
)
{
switch (alg)
{
#ifdef TPM_ALG_CMAC
case TPM_ALG_CMAC:
return TRUE;
break;
#endif
case TPM_ALG_NULL:
return FLAG;
break;
default:
return FALSE;
}
}
/* 10.2.6.6.24 CryptSymModeIsValid() */
/* Function checks to see if an algorithm ID is a valid, symmetric block cipher mode for the TPM. If
flag is SET, them TPM_ALG_NULL is a valid mode. not include the modes used for SMAC */
BOOL
CryptSymModeIsValid(
TPM_ALG_ID mode,
BOOL flag
)
{
switch(mode)
{
#if ALG_CTR
case TPM_ALG_CTR:
#endif // ALG_CTR
#if ALG_OFB
case TPM_ALG_OFB:
#endif // ALG_OFB
#if ALG_CBC
case TPM_ALG_CBC:
#endif // ALG_CBC
#if ALG_CFB
case TPM_ALG_CFB:
#endif // ALG_CFB
#if ALG_ECB
case TPM_ALG_ECB:
#endif // ALG_ECB
return TRUE;
case TPM_ALG_NULL:
return flag;
break;
default:
break;
}
return FALSE;
}

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptUtil_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptUtil_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -220,6 +220,26 @@ void
CryptAlgsSetImplemented(
void
);
TPM_RC
CryptSelectMac(
TPMT_PUBLIC *publicArea,
TPMI_ALG_MAC_SCHEME *inMac
);
BOOL
CryptMacIsValidForKey(
TPM_ALG_ID keyType,
TPM_ALG_ID macAlg,
BOOL flag
);
BOOL
CryptSmacIsValidAlg(
TPM_ALG_ID alg,
BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid
);
BOOL
CryptSymModeIsValid(
TPM_ALG_ID mode,
BOOL flag
);
#endif

View File

@ -3,7 +3,7 @@
/* Dictionary Attack Logic. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: DA.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: DA.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -89,7 +89,7 @@ DAPreInstall_Init(
NV_SYNC_PERSISTENT(lockOutAuthEnabled);
return;
}
/* 8.2.3.3 DAStartup() */
/* 8.2.3.2 DAStartup() */
/* This function is called by TPM2_Startup() to initialize the DA parameters. In the case of
Startup(CLEAR), use of lockoutAuth will be enabled if the lockout recovery time is 0. Otherwise,
lockoutAuth will not be enabled until the TPM has been continuously powered for the
@ -153,7 +153,7 @@ DAStartup(
TimeUpdate();
return;
}
/* 8.2.3.4 DARegisterFailure() */
/* 8.2.3.3 DARegisterFailure() */
/* This function is called when a authorization failure occurs on an entity that is subject to
dictionary-attack protection. When a DA failure is triggered, register the failure by resetting
the relevant self-healing timer to the current time. */
@ -169,7 +169,7 @@ DARegisterFailure(
s_selfHealTimer = g_time;
return;
}
/* 8.2.3.5 DASelfHeal() */
/* 8.2.3.4 DASelfHeal() */
/* This function is called to check if sufficient time has passed to allow decrement of failedTries
or to re-enable use of lockoutAuth. */
/* This function should be called when the time interval is updated. */

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Duplication Commands */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: DuplicationCommands.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: DuplicationCommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -81,7 +81,7 @@ TPM2_Duplicate(
// Get new parent
newParent = HandleToObject(in->newParentHandle);
// duplicate key must have fixParent bit CLEAR.
if(object->publicArea.objectAttributes.fixedParent == SET)
if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, fixedParent))
return TPM_RCS_ATTRIBUTES + RC_Duplicate_objectHandle;
// Do not duplicate object with NULL nameAlg
if(object->publicArea.nameAlg == TPM_ALG_NULL)
@ -92,7 +92,8 @@ TPM2_Duplicate(
return TPM_RCS_TYPE + RC_Duplicate_newParentHandle;
// If the duplicated object has encryptedDuplication SET, then there must be
// an inner wrapper and the new parent may not be TPM_RH_NULL
if(object->publicArea.objectAttributes.encryptedDuplication == SET)
if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT,
encryptedDuplication))
{
if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
return TPM_RCS_SYMMETRIC + RC_Duplicate_symmetricAlg;
@ -167,7 +168,7 @@ TPM2_Rewrap(
return TPM_RCS_HANDLE + RC_Rewrap_oldParent;
if(in->oldParent != TPM_RH_NULL)
{
OBJECT *oldParent = HandleToObject(in->oldParent);;
OBJECT *oldParent = HandleToObject(in->oldParent);
// old parent key must be a storage object
if(!ObjectIsStorage(in->oldParent))
return TPM_RCS_TYPE + RC_Rewrap_oldParent;
@ -260,12 +261,15 @@ TPM2_Import(
TPM2B_DATA data; // symmetric key
TPMT_SENSITIVE sensitive;
TPM2B_NAME name;
TPMA_OBJECT attributes;
UINT16 innerKeySize = 0; // encrypt key size for inner
// wrapper
// Input Validation
// to save typing
attributes = in->objectPublic.publicArea.objectAttributes;
// FixedTPM and fixedParent must be CLEAR
if(in->objectPublic.publicArea.objectAttributes.fixedTPM == SET
|| in->objectPublic.publicArea.objectAttributes.fixedParent == SET)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)
|| IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent))
return TPM_RCS_ATTRIBUTES + RC_Import_objectPublic;
// Get parent pointer
parentObject = HandleToObject(in->parentHandle);
@ -287,7 +291,7 @@ TPM2_Import(
return TPM_RCS_SIZE + RC_Import_encryptionKey;
// If encryptedDuplication is SET, then the object must have an inner
// wrapper
if(in->objectPublic.publicArea.objectAttributes.encryptedDuplication)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
return TPM_RCS_ATTRIBUTES + RC_Import_encryptionKey;
}
// See if there is an outer wrapper
@ -310,7 +314,7 @@ TPM2_Import(
{
// If encrytpedDuplication is set, then the object must have an outer
// wrapper
if(in->objectPublic.publicArea.objectAttributes.encryptedDuplication)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
return TPM_RCS_ATTRIBUTES + RC_Import_inSymSeed;
data.t.size = 0;
}
@ -329,7 +333,7 @@ TPM2_Import(
// If the parent of this object has fixedTPM SET, then validate this
// object as if it were being loaded so that validation can be skipped
// when it is actually loaded.
if(parentObject->publicArea.objectAttributes.fixedTPM == SET)
if(IS_ATTRIBUTE(parentObject->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM))
{
result = ObjectLoad(NULL, NULL, &in->objectPublic.publicArea,
&sensitive, RC_Import_objectPublic, RC_Import_duplicate,

View File

@ -3,7 +3,7 @@
/* Enhanced Authorization Commands */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: EACommands.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: EACommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -155,18 +155,23 @@ TPM2_PolicySigned(
&& session->attributes.isTrialPolicy == CLEAR)
{
BOOL expiresOnReset = (in->nonceTPM.t.size == 0);
// Generate timeout buffer. The format of output timeout buffer is
// TPM-specific.
// In this implementation, the timeout parameter is the timeout relative
// to g_time with a one byte flag to indicate if the ticket will expire on
// TPM Reset
out->timeout.t.size = sizeof(authTimeout) + 1;
UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
out->timeout.t.buffer[sizeof(authTimeout)] = (BYTE)expiresOnReset;
// Compute policy ticket
authTimeout &= ~EXPIRATION_BIT;
TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject),
authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef,
&entityName, &out->policyTicket);
// Generate timeout buffer. The format of output timeout buffer is
// TPM-specific.
// Note: In this implementation, the timeout buffer value is computed after
// the ticket is produced so, when the ticket is checked, the expiration
// flag needs to be extracted before the ticket is checked.
// In the Windows compatible version, the least-significant bit of the
// timeout value is used as a flag to indicate if the authorization expires
// on reset. The flag is the MSb.
out->timeout.t.size = sizeof(authTimeout);
if(expiresOnReset)
authTimeout |= EXPIRATION_BIT;
UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
}
else
{
@ -231,18 +236,23 @@ TPM2_PolicySecret(
&& !NvIsPinPassIndex(in->authHandle))
{
BOOL expiresOnReset = (in->nonceTPM.t.size == 0);
// Generate timeout buffer. The format of output timeout buffer is
// TPM-specific.
// In this implementation, the timeout parameter is the timeout relative
// to g_time with a one byte flag to indicate if the ticket will expire on
// TPM Reset
out->timeout.t.size = sizeof(authTimeout) + 1;
UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
out->timeout.t.buffer[sizeof(authTimeout)] = (BYTE)expiresOnReset;
// Compute policy ticket
authTimeout &= ~EXPIRATION_BIT;
TicketComputeAuth(TPM_ST_AUTH_SECRET, EntityGetHierarchy(in->authHandle),
authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef,
&entityName, &out->policyTicket);
// Generate timeout buffer. The format of output timeout buffer is
// TPM-specific.
// Note: In this implementation, the timeout buffer value is computed after
// the ticket is produced so, when the ticket is checked, the expiration
// flag needs to be extracted before the ticket is checked.
out->timeout.t.size = sizeof(authTimeout);
// In the Windows compatible version, the least-significant bit of the
// timeout value is used as a flag to indicate if the authorization expires
// on reset. The flag is the MSb.
if(expiresOnReset)
authTimeout |= EXPIRATION_BIT;
UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
}
else
{
@ -287,12 +297,16 @@ TPM2_PolicyTicket(
if(session->attributes.isTrialPolicy)
return TPM_RCS_ATTRIBUTES + RC_PolicyTicket_policySession;
// Restore timeout data. The format of timeout buffer is TPM-specific.
// In this implementation, we simply copy the value of timeout to the
// buffer.
if(in->timeout.t.size != sizeof(UINT64) + 1)
// In this implementation, the most significant bit of the timeout value is
// used as the flag to indicate that the ticket expires on TPM Reset or
// TPM Restart. The flag has to be removed before the parameters and ticket
// are checked.
if(in->timeout.t.size != sizeof(UINT64))
return TPM_RCS_SIZE + RC_PolicyTicket_timeout;
authTimeout = BYTE_ARRAY_TO_UINT64(in->timeout.t.buffer);
expiresOnReset = in->timeout.t.buffer[sizeof(authTimeout)];
// extract the flag
expiresOnReset = (authTimeout & EXPIRATION_BIT) != 0;
authTimeout &= ~EXPIRATION_BIT;
// Do the normal checks on the cpHashA and timeout values
result = PolicyParameterChecks(session, authTimeout,
&in->cpHashA,
@ -898,7 +912,7 @@ TPM2_PolicyAuthorize(
hashAlg = BYTE_ARRAY_TO_UINT16(in->keySign.t.name);
// 'keySign' parameter needs to use a supported hash algorithm, otherwise
// can't tell how large the digest should be
if(!CryptHashIsImplemented(hashAlg, 0))
if(!CryptHashIsValidAlg(hashAlg, FALSE))
return TPM_RCS_HASH + RC_PolicyAuthorize_keySign;
digestSize = CryptHashGetDigestSize(hashAlg);
if(digestSize != (in->keySign.t.size - 2))

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: EncryptDecrypt2_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: EncryptDecrypt2_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -59,17 +59,17 @@
/* */
/********************************************************************************/
/* rev 134 */
/* rev 146 */
#ifndef ENCRYPTDECRYPT2_FP_H
#define ENCRYPTDECRYPT2_FP_H
typedef struct {
TPMI_DH_OBJECT keyHandle;
TPM2B_MAX_BUFFER inData;
TPMI_YES_NO decrypt;
TPMI_ALG_SYM_MODE mode;
TPM2B_IV ivIn;
TPMI_DH_OBJECT keyHandle;
TPM2B_MAX_BUFFER inData;
TPMI_YES_NO decrypt;
TPMI_ALG_CIPHER_MODE mode;
TPM2B_IV ivIn;
} EncryptDecrypt2_In;
#define RC_EncryptDecrypt2_keyHandle (TPM_RC_H + TPM_RC_1)

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: EncryptDecrypt_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: EncryptDecrypt_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -65,11 +65,11 @@
#define ENCRYPTDECRYPT_FP_H
typedef struct {
TPMI_DH_OBJECT keyHandle;
TPMI_YES_NO decrypt;
TPMI_ALG_SYM_MODE mode;
TPM2B_IV ivIn;
TPM2B_MAX_BUFFER inData;
TPMI_DH_OBJECT keyHandle;
TPMI_YES_NO decrypt;
TPMI_ALG_CIPHER_MODE mode;
TPM2B_IV ivIn;
TPM2B_MAX_BUFFER inData;
} EncryptDecrypt_In;
#define RC_EncryptDecrypt_keyHandle (TPM_RC_H + TPM_RC_1)

View File

@ -3,7 +3,7 @@
/* Encrypt Decrypt Support */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: EncryptDecrypt_spt.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: EncryptDecrypt_spt.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -94,13 +94,19 @@ EncryptDecryptShared(
if(symKey->publicArea.type != TPM_ALG_SYMCIPHER)
return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle;
// The key must be unrestricted and allow the selected operation
OK = symKey->publicArea.objectAttributes.restricted != SET;
OK = !IS_ATTRIBUTE(symKey->publicArea.objectAttributes,
TPMA_OBJECT, restricted);
if(YES == decryptIn)
OK = OK && symKey->publicArea.objectAttributes.decrypt == SET;
OK = OK && IS_ATTRIBUTE(symKey->publicArea.objectAttributes,
TPMA_OBJECT, decrypt);
else
OK = OK && symKey->publicArea.objectAttributes.sign == SET;
OK = OK && IS_ATTRIBUTE(symKey->publicArea.objectAttributes,
TPMA_OBJECT, sign);
if(!OK)
return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle;
// Make sure that key is an encrypt/decrypt key and not SMAC
if(!CryptSymModeIsValid(mode, TRUE))
return TPM_RCS_MODE + RC_EncryptDecrypt_keyHandle;
// If the key mode is not TPM_ALG_NULL...
// or TPM_ALG_NULL
if(mode != TPM_ALG_NULL)

View File

@ -3,7 +3,7 @@
/* Accessing properties for handles of various types */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Entity.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Entity.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -448,7 +448,8 @@ EntityGetHierarchy(
// If only the platform can delete the index, then it is
// considered to be in the platform hierarchy, otherwise it
// is in the owner hierarchy.
if(IsNv_TPMA_NV_PLATFORMCREATE(nvIndex->publicArea.attributes))
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV,
PLATFORMCREATE))
hierarchy = TPM_RH_PLATFORM;
else
hierarchy = TPM_RH_OWNER;

View File

@ -3,7 +3,7 @@
/* TPM variables that are not stack allocated */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Global.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Global.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -79,7 +79,6 @@ UINT64 g_time;
#ifdef CLOCK_STOPS
CLOCK_NONCE g_timeEpoch;
#endif
BOOL g_timeNewEpochNeeded;
BOOL g_pcrReConfig;
TPMI_DH_OBJECT g_DRTMHandle;
BOOL g_DrtmPreStartup;
@ -94,6 +93,15 @@ UPDATE_TYPE g_updateNV;
BOOL g_nvOk;
TPM_RC g_NvStatus;
TPM2B_AUTH g_platformUniqueDetails;
ALGORITHM_VECTOR g_implementedAlgorithms;
ALGORITHM_VECTOR g_toTest;
CRYPTO_SELF_TEST_STATE g_cryptoSelfTestState; // This structure contains the
// cryptographic self-test
#ifdef SIMULATION
BOOL g_forceFailureMode;
#endif
BOOL g_inFailureMode;
// cryptographic self-test
STATE_CLEAR_DATA gc;
STATE_RESET_DATA gr;
PERSISTENT_DATA gp;
@ -127,9 +135,11 @@ UINT64 s_maxCounter;
NV_REF s_evictNvEnd;
TPM_RC g_NvStatus;
BYTE s_indexOrderlyRam[RAM_INDEX_SPACE];
#ifndef __IGNORE_STATE__ // DO NOT DEFINE THIS VALUE
NV_INDEX s_cachedNvIndex;
NV_REF s_cachedNvRef;
BYTE *s_cachedNvRamRef;
#endif // __IGNORE_STATE__
/* 9.5.4.4 Object.c */
OBJECT s_objects[MAX_LOADED_OBJECTS];
/* 9.5.4.5 PCR.c */
@ -146,27 +156,11 @@ int s_freeSessionSlots;
UINT32 s_actionInputBuffer[1024]; // action input buffer
UINT32 s_actionOutputBuffer[1024]; // action output buffer
#endif
/* 9.5.4.8 SelfTest.c */
ALGORITHM_VECTOR g_implementedAlgorithms;
ALGORITHM_VECTOR g_toTest;
/* 9.5.4.9 g_cryptoSelfTestState */
/* This structure contains the cryptographic self-test state values. */
CRYPTO_SELF_TEST_STATE g_cryptoSelfTestState;
ALGORITHM_VECTOR AlgToTest;
/* 9.5.4.10 TpmFail.c */
#ifdef SIMULATION
BOOL g_forceFailureMode;
#endif
BOOL g_inFailureMode;
UINT32 s_failFunction;
UINT32 s_failLine;
UINT32 s_failCode;
#if 0
#ifdef TPM_ALG_ECC
/* 9.5.4.11 ECC Curves */
ECC_CURVE c_curves[ECC_CURVE_COUNT];
#endif
#endif // 0
/* 9.5.5.9 CryptRand.c */
/* This is the state used when the library uses a random number generator. A special function is
installed for the library to call. That function picks up the state from this location and uses
it for the generation of the random number. */
@ -180,7 +174,7 @@ BOOL g_manufactured = FALSE;
/* This is here for the same reason that g_manufactured is here. Both of these values can be
provided by the actual platform-specific code or by hardware indications. */
BOOL g_initialized;
/* 9.5.4.14 Purpose String Constants */
/* 9.5.4.14 Purpose-specific String Constants */
/* These string constants are shared across functions to make sure that they are all using
consistent sting values. */
TPM2B_STRING(PRIMARY_OBJECT_CREATION, "Primary Object Creation");

View File

@ -3,7 +3,7 @@
/* Internal Global Type Definitions */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Global.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Global.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -59,10 +59,11 @@
/* */
/********************************************************************************/
/* 5.12 Global.h */
/* 5.10 Global.h */
/* 5.10.2 Includes */
#if !defined _TPM_H_
#error "Should not be called"
#error "Should only be instanced in TPM.h"
#endif
#ifndef GLOBAL_H
@ -70,7 +71,6 @@
//#define SELF_TEST
_REDUCE_WARNING_LEVEL_(2)
#include <string.h>
//#include <setjmp.h>
#include <stddef.h>
_NORMAL_WARNING_LEVEL_
#ifdef SIMULATION
@ -83,6 +83,7 @@ _NORMAL_WARNING_LEVEL_
#include "CryptTest.h"
#include "BnValues.h"
#include "CryptHash.h"
#include "CryptSym.h"
#include "CryptRand.h"
#include "CryptEcc.h"
#include "CryptRsa.h"
@ -105,6 +106,10 @@ typedef BYTE AUTH_VALUE[sizeof(TPMU_HA)];
typedef BYTE TIME_INFO[sizeof(TPMS_TIME_INFO)];
/* A NAME is a BYTE array that can contain a TPMU_NAME */
typedef BYTE NAME[sizeof(TPMU_NAME)];
/* Definition for a PROOF value */
TPM2B_TYPE(PROOF, PROOF_SIZE);
/* Definition for a Primary Seed value */
TPM2B_TYPE(SEED, PRIMARY_SEED_SIZE);
/* A CLOCK_NONCE is used to tag the time value in the authorization session and in the ticket
computation so that the ticket expires when there is a time discontinuity. When the clock stops
during normal operation, the nonce is 64-bit value kept in RAM but it is a 32-bit counter when
@ -139,7 +144,7 @@ typedef struct
unsigned primary : 1; //5) SET for a primary object
unsigned temporary : 1; //6) SET for a temporary object
unsigned stClear : 1; //7) SET for an stClear object
unsigned hmacSeq : 1; //8) SET for an HMAC sequence object
unsigned hmacSeq : 1; //8) SET for an HMAC or MAC sequence object
unsigned hashSeq : 1; //9) SET for a hash sequence object
unsigned eventSeq : 1; //10) SET for an event sequence object
unsigned ticketSafe : 1; //11) SET if a ticket is safe to create
@ -388,7 +393,7 @@ typedef BYTE *NV_RAM_REF;
all the values on a little endian system. This will put the bytes with the 4-octet values in the
correct order but will swap the pinLimit and pinCount values. When written, the PIN index is
simply handled as a normal index with the octets in canonical order. */
#if BIG_ENDIAN_TPM == YES
#if BIG_ENDIAN_TPM
typedef struct
{
UINT32 pinCount;
@ -422,7 +427,9 @@ extern const UINT16 g_rcIndex[15];
exclusive audit session, the location is set to TPM_RH_UNASSIGNED. */
extern TPM_HANDLE g_exclusiveAuditSession;
/* This is the value in which we keep the current command time. This is initialized at the start of
each command. The time is in mS. */
each command. The time is the accumulated time since the last time that the TPM's timer was
last powered up. Clock is the accumulated time since the last time that the TPM was
cleared. g_time is in mS. */
extern UINT64 g_time;
/* This value contains the current clock Epoch. It changes when there is a clock discontinuity. It
may be necessary to place this in NV should the timer be able to run across a power down of the
@ -433,42 +440,42 @@ extern CLOCK_NONCE g_timeEpoch;
#else
#define g_timeEpoch gp.timeEpoch
#endif
/* 5.12.10.7 g_phEnable */
/* 5.10.10.7 g_phEnable */
/* This is the platform hierarchy control and determines if the platform hierarchy is
available. This value is SET on each TPM2_Startup(). The default value is SET. */
extern BOOL g_phEnable;
/* 5.12.10.8 g_pcrReConfig */
/* 5.10.10.8 g_pcrReConfig */
/* This value is SET if a TPM2_PCR_Allocate() command successfully executed since the last
TPM2_Startup(). If so, then the next shutdown is required to be Shutdown(CLEAR). */
extern BOOL g_pcrReConfig;
/* 5.12.10.9 g_DRTMHandle */
/* 5.10.10.9 g_DRTMHandle */
/* This location indicates the sequence object handle that holds the DRTM sequence data. When not
used, it is set to TPM_RH_UNASSIGNED. A sequence DRTM sequence is started on either _TPM_Init()
or _TPM_Hash_Start(). */
extern TPMI_DH_OBJECT g_DRTMHandle;
/* 5.12.10.10 g_DrtmPreStartup */
/* 5.10.10.10 g_DrtmPreStartup */
/* This value indicates that an H-CRTM occurred after _TPM_Init() but before TPM2_Startup(). The
define for PRE_STARTUP_FLAG is used to add the g_DrtmPreStartup value to gp_orderlyState at
shutdown. This hack is to avoid adding another NV variable. */
extern BOOL g_DrtmPreStartup;
/* 5.12.10.11 g_StartupLocality3 */
/* 5.10.10.11 g_StartupLocality3 */
/* This value indicates that a TPM2_Startup() occurred at locality 3. Otherwise, it at locality
0. The define for STARTUP_LOCALITY_3 is to indicate that the startup was not at locality 0. This
hack is to avoid adding another NV variable. */
extern BOOL g_StartupLocality3;
/* 5.12.10.12 TPM_SU_NONE */
/* 5.10.10.12 TPM_SU_NONE */
/* Part 2 defines the two shutdown/startup types that may be used in TPM2_Shutdown() and
TPM2_Starup(). This additional define is used by the TPM to indicate that no shutdown was
received. */
/* NOTE: This is a reserved value. */
#define SU_NONE_VALUE (0xFFFF)
#define TPM_SU_NONE (TPM_SU)(SU_NONE_VALUE)
/* 5.12.10.13 TPM_SU_DA_USED */
/* 5.10.10.13 TPM_SU_DA_USED */
/* As with TPM_SU_NONE, this value is added to allow indication that the shutdown was not orderly
and that a DA=protected object was reference during the previous cycle. */
#define SU_DA_USED_VALUE (SU_NONE_VALUE - 1)
#define TPM_SU_DA_USED (TPM_SU)(SU_DA_USED_VALUE)
/* 5.12.10.14 Startup Flags */
/* 5.10.10.14 Startup Flags */
/* These flags are included in gp.orderlyState. These are hacks and are being used to avoid having
to change the layout of gp. The PRE_STARTUP_FLAG indicates that a
_TPM_Hash_Start()/_Data()/_End() sequence was received after _TPM_Init() but before
@ -477,13 +484,13 @@ extern BOOL g_StartupLocality3;
#define PRE_STARTUP_FLAG 0x8000
#define STARTUP_LOCALITY_3 0x4000
#ifdef USE_DA_USED
/* 5.12.10.15 g_daUsed */
/* 5.10.10.15 g_daUsed */
/* This location indicates if a DA-protected value is accessed during a boot cycle. If none has,
then there is no need to increment failedTries on the next non-orderly startup. This bit is
merged with gp.orderlyState when that gp.orderly is set to SU_NONE_VALUE */
extern BOOL g_daUsed;
#endif
/* 5.12.10.16 g_updateNV */
/* 5.10.10.16 g_updateNV */
/* This flag indicates if NV should be updated at the end of a command. This flag is set to UT_NONE
at the beginning of each command in ExecuteCommand(). This flag is checked in ExecuteCommand()
after the detailed actions of a command complete. If the command execution was successful and
@ -494,7 +501,7 @@ typedef BYTE UPDATE_TYPE;
#define UT_NV (UPDATE_TYPE)1
#define UT_ORDERLY (UPDATE_TYPE)(UT_NV + 2)
extern UPDATE_TYPE g_updateNV;
/* 5.12.10.17 g_powerWasLost */
/* 5.10.10.17 g_powerWasLost */
/* This flag is used to indicate if the power was lost. It is SET in _TPM__Init(). This flag is
cleared by TPM2_Startup() after all power-lost activities are completed. */
/* NOTE: When power is applied, this value can come up as anything. However, _plat__WasPowerLost()
@ -502,19 +509,19 @@ extern UPDATE_TYPE g_updateNV;
correct answer. When power was not lost, but the power-lost processing has not been completed
before the next _TPM_Init(), then the TPM still does the correct thing. */
extern BOOL g_powerWasLost;
/* 5.12.10.18 g_clearOrderly */
/* 5.10.10.18 g_clearOrderly */
/* This flag indicates if the execution of a command should cause the orderly state to be cleared.
This flag is set to FALSE at the beginning of each command in ExecuteCommand() and is checked in
ExecuteCommand() after the detailed actions of a command complete but before the check of
g_updateNV. If this flag is TRUE, and the orderly state is not SU_NONE_VALUE, then the orderly
state in NV memory will be changed to SU_NONE_VALUE or SU_DA_USED_VALUE. */
extern BOOL g_clearOrderly;
/* 5.12.10.19 g_prevOrderlyState */
/* 5.10.10.19 g_prevOrderlyState */
/* This location indicates how the TPM was shut down before the most recent TPM2_Startup(). This
value, along with the startup type, determines if the TPM should do a TPM Reset, TPM Restart, or
TPM Resume. */
extern TPM_SU g_prevOrderlyState;
/* 5.12.10.20 g_nvOk */
/* 5.10.10.20 g_nvOk */
/* This value indicates if the NV integrity check was successful or not. If not and the failure was
severe, then the TPM would have been put into failure mode after it had been re-manufactured. If
the NV failure was in the area where the state-save data is kept, then this variable will have a
@ -523,7 +530,7 @@ extern BOOL g_nvOk;
/* NV availability is sampled as the start of each command and stored here so that its value remains
consistent during the command execution */
extern TPM_RC g_NvStatus;
/* 5.12.10.21 g_platformUnique */
/* 5.10.10.21 g_platformUnique */
/* This location contains the unique value(s) used to identify the TPM. It is loaded on every
_TPM2_Startup() The first value is used to seed the RNG. The second value is used as a vendor
authValue. The value used by the RNG would be the value derived from the chip unique value (such
@ -563,9 +570,9 @@ typedef struct
TPM2B_SEED PPSeed;
// Note there is a nullSeed in the state_reset memory.
// Hierarchy proofs
TPM2B_AUTH phProof;
TPM2B_AUTH shProof;
TPM2B_AUTH ehProof;
TPM2B_PROOF phProof;
TPM2B_PROOF shProof;
TPM2B_PROOF ehProof;
// Note there is a nullProof in the state_reset memory.
//*********************************************************************************
// Reset Events
@ -665,7 +672,7 @@ typedef struct
#endif
} PERSISTENT_DATA;
extern PERSISTENT_DATA gp;
/* 5.12.11.3
/* 5.10.11.3
ORDERLY_DATA */
/* The data in this structure is saved to NV on each TPM2_Shutdown(). */
typedef struct orderly_data
@ -689,8 +696,6 @@ typedef struct orderly_data
// of entropy. By keeping the old state and adding entropy, the entropy will
// accumulate.
DRBG_STATE drbgState;
// These values allow the accumulation of self-healing time across orderly shutdown
// of the TPM.
#ifdef ACCUMULATE_SELF_HEAL_TIMER
@ -705,8 +710,8 @@ typedef struct orderly_data
#endif // ACCUMULATE_SELF_HEAL_TIMER
# define drbgDefault go.drbgState
extern ORDERLY_DATA go;
/* 5.12.11.4 STATE_CLEAR_DATA */
/* 5.10.11.4 STATE_CLEAR_DATA */
/* This structure contains the data that is saved on Shutdown(STATE). and restored on
Startup(STATE). The values are set to their default settings on any Startup(Clear). In other
words the data is only persistent across TPM Resume. */
@ -736,7 +741,7 @@ typedef struct state_clear_data
PCR_AUTHVALUE pcrAuthValues;
} STATE_CLEAR_DATA;
extern STATE_CLEAR_DATA gc;
/* 5.12.11.5
/* 5.10.11.5
State
Reset
Data */
@ -748,7 +753,7 @@ typedef struct state_reset_data
//*****************************************************************************
// Hierarchy Control
//*****************************************************************************
TPM2B_AUTH nullProof; // The proof value associated with
TPM2B_PROOF nullProof; // The proof value associated with
// the TPM_RH_NULL hierarchy. The
// default reset value is from the RNG.
TPM2B_SEED nullSeed; // The seed value for the TPM_RN_NULL
@ -824,7 +829,7 @@ typedef struct state_reset_data
#endif //TPM_ALG_ECC
} STATE_RESET_DATA;
extern STATE_RESET_DATA gr;
/* 5.12.12
/* 5.10.12
NV
Layout */
/* The NV data organization is */
@ -840,7 +845,7 @@ extern STATE_RESET_DATA gr;
#define NV_INDEX_RAM_DATA (NV_ORDERLY_DATA + sizeof(ORDERLY_DATA))
#define NV_USER_DYNAMIC (NV_INDEX_RAM_DATA + sizeof(s_indexOrderlyRam))
#define NV_USER_DYNAMIC_END NV_MEMORY_SIZE
/* 5.12.13 Global Macro Definitions */
/* 5.10.13 Global Macro Definitions */
/* The NV_READ_PERSISTENT and NV_WRITE_PERSISTENT macros are used to access members of the
PERSISTENT_DATA structure in NV. */
#define NV_READ_PERSISTENT(to, from) \
@ -930,7 +935,7 @@ extern BOOL g_manufactured;
This flag is maintained in power simulation module because this is the only place that may
reliably set this flag to FALSE. */
extern BOOL g_initialized;
/* 5.12.14 Private data */
/* 5.10.14 Private data */
#if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C
/* From SessionProcess.c */
/* The following arrays are used to save command sessions information so that the command

View File

@ -3,7 +3,7 @@
/* This file is a collection of miscellaneous macros. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: GpMacros.h 960 2017-03-10 19:08:17Z kgoldman $ */
/* $Id: GpMacros.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -62,15 +62,14 @@
#ifndef GPMACROS_H
#define GPMACROS_H
/* 5.11 GpMacros.h */
/* 5.11.1 Introduction */
/* This file is a collection of miscellaneous macros. */
#ifndef NULL
#define NULL 0
#endif
#include "swap.h"
#include "VendorString.h"
/* 5.13.2 For Self-test */
/* 5.11.2 For Self-test */
/* These macros are used in CryptUtil() to invoke the incremental self test. */
#ifdef SELF_TEST
# define TEST(alg) if(TEST_BIT(alg, g_toTest)) CryptTestAlgorithm(alg, NULL)
@ -84,22 +83,14 @@
# define TEST(alg)
# define TEST_HASH(alg)
#endif // SELF_TEST
/* 5.13.3 For Failures */
#if 0
/* 5.11.3 For Failures */
#if defined _POSIX_
# define FUNCTION_NAME 0
#else
# define FUNCTION_NAME __FUNCTION__
#endif
#endif
#if defined ( WIN32 )
#define __func__ __FUNCTION__
#endif
# define FUNCTION_NAME __func__
#ifdef NO_FAIL_TRACE
# define FAIL(errorCode) (TpmFail(errorCode))
# define FAIL(errorCode) (TpmFail(errorCode))
#else
# define FAIL(errorCode) (TpmFail(FUNCTION_NAME, __LINE__, errorCode))
#endif
@ -119,26 +110,26 @@
#define REQUIRE(condition, errorCode, returnCode) \
{ \
if(!!(condition)) \
{ \
FAIL(FATAL_ERROR_errorCode); \
FAIL_RETURN(returnCode); \
} \
{ \
FAIL(FATAL_ERROR_errorCode); \
FAIL_RETURN(returnCode); \
} \
}
#define PARAMETER_CHECK(condition, returnCode) \
REQUIRE((condition), PARAMETER, returnCode)
#if defined(EMPTY_ASSERT)
#if defined EMPTY_ASSERT
# define pAssert(a) ((void)0)
#else
# define pAssert(a) {if(!(a)) FAIL(FATAL_ERROR_PARAMETER);}
#endif
/* 5.13.4 Derived from Vendor-specific values */
/* 5.11.4 Derived from Vendor-specific values */
/* Values derived from vendor specific settings in Implementation.h */
#define PCR_SELECT_MIN ((PLATFORM_PCR+7)/8)
#define PCR_SELECT_MAX ((IMPLEMENTATION_PCR+7)/8)
#define MAX_ORDERLY_COUNT ((1 << ORDERLY_BITS) - 1)
#define PRIVATE_VENDOR_SPECIFIC_BYTES \
((MAX_RSA_KEY_BYTES/2) * (3 + CRT_FORMAT_RSA * 2))
/* 5.13.5 Compile-time Checks */
/* 5.11.5 Compile-time Checks */
/* In some cases, the relationship between two values may be dependent on things that change based
on various selections like the chosen cryptographic libraries. It is possible that these
selections will result in incompatible settings. These are often detectable by the compiler but
@ -192,6 +183,10 @@
# define DEBUG YES
#endif
#define STD_RESPONSE_HEADER (sizeof(TPM_ST) + sizeof(UINT32) + sizeof(TPM_RC))
#define JOIN(x,y) x##y
#define CONCAT(x,y) JOIN(x, y)
/* If CONTEXT_INTEGRITY_HASH_ALG is defined, then the vendor is using the old style
table. Otherwise, pick the strongest implemented hash algorithm as the context hash. */
#ifndef CONTEXT_HASH_ALGORITHM
# if defined ALG_SHA512 && ALG_SHA512 == YES
# define CONTEXT_HASH_ALGORITHM SHA512
@ -202,32 +197,97 @@
# elif defined ALG_SM3_256 && ALG_SM3_256 == YES
# define CONTEXT_HASH_ALGORITHM SM3_256
# elif defined ALG_SHA1 && ALG_SHA1 == YES
# define CONTEXT_HASH_ALGORITHM SHA1
# define CONTEXT_HASH_ALGORITHM SHA1
# endif
# define CONTEXT_INTEGRITY_HASH_ALG CONCAT(TPM_ALG_, CONTEXT_HASH_ALGORITHM)
#endif
#ifndef CONTEXT_INTEGRITY_HASH_SIZE
#define CONTEXT_INTEGRITY_HASH_SIZE CONCAT(CONTEXT_HASH_ALGORITHM, _DIGEST_SIZE)
#endif
#ifdef TPM_ALG_RSA
#define RSA_SECURITY_STRENGTH (MAX_RSA_KEY_BITS >= 15360 ? 256 : \
(MAX_RSA_KEY_BITS >= 7680 ? 192 : \
(MAX_RSA_KEY_BITS >= 3072 ? 128 : \
(MAX_RSA_KEY_BITS >= 2048 ? 112 : \
(MAX_RSA_KEY_BITS >= 1024 ? 80 : 0)))))
#else
#define RSA_SECURITY_STRENGTH 0
#endif
#ifdef TPM_ALG_ECC
#define ECC_SECURITY_STRENGTH (MAX_ECC_KEY_BITS >= 521 ? 256 : \
(MAX_ECC_KEY_BITS >= 384 ? 192 : \
(MAX_ECC_KEY_BITS >= 256 ? 128 : 0)))
#else
#define ECC_SECURITY_STRENGTH 0
#endif // TPM_AGL_ECC
#define MAX_ASYM_SECURITY_STRENGTH \
MAX(RSA_SECURITY_STRENGTH, ECC_SECURITY_STRENGTH)
#define MAX_HASH_SECURITY_STRENGTH ((CONTEXT_INTEGRITY_HASH_SIZE * 8) / 2)
/* Unless some algorithm is broken... */
#define MAX_SYM_SECURITY_STRENGTH MAX_SYM_KEY_BITS
#define MAX_SECURITY_STRENGTH_BITS \
MAX(MAX_ASYM_SECURITY_STRENGTH, \
MAX(MAX_SYM_SECURITY_STRENGTH, \
MAX_HASH_SECURITY_STRENGTH))
/* This is the size that was used before the 1.38 errata requiring that P1.14.4 be followed */
#define PROOF_SIZE CONTEXT_INTEGRITY_HASH_SIZE
/* As required by P1.14.4 */
#define COMPLIANT_PROOF_SIZE \
(MAX(CONTEXT_INTEGRITY_HASH_SIZE, (2 * MAX_SYM_KEY_BYTES)))
/* As required by P1.14.3.1 */
#define COMPLIANT_PRIMARY_SEED_SIZE \
BITS_TO_BYTES(MAX_SECURITY_STRENGTH_BITS * 2)
/* This is the pre-errata version */
#ifndef PRIMARY_SEED_SIZE
# define PRIMARY_SEED_SIZE PROOF_SIZE
#endif
#ifdef USE_SPEC_COMPLIANT_PROOFS
# undef PROOF_SIZE
# define PROOF_SIZE COMPLIANT_PROOF_SIZE
# undef PRIMARY_SEED_SIZE
# define PRIMARY_SEED_SIZE COMPLIANT_PRIMARY_SEED_SIZE
#endif // USE_SPEC_COMPLIANT_PROOFS || !defined PRIMARY_SEED_SIZE
#ifndef SKIP_PROOF_ERRORS
# if PROOF_SIZE < COMPLIANT_PROOF_SIZE
# error "PROOF_SIZE is not compliant with TPM specification"
# endif
# if PRIMARY_SEED_SIZE < COMPLIANT_PRIMARY_SEED_SIZE
# error "Implementation.h specifies a non-compliant PRIMARY_SEED_SIZE"
# endif
#endif
#define JOIN(x,y) x##y
#define CONCAT(x,y) JOIN(x, y)
/* If CONTEXT_INTEGRITY_HASH_ALG is defined, then the vendor is using the old style table */
#ifndef CONTEXT_INTEGRITY_HASH_ALG
#define CONTEXT_INTEGRITY_HASH_ALG CONCAT(TPM_ALG_, CONTEXT_HASH_ALGORITHM)
#define CONTEXT_INTEGRITY_HASH_SIZE CONCAT(CONTEXT_HASH_ALGORITHM, _DIGEST_SIZE)
#endif
#define PROOF_SIZE CONTEXT_INTEGRITY_HASH_SIZE
/* If CONTEXT_ENCRYP_ALG is defined, then the vendor is using the old style table */
#ifndef CONTEXT_ENCRYPT_ALG
#define CONTEXT_ENCRYPT_ALG CONCAT(TPM_ALG_, CONTEXT_ENCRYPT_ALGORITHM)
#define CONTEXT_ENCRYPT_KEY_BITS \
CONCAT(CONCAT(MAX_, CONTEXT_ENCRYPT_ALGORITHM), _KEY_BITS)
#define CONTEXT_ENCRYPT_KEY_BYTES ((CONTEXT_ENCRYPT_KEY_BITS+7)/8)
#endif
#if ALG_ECC
# define LABEL_MAX_BUFFER MAX_ECC_KEY_BYTES
#else
# define LABEL_MAX_BUFFER MAX_DIGEST_SIZE
/* This is updated to follow the requirement of P2 that the label not be larger than 32 bytes. */
#ifndef LABEL_MAX_BUFFER
#define LABEL_MAX_BUFFER MIN(32, MIN(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE))
#endif
/* This bit is used to indicate that an authorization ticket expires on TPM Reset and TPM Restart.It
is added to the timeout value returned by TPM2_PoliySigned() and TPM2_PolicySecret() and used by
TPM2_PolicyTicket(). The timeout value is relative to Time (g_time). Time is reset whenever the
TPM loses power and cannot be moved forward by the user (as can Clock). g_time is a 64-bit value
expressing time in ms. Sealing the MSb() for a flag means that the TPM needs to be reset at least
once every 292,471,208 years rather than once every 584,942,417 years. */
#define EXPIRATION_BIT ((UINT64)1 << 63)
/* Check for consistency of the bit ordering an bit fields */
#if BIG_ENDIAN_TPM && MOST_SIGNIFICANT_BIT_0 && !defined NO_BIT_FIELD_STRUCTURES
# error "Settings not consistent"
#endif
/* These macros are used to handle the variation in handling of bit fields. If */
#ifndef NO_BIT_FIELD_STRUCTURES // The default, old version, with bit fields
# define IS_ATTRIBUTE(a, type, b) ((a.b != 0))
# define SET_ATTRIBUTE(a, type, b) (a.b = SET)
# define CLEAR_ATTRIBUTE(a, type, b) (a.b = CLEAR)
# define GET_ATTRIBUTE(a, type, b) (a.b)
#else
# define IS_ATTRIBUTE(a, type, b) ((a & type##_##b) != 0)
# define SET_ATTRIBUTE(a, type, b) (a |= type##_##b)
# define CLEAR_ATTRIBUTE(a, type, b) (a &= ~type##_##b)
# define GET_ATTRIBUTE(a, type, b) \
(type)((a & type##_##b) >> type##_##b##_SHIFT)
#endif
#endif // GP_MACROS_H

View File

@ -3,7 +3,7 @@
/* fUnctions that return the type of a handle. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Handle.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Handle.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -79,7 +79,6 @@ HandleGetType(
/* This function returns the permanent handle that is equal to the input value or is the next higher
value. If there is no handle with the input value and there is no next higher value, it returns
0: */
/* Return Values Meaning */
TPM_HANDLE
NextPermanentHandle(
TPM_HANDLE inHandle // IN: the handle to check

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: HashCommands.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: HashCommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -79,10 +79,12 @@ TPM2_HMAC_Start(
if(publicArea->type != TPM_ALG_KEYEDHASH)
return TPM_RCS_TYPE + RC_HMAC_Start_handle;
// and that it is unrestricted
if(publicArea->objectAttributes.restricted == SET)
if (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
//if(publicArea->objectAttributes.restricted == SET) kgold
return TPM_RCS_ATTRIBUTES + RC_HMAC_Start_handle;
// and that it is a signing key
if(publicArea->objectAttributes.sign != SET)
if (!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
// if(publicArea->objectAttributes.sign != SET) kgold
return TPM_RCS_KEY + RC_HMAC_Start_handle;
// See if the key has a default
if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL)
@ -110,6 +112,53 @@ TPM2_HMAC_Start(
}
#endif // CC_HMAC_Start
#include "Tpm.h"
#include "MAC_Start_fp.h"
#ifdef TPM_CC_MAC_Start // Conditional expansion of this file
/* Error Returns Meaning */
/* TPM_RC_ATTRIBUTES key referenced by handle is not a signing key or is restricted */
/* TPM_RC_OBJECT_MEMORY no space to create an internal object */
/* TPM_RC_KEY key referenced by handle is not an HMAC key */
/* TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of the object
referenced by handle */
TPM_RC
TPM2_MAC_Start(
MAC_Start_In *in, // IN: input parameter list
MAC_Start_Out *out // OUT: output parameter list
)
{
OBJECT *keyObject;
TPMT_PUBLIC *publicArea;
TPM_RC result;
// Input Validation
// Get HMAC key object and public area pointers
keyObject = HandleToObject(in->handle);
publicArea = &keyObject->publicArea;
// Make sure that the key can do what is required
result = CryptSelectMac(publicArea, &in->inScheme);
// If the key is not able to do a MAC, indicate that the handle selects an
// object that can't do a MAC
if(result == TPM_RCS_TYPE)
return TPM_RCS_TYPE + RC_MAC_Start_handle;
// If there is another error type, indicate that the scheme and key are not
// compatible
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result, RC_MAC_Start_inScheme);
// Make sure that the key is not restricted
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
return TPM_RCS_ATTRIBUTES + RC_MAC_Start_handle;
// and that it is a signing key
if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
return TPM_RCS_KEY + RC_MAC_Start_handle;
// Internal Data Update
// Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be
// returned at this point
return ObjectCreateHMACSequence(in->inScheme,
keyObject,
&in->auth,
&out->sequenceHandle);
}
#endif // CC_MAC_Start
#include "Tpm.h"
#include "HashSequenceStart_fp.h"
#ifdef TPM_CC_HashSequenceStart // Conditional expansion of this file
TPM_RC
@ -177,7 +226,7 @@ TPM2_SequenceUpdate(
}
else if(object->attributes.hmacSeq == SET)
{
// Update sequence object hash/HMAC stack
// Update sequence object HMAC stack
CryptDigestUpdate2B(&hashObject->state.hmacState.hashState,
&in->buffer.b);
}
@ -188,72 +237,77 @@ TPM2_SequenceUpdate(
#include "Tpm.h"
#include "SequenceComplete_fp.h"
#ifdef TPM_CC_SequenceComplete // Conditional expansion of this file
/* Error Returns Meaning */
/* TPM_RC_MODE sequenceHandle does not reference a hash or HMAC sequence object */
TPM_RC
TPM2_SequenceComplete(
SequenceComplete_In *in, // IN: input parameter list
SequenceComplete_Out *out // OUT: output parameter list
)
{
OBJECT *object;
HASH_OBJECT *hashObject;
// Input validation
// Get hash object pointer
object = HandleToObject(in->sequenceHandle);
hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle);
// input handle must be a hash or HMAC sequence object.
if(object->attributes.hashSeq == CLEAR
&& object->attributes.hmacSeq == CLEAR)
if(hashObject->attributes.hashSeq == CLEAR
&& hashObject->attributes.hmacSeq == CLEAR)
return TPM_RCS_MODE + RC_SequenceComplete_sequenceHandle;
// Command Output
if(object->attributes.hashSeq == SET) // sequence object for hash
if(hashObject->attributes.hashSeq == SET) // sequence object for hash
{
// Update last piece of data
HASH_OBJECT *hashObject = (HASH_OBJECT *)object;
// Get the hash algorithm before the algorithm is lost in CryptHashEnd
TPM_ALG_ID hashAlg = hashObject->state.hashState[0].hashAlg;
// Update last piece of the data
CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b);
// Complete hash
out->result.t.size
= CryptHashGetDigestSize(
CryptHashGetContextAlg(&hashObject->state.hashState[0]));
CryptHashEnd2B(&hashObject->state.hashState[0], &out->result.b);
out->result.t.size = CryptHashEnd(&hashObject->state.hashState[0],
sizeof(out->result.t.buffer),
out->result.t.buffer);
// Check if the first block of the sequence has been received
if(hashObject->attributes.firstBlock == CLEAR)
{
// If not, then this is the first block so see if it is 'safe'
// to sign.
if(TicketIsSafe(&in->buffer.b))
hashObject->attributes.ticketSafe = SET;
}
{
// If not, then this is the first block so see if it is 'safe'
// to sign.
if(TicketIsSafe(&in->buffer.b))
hashObject->attributes.ticketSafe = SET;
}
// Output ticket
out->validation.tag = TPM_ST_HASHCHECK;
out->validation.hierarchy = in->hierarchy;
if(in->hierarchy == TPM_RH_NULL)
{
// Ticket is not required
out->validation.digest.t.size = 0;
}
else if(object->attributes.ticketSafe == CLEAR)
{
// Ticket is not safe to generate
out->validation.hierarchy = TPM_RH_NULL;
out->validation.digest.t.size = 0;
}
{
// Ticket is not required
out->validation.digest.t.size = 0;
}
else if(hashObject->attributes.ticketSafe == CLEAR)
{
// Ticket is not safe to generate
out->validation.hierarchy = TPM_RH_NULL;
out->validation.digest.t.size = 0;
}
else
{
// Compute ticket
TicketComputeHashCheck(out->validation.hierarchy, hashAlg,
&out->result, &out->validation);
}
{
// Compute ticket
TicketComputeHashCheck(out->validation.hierarchy, hashAlg,
&out->result, &out->validation);
}
}
else
{
HASH_OBJECT *hashObject = (HASH_OBJECT *)object;
// Update last piece of data
CryptDigestUpdate2B(&hashObject->state.hmacState.hashState, &in->buffer.b);
// Complete hash/HMAC
out->result.t.size =
CryptHashGetDigestSize(
CryptHashGetContextAlg(&hashObject->state.hmacState.hashState));
CryptHmacEnd2B(&(hashObject->state.hmacState), &out->result.b);
#ifndef SMAC_IMPLEMENTED
// Complete HMAC
out->result.t.size = CryptHmacEnd(&(hashObject->state.hmacState),
sizeof(out->result.t.buffer),
out->result.t.buffer);
#else
// Complete the MAC
out->result.t.size = CryptMacEnd(&hashObject->state.hmacState,
sizeof(out->result.t.buffer),
out->result.t.buffer);
#endif
// No ticket is generated for HMAC sequence
out->validation.tag = TPM_ST_HASHCHECK;
out->validation.hierarchy = TPM_RH_NULL;
@ -261,7 +315,7 @@ TPM2_SequenceComplete(
}
// Internal Data Update
// mark sequence object as evict so it will be flushed on the way out
object->attributes.evict = SET;
hashObject->attributes.evict = SET;
return TPM_RC_SUCCESS;
}
#endif // CC_SequenceComplete

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Hierarchy.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: Hierarchy.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
/* 8.3 Hierarchy.c */
@ -76,15 +76,15 @@ HierarchyPreInstall_Init(
// Allow lockout clear command
gp.disableClear = FALSE;
// Initialize Primary Seeds
gp.EPSeed.t.size = PRIMARY_SEED_SIZE;
CryptRandomGenerate(PRIMARY_SEED_SIZE, gp.EPSeed.t.buffer);
gp.SPSeed.t.size = PRIMARY_SEED_SIZE;
CryptRandomGenerate(PRIMARY_SEED_SIZE, gp.SPSeed.t.buffer);
gp.PPSeed.t.size = PRIMARY_SEED_SIZE;
gp.EPSeed.t.size = sizeof(gp.EPSeed.t.buffer);
gp.SPSeed.t.size = sizeof(gp.SPSeed.t.buffer);
gp.PPSeed.t.size = sizeof(gp.PPSeed.t.buffer);
CryptRandomGenerate(gp.EPSeed.t.size, gp.EPSeed.t.buffer);
CryptRandomGenerate(gp.SPSeed.t.size, gp.SPSeed.t.buffer);
#ifdef USE_PLATFORM_EPS
_plat__GetEPS(PRIMARY_SEED_SIZE, gp.EPSeed.t.buffer);
_plat__GetEPS(gp.PPSeed.t.size, gp.EPSeed.t.buffer);
#else
CryptRandomGenerate(PRIMARY_SEED_SIZE, gp.PPSeed.t.buffer);
CryptRandomGenerate(gp.PPSeed.t.size, gp.PPSeed.t.buffer);
#endif
// Initialize owner, endorsement and lockout auth
gp.ownerAuth.t.size = 0;
@ -98,9 +98,9 @@ HierarchyPreInstall_Init(
gp.lockoutAlg = TPM_ALG_NULL;
gp.lockoutPolicy.t.size = 0;
// Initialize ehProof, shProof and phProof
gp.phProof.t.size = PROOF_SIZE;
gp.shProof.t.size = PROOF_SIZE;
gp.ehProof.t.size = PROOF_SIZE;
gp.phProof.t.size = sizeof(gp.phProof.t.buffer);
gp.shProof.t.size = sizeof(gp.shProof.t.buffer);
gp.ehProof.t.size = sizeof(gp.ehProof.t.buffer);
CryptRandomGenerate(gp.phProof.t.size, gp.phProof.t.buffer);
CryptRandomGenerate(gp.shProof.t.size, gp.shProof.t.buffer);
CryptRandomGenerate(gp.ehProof.t.size, gp.ehProof.t.buffer);
@ -144,46 +144,45 @@ HierarchyStartup(
// nullProof and nullSeed are updated at every TPM_RESET
if((type != SU_RESTART) && (type != SU_RESUME))
{
gr.nullProof.t.size = PROOF_SIZE;
CryptRandomGenerate(gr.nullProof.t.size,
gr.nullProof.t.buffer);
gr.nullSeed.t.size = PRIMARY_SEED_SIZE;
CryptRandomGenerate(PRIMARY_SEED_SIZE, gr.nullSeed.t.buffer);
gr.nullProof.t.size = sizeof(gr.nullProof.t.buffer);
CryptRandomGenerate(gr.nullProof.t.size, gr.nullProof.t.buffer);
gr.nullSeed.t.size = sizeof(gr.nullProof.t.buffer);
CryptRandomGenerate(gr.nullProof.t.size, gr.nullSeed.t.buffer);
}
return;
}
/* 8.3.3.3 HierarchyGetProof() */
/* This function finds the proof value associated with a hierarchy.It returns a pointer to the proof
value. */
TPM2B_AUTH *
TPM2B_PROOF *
HierarchyGetProof(
TPMI_RH_HIERARCHY hierarchy // IN: hierarchy constant
)
{
TPM2B_AUTH *auth = NULL;
TPM2B_PROOF *proof = NULL;
switch(hierarchy)
{
case TPM_RH_PLATFORM:
// phProof for TPM_RH_PLATFORM
auth = &gp.phProof;
proof = &gp.phProof;
break;
case TPM_RH_ENDORSEMENT:
// ehProof for TPM_RH_ENDORSEMENT
auth = &gp.ehProof;
proof = &gp.ehProof;
break;
case TPM_RH_OWNER:
// shProof for TPM_RH_OWNER
auth = &gp.shProof;
proof = &gp.shProof;
break;
case TPM_RH_NULL:
// nullProof for TPM_RH_NULL
auth = &gr.nullProof;
proof = &gr.nullProof;
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;
}
return auth;
return proof;
}
/* 8.3.3.4 HierarchyGetPrimarySeed() */
/* This function returns the primary seed of a hierarchy. */

View File

@ -3,7 +3,7 @@
/* Hierarchy Commands */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: HierarchyCommands.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: HierarchyCommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -68,7 +68,6 @@ TPM2_CreatePrimary(
CreatePrimary_Out *out // OUT: output parameter list
)
{
// Local variables
TPM_RC result = TPM_RC_SUCCESS;
TPMT_PUBLIC *publicArea;
DRBG_STATE rand;
@ -289,13 +288,12 @@ TPM2_ChangePPS(
RETURN_IF_NV_IS_NOT_AVAILABLE;
// Input parameter is not reference in command action
NOT_REFERENCED(in);
// in = NULL; kgold
// Internal Data Update
// Reset platform hierarchy seed from RNG
CryptRandomGenerate(PRIMARY_SEED_SIZE, gp.PPSeed.t.buffer);
CryptRandomGenerate(sizeof(gp.PPSeed.t.buffer), gp.PPSeed.t.buffer);
// Create a new phProof value from RNG to prevent the saved platform
// hierarchy contexts being loaded
CryptRandomGenerate(PROOF_SIZE, gp.phProof.t.buffer);
CryptRandomGenerate(sizeof(gp.phProof.t.buffer), gp.phProof.t.buffer);
// Set platform authPolicy to null
gc.platformAlg = TPM_ALG_NULL;
gc.platformPolicy.t.size = 0;
@ -336,9 +334,9 @@ TPM2_ChangeEPS(
NOT_REFERENCED(in);
// Internal Data Update
// Reset endorsement hierarchy seed from RNG
CryptRandomGenerate(PRIMARY_SEED_SIZE, gp.EPSeed.t.buffer);
CryptRandomGenerate(sizeof(gp.EPSeed.t.buffer), gp.EPSeed.t.buffer);
// Create new ehProof value from RNG
CryptRandomGenerate(PROOF_SIZE, gp.ehProof.t.buffer);
CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer);
// Enable endorsement hierarchy
gc.ehEnable = TRUE;
// set authValue buffer to zeros
@ -383,10 +381,10 @@ TPM2_Clear(
return TPM_RC_DISABLED;
// Internal Data Update
// Reset storage hierarchy seed from RNG
CryptRandomGenerate(PRIMARY_SEED_SIZE, gp.SPSeed.t.buffer);
CryptRandomGenerate(sizeof(gp.SPSeed.t.buffer), gp.SPSeed.t.buffer);
// Create new shProof and ehProof value from RNG
CryptRandomGenerate(PROOF_SIZE, gp.shProof.t.buffer);
CryptRandomGenerate(PROOF_SIZE, gp.ehProof.t.buffer);
CryptRandomGenerate(sizeof(gp.shProof.t.buffer), gp.shProof.t.buffer);
CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer);
// Enable storage and endorsement hierarchy
gc.shEnable = gc.ehEnable = TRUE;
// set the authValue buffers to zero

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Hierarchy_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: Hierarchy_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -70,7 +70,7 @@ void
HierarchyStartup(
STARTUP_TYPE type // IN: start up type
);
TPM2B_AUTH *
TPM2B_PROOF *
HierarchyGetProof(
TPMI_RH_HIERARCHY hierarchy // IN: hierarchy constant
);

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Implementation.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Implementation.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -81,14 +81,18 @@
#define SET 1
#define CLEAR 0
/* From Vendor-Specific: Table 1 - Defines for Processor Values */
#ifndef BIG_ENDIAN_TPM
#define BIG_ENDIAN_TPM NO
#define LITTLE_ENDIAN_TPM YES
#define AUTO_ALIGN NO
#endif
#define LITTLE_ENDIAN_TPM !BIG_ENDIAN_TPM
#define MOST_SIGNIFICANT_BIT_0 NO
#define LEAST_SIGNIFICANT_BIT_0 !MOST_SIGNIFICANT_BIT_0
#define AUTO_ALIGN NO
/* From Vendor-Specific: Table 2 - Defines for Implemented Algorithms */
#define ALG_RSA ALG_YES
#define ALG_SHA1 ALG_YES
#define ALG_HMAC ALG_YES
#define ALG_TDES ALG_YES
#define ALG_TDES ALG_NO
#define ALG_AES ALG_YES
#define ALG_MGF1 ALG_YES
#define ALG_XOR ALG_YES
@ -113,6 +117,7 @@
#define ALG_KDF1_SP800_56A (ALG_YES*ALG_ECC)
#define ALG_KDF2 ALG_NO
#define ALG_KDF1_SP800_108 ALG_YES
#define ALG_CMAC ALG_NO
#define ALG_CTR ALG_YES
#define ALG_OFB ALG_YES
#define ALG_CBC ALG_YES
@ -213,8 +218,10 @@
#define CC_HashSequenceStart CC_YES
#define CC_HierarchyChangeAuth CC_YES
#define CC_HierarchyControl CC_YES
#define CC_HMAC CC_YES
#define CC_HMAC_Start CC_YES
#define CC_HMAC (CC_YES^ALG_CMAC)
#define CC_MAC (CC_NO^ALG_CMAC)
#define CC_HMAC_Start (CC_YES^ALG_CMAC)
#define CC_MAC_Start (CC_NO^ALG_CMAC)
#define CC_Import CC_YES
#define CC_IncrementalSelfTest CC_YES
#define CC_Load CC_YES
@ -353,6 +360,7 @@
#define CRT_FORMAT_RSA YES
#define VENDOR_COMMAND_COUNT 0
#define MAX_VENDOR_BUFFER_SIZE 1024
#define TPM_MAX_DERIVATION_BITS 8192
/* From TCG Algorithm Registry: Table 2 - Definition of TPM_ALG_ID Constants */
typedef UINT16 TPM_ALG_ID;
#define ALG_ERROR_VALUE 0x0000
@ -479,6 +487,10 @@ typedef UINT16 TPM_ALG_ID;
#if defined ALG_CAMELLIA && ALG_CAMELLIA == YES
#define TPM_ALG_CAMELLIA (TPM_ALG_ID)(ALG_CAMELLIA_VALUE)
#endif
#define ALG_CMAC_VALUE 0x003F
#if defined ALG_CMAC && ALG_CMAC == YES
#define TPM_ALG_CMAC (TPM_ALG_ID)(ALG_CMAC_VALUE)
#endif
#define ALG_CTR_VALUE 0x0040
#if defined ALG_CTR && ALG_CTR == YES
#define TPM_ALG_CTR (TPM_ALG_ID)(ALG_CTR_VALUE)
@ -913,6 +925,12 @@ typedef UINT32 TPM_CC;
#if CC_HMAC == YES
#define TPM_CC_HMAC (TPM_CC)(0x00000155)
#endif
#ifndef CC_MAC
# define CC_MAC NO
#endif
#if CC_MAC == YES
#define TPM_CC_MAC (TPM_CC)(0x00000155)
#endif
#ifndef CC_Import
# define CC_Import NO
#endif
@ -943,6 +961,12 @@ typedef UINT32 TPM_CC;
#if CC_HMAC_Start == YES
#define TPM_CC_HMAC_Start (TPM_CC)(0x0000015b)
#endif
#ifndef CC_MAC_Start
# define CC_MAC_Start NO
#endif
#if CC_MAC_Start == YES
#define TPM_CC_MAC_Start (TPM_CC)(0x0000015b)
#endif
#ifndef CC_SequenceUpdate
# define CC_SequenceUpdate NO
#endif
@ -1261,6 +1285,12 @@ typedef UINT32 TPM_CC;
#if CC_EncryptDecrypt2 == YES
#define TPM_CC_EncryptDecrypt2 (TPM_CC)(0x00000193)
#endif
#ifndef CC_AC_GetCapability
# define CC_AC_GetCapability NO
#endif
#if CC_AC_GetCapability == YES
#define TPM_CC_AC_GetCapability (TPM_CC)(0x00000194)
#endif
#ifndef CC_AC_Send
# define CC_AC_Send NO
#endif
@ -1273,12 +1303,6 @@ typedef UINT32 TPM_CC;
#if CC_Policy_AC_SendSelect == YES
#define TPM_CC_Policy_AC_SendSelect (TPM_CC)(0x00000196)
#endif
#ifndef CC_SMAC
# define CC_SMAC NO
#endif
#if CC_SMAC == YES
#define TPM_CC_SMAC (TPM_CC)(0x00000197)
#endif
#define CC_VEND (TPM_CC)(0x20000000)
#ifndef CC_Vendor_TCG_Test
# define CC_Vendor_TCG_Test NO
@ -1349,13 +1373,13 @@ typedef UINT32 TPM_CC;
+ (ADD_FILL || CC_Rewrap) /* 0x00000152 */ \
+ (ADD_FILL || CC_Create) /* 0x00000153 */ \
+ (ADD_FILL || CC_ECDH_ZGen) /* 0x00000154 */ \
+ (ADD_FILL || CC_HMAC) /* 0x00000155 */ \
+ (ADD_FILL || CC_HMAC || CC_MAC) /* 0x00000155 */ \
+ (ADD_FILL || CC_Import) /* 0x00000156 */ \
+ (ADD_FILL || CC_Load) /* 0x00000157 */ \
+ (ADD_FILL || CC_Quote) /* 0x00000158 */ \
+ (ADD_FILL || CC_RSA_Decrypt) /* 0x00000159 */ \
+ ADD_FILL /* 0x0000015a */ \
+ (ADD_FILL || CC_HMAC_Start) /* 0x0000015b */ \
+ (ADD_FILL || CC_HMAC_Start || CC_MAC_Start) /* 0x0000015b */ \
+ (ADD_FILL || CC_SequenceUpdate) /* 0x0000015c */ \
+ (ADD_FILL || CC_Sign) /* 0x0000015d */ \
+ (ADD_FILL || CC_Unseal) /* 0x0000015e */ \
@ -1417,7 +1441,6 @@ typedef UINT32 TPM_CC;
+ (ADD_FILL || CC_Policy_AC_SendSelect) /* 0x00000196 */ \
+ ADD_FILL /* 0x00000197 */ \
)
#define VENDOR_COMMAND_ARRAY_SIZE ( 0 \
+ CC_Vendor_TCG_Test \
)
@ -1496,6 +1519,4 @@ typedef TPM2B_MAX_HASH_BLOCK TPM2B_HASH_BLOCK;
#if MAX_SYM_KEY_BITS == 0 || MAX_SYM_BLOCK_SIZE == 0
# error Bad size for MAX_SYM_KEY_BITS or MAX_SYM_BLOCK_SIZE
#endif
/* Define the 2B structure for a seed */
TPM2B_TYPE(SEED, PRIMARY_SEED_SIZE);
#endif // _IMPLEMENTATION_H_

View File

@ -3,7 +3,7 @@
/* Include Headers for Internal Routines */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: InternalRoutines.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: InternalRoutines.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -106,7 +106,7 @@
#include "IoBuffers_fp.h"
#include "Memory_fp.h"
#include "ResponseCodeProcessing_fp.h"
/* Internal crypto functions */
/* Internal cryptographic functions */
#include "BnConvert_fp.h"
#include "BnMath_fp.h"
#include "BnMemory_fp.h"
@ -130,6 +130,12 @@
#include "CryptEccSignature_fp.h"
#include "CryptEccKeyExchange_fp.h"
#endif
#if defined TPM_CC_MAC || defined TPM_CC_MAC_Start
# include "CryptSmac_fp.h"
# ifdef TPM_ALG_CMAC
# include "CryptCmac_fp.h"
# endif
#endif
/* Support library */
#include "SupportLibraryFunctionPrototypes_fp.h"
/* Linkage to platform functions */

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: IoBuffers.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: IoBuffers.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Locality.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Locality.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -76,19 +76,19 @@ LocalityGetAttributes(
switch(locality)
{
case 0:
locality_attributes.TPM_LOC_ZERO = SET;
SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_ZERO);
break;
case 1:
locality_attributes.TPM_LOC_ONE = SET;
SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_ONE);
break;
case 2:
locality_attributes.TPM_LOC_TWO = SET;
SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_TWO);
break;
case 3:
locality_attributes.TPM_LOC_THREE = SET;
SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_THREE);
break;
case 4:
locality_attributes.TPM_LOC_FOUR = SET;
SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_FOUR);
break;
default:
pAssert(locality > 31);

88
src/tpm2/MAC_Start_fp.h Normal file
View File

@ -0,0 +1,88 @@
/********************************************************************************/
/* */
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: MAC_Start_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
/* 1. Copyright Licenses: */
/* */
/* - Trusted Computing Group (TCG) grants to the user of the source code in */
/* this specification (the "Source Code") a worldwide, irrevocable, */
/* nonexclusive, royalty free, copyright license to reproduce, create */
/* derivative works, distribute, display and perform the Source Code and */
/* derivative works thereof, and to grant others the rights granted herein. */
/* */
/* - The TCG grants to the user of the other parts of the specification */
/* (other than the Source Code) the rights to reproduce, distribute, */
/* display, and perform the specification solely for the purpose of */
/* developing products based on such documents. */
/* */
/* 2. Source Code Distribution Conditions: */
/* */
/* - Redistributions of Source Code must retain the above copyright licenses, */
/* this list of conditions and the following disclaimers. */
/* */
/* - Redistributions in binary form must reproduce the above copyright */
/* licenses, this list of conditions and the following disclaimers in the */
/* documentation and/or other materials provided with the distribution. */
/* */
/* 3. Disclaimers: */
/* */
/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */
/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */
/* information on specification licensing rights available through TCG */
/* membership agreements. */
/* */
/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */
/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */
/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */
/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */
/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */
/* */
/* - Without limitation, TCG and its members and licensors disclaim all */
/* liability, including liability for infringement of any proprietary */
/* rights, relating to use of information in this specification and to the */
/* implementation of this specification, and TCG disclaims all liability for */
/* cost of procurement of substitute goods or services, lost profits, loss */
/* of use, loss of data or any incidental, consequential, direct, indirect, */
/* or special damages, whether under contract, tort, warranty or otherwise, */
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2017 */
/* */
/********************************************************************************/
/* rev 146 */
#ifndef MAC_START_FP_H
#define MAC_START_FP_H
typedef struct {
TPMI_DH_OBJECT handle;
TPM2B_AUTH auth;
TPMI_ALG_MAC_SCHEME inScheme;
} MAC_Start_In;
typedef struct {
TPMI_DH_OBJECT sequenceHandle;
} MAC_Start_Out;
#define RC_MAC_Start_handle (TPM_RC_H + TPM_RC_1)
#define RC_MAC_Start_auth (TPM_RC_P + TPM_RC_1)
#define RC_MAC_Start_inScheme (TPM_RC_P + TPM_RC_2)
TPM_RC
TPM2_MAC_Start(
MAC_Start_In *in, // IN: input parameter list
MAC_Start_Out *out // OUT: output parameter list
);
#endif

88
src/tpm2/MAC_fp.h Normal file
View File

@ -0,0 +1,88 @@
/********************************************************************************/
/* */
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: MAC_fp.h 1049 2017-07-20 21:00:18Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
/* 1. Copyright Licenses: */
/* */
/* - Trusted Computing Group (TCG) grants to the user of the source code in */
/* this specification (the "Source Code") a worldwide, irrevocable, */
/* nonexclusive, royalty free, copyright license to reproduce, create */
/* derivative works, distribute, display and perform the Source Code and */
/* derivative works thereof, and to grant others the rights granted herein. */
/* */
/* - The TCG grants to the user of the other parts of the specification */
/* (other than the Source Code) the rights to reproduce, distribute, */
/* display, and perform the specification solely for the purpose of */
/* developing products based on such documents. */
/* */
/* 2. Source Code Distribution Conditions: */
/* */
/* - Redistributions of Source Code must retain the above copyright licenses, */
/* this list of conditions and the following disclaimers. */
/* */
/* - Redistributions in binary form must reproduce the above copyright */
/* licenses, this list of conditions and the following disclaimers in the */
/* documentation and/or other materials provided with the distribution. */
/* */
/* 3. Disclaimers: */
/* */
/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */
/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */
/* information on specification licensing rights available through TCG */
/* membership agreements. */
/* */
/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */
/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */
/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */
/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */
/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */
/* */
/* - Without limitation, TCG and its members and licensors disclaim all */
/* liability, including liability for infringement of any proprietary */
/* rights, relating to use of information in this specification and to the */
/* implementation of this specification, and TCG disclaims all liability for */
/* cost of procurement of substitute goods or services, lost profits, loss */
/* of use, loss of data or any incidental, consequential, direct, indirect, */
/* or special damages, whether under contract, tort, warranty or otherwise, */
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2012-2015 */
/* */
/********************************************************************************/
/* rev 119 */
#ifndef MAC_FP_H
#define MAC_FP_H
typedef struct {
TPMI_DH_OBJECT handle;
TPM2B_MAX_BUFFER buffer;
TPMI_ALG_MAC_SCHEME inScheme;
} Mac_In;
#define RC_Mac_handle (TPM_RC_H + TPM_RC_1)
#define RC_Mac_buffer (TPM_RC_P + TPM_RC_1)
#define RC_Mac_inScheme (TPM_RC_P + TPM_RC_2)
typedef struct {
TPM2B_MAX_BUFFER outMac;
} Mac_Out;
TPM_RC
TPM2_Mac(
Mac_In *in, // IN: input parameter list
Mac_Out *out // OUT: output parameter list
);
#endif

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Parameter Marshaling */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Marshal.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: Marshal.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -335,7 +335,7 @@ UINT16
TPMA_SESSION_Marshal(TPMA_SESSION *source, BYTE **buffer, INT32 *size)
{
UINT16 written = 0;
written += UINT8_Marshal(&source->val, buffer, size);
written += UINT8_Marshal(source, buffer, size);
return written;
}
@ -345,7 +345,7 @@ UINT16
TPMA_LOCALITY_Marshal(TPMA_LOCALITY *source, BYTE **buffer, INT32 *size)
{
UINT16 written = 0;
written += UINT8_Marshal(&source->val, buffer, size);
written += UINT8_Marshal(source, buffer, size);
return written;
}
@ -561,6 +561,15 @@ TPM2B_MAX_NV_BUFFER_Marshal(TPM2B_MAX_NV_BUFFER *source, BYTE **buffer, INT32 *s
return written;
}
/* Table 80 - Definition of TPM2B_TIMEOUT Structure <IN/OUT> */
UINT16
TPM2B_TIMEOUT_Marshal(TPM2B_TIMEOUT *source, BYTE **buffer, INT32 *size)
{
UINT16 written = 0;
written += TPM2B_Marshal(&source->b, buffer, size);
return written;
}
/* Table 2:82 - Definition of TPM2B_IV Structure (StructuresTable()) */
UINT16
@ -1690,8 +1699,8 @@ TPMS_ALGORITHM_DETAIL_ECC_Marshal(TPMS_ALGORITHM_DETAIL_ECC *source, BYTE **buff
written += TPM_ECC_CURVE_Marshal(&source->curveID, buffer, size);
written += UINT16_Marshal(&source->keySize, buffer, size);
written += TPMT_KDF_SCHEME_Marshal(&source->kdf, buffer, size);;
written += TPMT_ECC_SCHEME_Marshal(&source->sign, buffer, size);;
written += TPMT_KDF_SCHEME_Marshal(&source->kdf, buffer, size);
written += TPMT_ECC_SCHEME_Marshal(&source->sign, buffer, size);
written += TPM2B_ECC_PARAMETER_Marshal(&source->p, buffer, size);
written += TPM2B_ECC_PARAMETER_Marshal(&source->a, buffer, size);
written += TPM2B_ECC_PARAMETER_Marshal(&source->b, buffer, size);
@ -2079,7 +2088,7 @@ UINT16
TPMA_NV_Marshal(TPMA_NV *source, BYTE **buffer, INT32 *size)
{
UINT16 written = 0;
written += UINT32_Marshal(&source->val, buffer, size);
written += UINT32_Marshal(source, buffer, size);
return written;
}

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Parameter Marshaling */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Marshal_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: Marshal_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -153,6 +153,8 @@ extern "C" {
UINT16
TPM2B_MAX_NV_BUFFER_Marshal(TPM2B_MAX_NV_BUFFER *source, BYTE **buffer, INT32 *size);
UINT16
TPM2B_TIMEOUT_Marshal(TPM2B_TIMEOUT *source, BYTE **buffer, INT32 *size);
UINT16
TPM2B_IV_Marshal(TPM2B_IV *source, BYTE **buffer, INT32 *size);
UINT16
TPM2B_NAME_Marshal(TPM2B_NAME *source, BYTE **buffer, INT32 *size);

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Math functions performed with canonical integers in byte buffers */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: MathOnByteBuffers.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: MathOnByteBuffers.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -64,7 +64,7 @@
/* This file contains implementation of the math functions that are performed with canonical
integers in byte buffers. The canonical integer is big-endian bytes. */
#include "Tpm.h"
/* 9.11.1.1 UnsignedCmpB */
/* 9.11.2.1 UnsignedCmpB */
/* This function compare two unsigned values. The values are byte-aligned, big-endian numbers (e.g,
a hash). */
/* Return Values Meaning */
@ -94,7 +94,7 @@ UnsignedCompareB(
}
return 0;
}
/* 9.11.1.2 SignedCompareB() */
/* 9.11.2.2 SignedCompareB() */
/* Compare two signed integers: */
/* Return Values Meaning */
/* 1 if a > b */
@ -126,7 +126,7 @@ SignedCompareB(
// do unsigned compare the other way
return 0 - UnsignedCompareB(aSize, a, bSize, b);
}
/* 9.11.1.3 ModExpB */
/* 9.11.3.3 ModExpB */
/* This function is used to do modular exponentiation in support of RSA. The most typical uses are:
c = m^e mod n (RSA encrypt) and m = c^d mod n (RSA decrypt). When doing decryption, the e
parameter of the function will contain the private exponent d instead of the public exponent
@ -174,7 +174,7 @@ ModExpB(
Exit:
return retVal;
}
/* 9.11.1.4 DivideB() */
/* 9.11.2.4 DivideB() */
/* Divide an integer (n) by an integer (d) producing a quotient (q) and a remainder (r). If q or r
is not needed, then the pointer to them may be set to NULL. */
/* Error Returns Meaning */
@ -205,7 +205,7 @@ DivideB(
return TPM_RC_NO_RESULT;
return TPM_RC_SUCCESS;
}
/* 9.11.1.5 AdjustNumberB() */
/* 9.11.2.5 AdjustNumberB() */
/* Remove/add leading zeros from a number in a TPM2B. Will try to make the number by adding or
removing leading zeros. If the number is larger than the requested size, it will make the number
as small as possible. Setting requestedSize to zero is equivalent to requesting that the number
@ -242,3 +242,24 @@ AdjustNumberB(
}
return num->size;
}
/* 9.11.2.6 ShiftLeft() */
/* This function shifts a byte buffer (a TPM2B) one byte to the left. That is, the most significant
bit of the most significant byte is lost. */
TPM2B *
ShiftLeft(
TPM2B *value // IN/OUT: value to shift and shifted value out
)
{
UINT16 count = value->size;
BYTE *buffer = value->buffer;
if(count > 0)
{
for(count -= 1; count > 0; buffer++, count--)
{
buffer[0] = (buffer[0] << 1) + ((buffer[1] & 0x80) ? 1 : 0);
}
*buffer <<= 1;
}
return value;
}

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Math functions performed with canonical integers in byte buffers */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: MathOnByteBuffers_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: MathOnByteBuffers_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -102,6 +102,9 @@ AdjustNumberB(
TPM2B *num,
UINT16 requestedSize
);
TPM2B *
ShiftLeft(
TPM2B *value // IN/OUT: value to shift and shifted value out
);
#endif

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: NV.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: NV.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -62,53 +62,43 @@
#ifndef NV_H
#define NV_H
/* 5.14.1 Index Type Definitions */
/* These definitions allow the same code to be used pre and post 1.21. The main action is to
redefine the index type values from the bit values. Use TPM_NT_ORDINARY to indicate if the TPM_NT
type is defined */
#ifdef TPM_NT_ORDINARY
# define NV_ATTRIBUTES_TO_TYPE(attributes) (attributes.TPM_NT)
/* If TPM_NT_ORDINARY is defined, then the TPM_NT field is present in a TPMA_NV */
# define GET_TPM_NT(attributes) GET_ATTRIBUTE(attributes, TPMA_NV, TPM_NT)
#else
# define NV_ATTRIBUTES_TO_TYPE(attributes) \
( attributes.TPMA_NV_COUNTER \
+ (attributes.TPMA_NV_BITS << 1) \
+ (attributes.TPMA_NV_EXTEND << 2) \
/* If TPM_NT_ORDINARY is not defined, then need to synthesize it from the attributes */
# define GetNv_TPM_NV(attributes) \
( IS_ATTRIBUTE(attributes, TPMA_NV, COUNTER) \
+ (IS_ATTRIBUTE(attributes, TPMA_NV, BITS) << 1) \
+ (IS_ATTRIBUTE(attributes, TPMA_NV, EXTEND) << 2) \
)
# define TPM_NT_ORDINARY (0)
# define TPM_NT_COUNTER (1)
# define TPM_NT_BITS (2)
# define TPM_NT_EXTEND (4)
#endif
/* 5.17.2 Attribute Macros */
/* 5.14.2 Attribute Macros */
/* These macros are used to isolate the differences in the way that the index type changed in
version 1.21 of the specification */
#ifdef TPM_NT_ORDINARY
# define IsNvOrdinaryIndex(attributes) (attributes.TPM_NT == TPM_NT_ORDINARY)
#else
# define IsNvOrdinaryIndex(attributes) \
((attributes.TPMA_NV_COUNTER == CLEAR) \
&& (attributes.TPMA_NV_BITS == CLEAR) \
&& (attributes.TPMA_NV_EXTEND == CLEAR)
# define TPM_NT_ORDINARY (0)
#endif
#ifdef TPM_NT_COUNTER
# define IsNvCounterIndex(attributes) (attributes.TPM_NT == TPM_NT_COUNTER)
#else
# define IsNvCounterIndex(attributes) (attributes.TPMA_NV_COUNTER == SET)
# define TPM_NT_COUNTER (1)
#endif
#ifdef TPM_NT_BITS
# define IsNvBitsIndex(attributes) (attributes.TPM_NT == TPM_NT_BITS)
#else
# define IsNvBitsIndex(attributes) (attributes.TPMA_NV_BITS == SET)
# define TPM_NT_BITS (2)
#endif
#ifdef TPM_NT_EXTEND
# define IsNvExtendIndex(attributes) (attributes.TPM_NT == TPM_NT_EXTEND)
#else
# define IsNvExtendIndex(attributes) (attributes.TPMA_NV_EXTEND == SET)
# define TPM_NT_EXTEND (4)
#endif
(GET_TPM_NT(attributes) == TPM_NT_ORDINARY)
# define IsNvCounterIndex(attributes) \
(GET_TPM_NT(attributes) == TPM_NT_COUNTER)
# define IsNvBitsIndex(attributes) \
(GET_TPM_NT(attributes) == TPM_NT_BITS)
# define IsNvExtendIndex(attributes) \
(GET_TPM_NT(attributes) == TPM_NT_EXTEND)
#ifdef TPM_NT_PIN_PASS
# define IsNvPinPassIndex(attributes) (attributes.TPM_NT == TPM_NT_PIN_PASS)
# define IsNvPinPassIndex(attributes) \
(GET_TPM_NT(attributes) == TPM_NT_PIN_PASS)
#endif
#ifdef TPM_NT_PIN_FAIL
# define IsNvPinFailIndex(attributes) (attributes.TPM_NT == TPM_NT_PIN_FAIL)
# define IsNvPinFailIndex(attributes) \
(GET_TPM_NT(attributes) == TPM_NT_PIN_FAIL)
#endif
typedef struct {
UINT32 size;
@ -118,7 +108,7 @@ typedef struct {
(sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(OBJECT))
#define NV_INDEX_COUNTER_SIZE \
(sizeof(UINT32) + sizeof(NV_INDEX) + sizeof(UINT64))
#define NV_RAM_INDEX_COUNTER_SIZE \
#define NV_RAM_INDEX_COUNTER_SIZE \
(sizeof(NV_RAM_HEADER) + sizeof(UINT64))
typedef struct {
UINT32 size;
@ -130,22 +120,20 @@ typedef struct {
UINT32 values so that there is no padding between the UINT32 list end marker and the UIT64m()
maxCounter value. */
typedef UINT32 NV_LIST_TERMINATOR[3];
/* 5.15.3 Orderly RAM Values */
/* 5.14.3 Orderly RAM Values */
/* The following defines are for accessing orderly RAM values. This is the initialize for the RAM
reference iterator. */
#define NV_RAM_REF_INIT 0
/* This is the starting address of the RAM space used for orderly data */
#define RAM_ORDERLY_START \
(&s_indexOrderlyRam[0])
#define RAM_ORDERLY_START \
(&s_indexOrderlyRam[0])
/* This is the offset within NV that is used to save the orderly data on an orderly shutdown. */
#define NV_ORDERLY_START \
(NV_INDEX_RAM_DATA)
#define NV_ORDERLY_START \
(NV_INDEX_RAM_DATA)
/* This is the end of the orderly RAM space. It is actually the first byte after the last byte of
orderly RAM data */
#define RAM_ORDERLY_END \
(RAM_ORDERLY_START + sizeof(s_indexOrderlyRam))
(RAM_ORDERLY_START + sizeof(s_indexOrderlyRam))
/* This is the end of the orderly space in NV memory. As with RAM_ORDERLY_END, it is actually the
offset of the first byte after the end of the NV orderly data. */
#define NV_ORDERLY_END \
@ -153,17 +141,17 @@ typedef UINT32 NV_LIST_TERMINATOR[3];
/* Macro to check that an orderly RAM address is with range. */
#define ORDERLY_RAM_ADDRESS_OK(start, offset) \
((start >= RAM_ORDERLY_START) && ((start + offset - 1) < RAM_ORDERLY_END))
#define RETURN_IF_NV_IS_NOT_AVAILABLE \
{ \
if(g_NvStatus != TPM_RC_SUCCESS) \
return g_NvStatus; \
#define RETURN_IF_NV_IS_NOT_AVAILABLE \
{ \
if(g_NvStatus != TPM_RC_SUCCESS) \
return g_NvStatus; \
}
/* Routinely have to clear the orderly flag and fail if the NV is not available so that it can be
cleared. */
#define RETURN_IF_ORDERLY \
{ \
if(NvClearOrderly() != TPM_RC_SUCCESS) \
return g_NvStatus; \
#define RETURN_IF_ORDERLY \
{ \
if(NvClearOrderly() != TPM_RC_SUCCESS) \
return g_NvStatus; \
}
#define NV_IS_AVAILABLE (g_NvStatus == TPM_RC_SUCCESS)
#define IS_ORDERLY(value) (value < SU_DA_USED_VALUE)
@ -171,5 +159,4 @@ typedef UINT32 NV_LIST_TERMINATOR[3];
/* Macro to set the NV UPDATE_TYPE. This deals with the fact that the update is possibly a
combination of UT_NV and UT_ORDERLY. */
#define SET_NV_UPDATE(type) g_updateNV |= (type)
#endif
#endif // _NV_H_

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Non-Volatile Storage */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: NVCommands.c 847 2016-11-29 21:17:44Z kgoldman $ */
/* $Id: NVCommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -75,7 +75,7 @@ TPM2_NV_DefineSpace(
// If the UndefineSpaceSpecial command is not implemented, then can't have
// an index that can only be deleted with policy
#if CC_NV_UndefineSpaceSpecial == NO
if(IsNv_TPMA_NV_POLICY_DELETE(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
#endif
// check that the authPolicy consistent with hash algorithm
@ -94,7 +94,7 @@ TPM2_NV_DefineSpace(
return TPM_RCS_HIERARCHY + RC_NV_DefineSpace_authHandle;
// Attribute checks
// Eliminate the unsupported types
switch(NV_ATTRIBUTES_TO_TYPE(attributes))
switch(GET_TPM_NT(attributes))
{
#if CC_NV_Increment == YES
case TPM_NT_COUNTER:
@ -105,7 +105,7 @@ TPM2_NV_DefineSpace(
#if CC_NV_Extend == YES
case TPM_NT_EXTEND:
#endif
#if CC_PolicySigned == YES && defined TPM_NT_PIN_PASS
#if CC_PolicySecret == YES && defined TPM_NT_PIN_PASS
case TPM_NT_PIN_PASS:
case TPM_NT_PIN_FAIL:
#endif
@ -116,7 +116,7 @@ TPM2_NV_DefineSpace(
break;
}
// Check that the sizes are OK based on the type
switch(NV_ATTRIBUTES_TO_TYPE(attributes))
switch(GET_TPM_NT(attributes))
{
case TPM_NT_ORDINARY:
// Can't exceed the allowed size for the implementation
@ -134,11 +134,11 @@ TPM2_NV_DefineSpace(
break;
}
// Handle other specifics
switch(NV_ATTRIBUTES_TO_TYPE(attributes))
switch(GET_TPM_NT(attributes))
{
case TPM_NT_COUNTER:
// Counter can't have TPMA_NV_CLEAR_STCLEAR SET (don't clear counters)
if(IsNv_TPMA_NV_CLEAR_STCLEAR(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
break;
#ifdef TPM_NT_PIN_FAIL
@ -153,15 +153,15 @@ TPM2_NV_DefineSpace(
// (i.e., with platform authorization , owner authorization,
// or with policyAuth.)
// It is not allowed to create a PIN Index that can't be modified.
if(!IsNv_TPMA_NV_NO_DA(attributes))
if(!IS_ATTRIBUTE(attributes, TPMA_NV, NO_DA))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
#endif
#ifdef TPM_NT_PIN_PASS
case TPM_NT_PIN_PASS:
// AUTHWRITE must be CLEAR (see note above to TPM_NT_PIN_FAIL)
if(IsNv_TPMA_NV_AUTHWRITE(attributes)
|| IsNv_TPMA_NV_GLOBALLOCK(attributes)
|| IsNv_TPMA_NV_WRITEDEFINE(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE)
|| IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK)
|| IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
#endif // this comes before break because PIN_FAIL falls through
break;
@ -169,41 +169,41 @@ TPM2_NV_DefineSpace(
break;
}
// Locks may not be SET and written cannot be SET
if(IsNv_TPMA_NV_WRITTEN(attributes)
|| IsNv_TPMA_NV_WRITELOCKED(attributes)
|| IsNv_TPMA_NV_READLOCKED(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN)
|| IS_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED)
|| IS_ATTRIBUTE(attributes, TPMA_NV, READLOCKED))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// There must be a way to read the index.
if(!IsNv_TPMA_NV_OWNERREAD(attributes)
&& !IsNv_TPMA_NV_PPREAD(attributes)
&& !IsNv_TPMA_NV_AUTHREAD(attributes)
&& !IsNv_TPMA_NV_POLICYREAD(attributes))
if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERREAD)
&& !IS_ATTRIBUTE(attributes, TPMA_NV, PPREAD)
&& !IS_ATTRIBUTE(attributes, TPMA_NV, AUTHREAD)
&& !IS_ATTRIBUTE(attributes, TPMA_NV, POLICYREAD))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// There must be a way to write the index
if(!IsNv_TPMA_NV_OWNERWRITE(attributes)
&& !IsNv_TPMA_NV_PPWRITE(attributes)
&& !IsNv_TPMA_NV_AUTHWRITE(attributes)
&& !IsNv_TPMA_NV_POLICYWRITE(attributes))
if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERWRITE)
&& !IS_ATTRIBUTE(attributes, TPMA_NV, PPWRITE)
&& !IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE)
&& !IS_ATTRIBUTE(attributes, TPMA_NV, POLICYWRITE))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// An index with TPMA_NV_CLEAR_STCLEAR can't have TPMA_NV_WRITEDEFINE SET
if(IsNv_TPMA_NV_CLEAR_STCLEAR(attributes)
&& IsNv_TPMA_NV_WRITEDEFINE(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR)
&& IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// Make sure that the creator of the index can delete the index
if((IsNv_TPMA_NV_PLATFORMCREATE(attributes)
if((IS_ATTRIBUTE(attributes, TPMA_NV, PLATFORMCREATE)
&& in->authHandle == TPM_RH_OWNER)
|| (!IsNv_TPMA_NV_PLATFORMCREATE(attributes)
|| (!IS_ATTRIBUTE(attributes, TPMA_NV, PLATFORMCREATE)
&& in->authHandle == TPM_RH_PLATFORM))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_authHandle;
// If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by
// the platform
if(IsNv_TPMA_NV_POLICY_DELETE(attributes)
if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE)
&& TPM_RH_PLATFORM != in->authHandle)
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// Make sure that the TPMA_NV_WRITEALL is not set if the index size is larger
// than the allowed NV buffer size.
if(in->publicInfo.nvPublic.dataSize > MAX_NV_BUFFER_SIZE
&& IsNv_TPMA_NV_WRITEALL(attributes))
&& IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL))
return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
// And finally, see if the index is already defined.
if(NvIndexIsDefined(in->publicInfo.nvPublic.nvIndex))
@ -225,12 +225,12 @@ TPM2_NV_UndefineSpace(
NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
// Input Validation
// This command can't be used to delete an index with TPMA_NV_POLICY_DELETE SET
if(IsNv_TPMA_NV_POLICY_DELETE(nvIndex->publicArea.attributes))
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE))
return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex;
// The owner may only delete an index that was defined with ownerAuth. The
// platform may delete an index that was created with either authorization.
if(in->authHandle == TPM_RH_OWNER
&& IsNv_TPMA_NV_PLATFORMCREATE(nvIndex->publicArea.attributes))
&& IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE))
return TPM_RC_NV_AUTHORIZATION;
// Internal Data Update
// Call implementation dependent internal routine to delete NV index
@ -251,7 +251,7 @@ TPM2_NV_UndefineSpaceSpecial(
NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
// Input Validation
// This operation only applies when the TPMA_NV_POLICY_DELETE attribute is SET
if(!IsNv_TPMA_NV_POLICY_DELETE(nvIndex->publicArea.attributes))
if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE))
return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpaceSpecial_nvIndex;
// Internal Data Update
// Call implementation dependent internal routine to delete NV index
@ -317,7 +317,7 @@ TPM2_NV_Write(
// full sized.
// Note: if the requested size is the same as the Index data size, then offset
// will have to be zero. Otherwise, the range check above would have failed.
if(IsNv_TPMA_NV_WRITEALL(attributes)
if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL)
&& in->data.t.size < nvIndex->publicArea.dataSize)
return TPM_RC_NV_RANGE;
// Internal Data Update
@ -353,7 +353,7 @@ TPM2_NV_Increment(
return TPM_RCS_ATTRIBUTES + RC_NV_Increment_nvIndex;
// Internal Data Update
// If counter index is not been written, initialize it
if(!IsNv_TPMA_NV_WRITTEN(nvIndex->publicArea.attributes))
if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
countValue = NvReadMaxCount();
else
// Read NV data in native format for TPM CPU.
@ -369,12 +369,12 @@ TPM2_NV_Increment(
// If a counter just rolled over, then force the NV update.
// Note, if this is an orderly counter, then the write-back needs to be
// forced, for other counters, the write-back will happen anyway
if(IsNv_TPMA_NV_ORDERLY(nvIndex->publicArea.attributes)
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)
&& (countValue & MAX_ORDERLY_COUNT) == 0 )
{
// Need to force an NV update of orderly data
SET_NV_UPDATE(UT_ORDERLY);
}
{
// Need to force an NV update of orderly data
SET_NV_UPDATE(UT_ORDERLY);
}
}
return result;
}
@ -408,7 +408,7 @@ TPM2_NV_Extend(
// Perform the write.
oldDigest.t.size = CryptHashGetDigestSize(nvIndex->publicArea.nameAlg);
pAssert(oldDigest.t.size <= sizeof(oldDigest.t.buffer));
if(IsNv_TPMA_NV_WRITTEN(nvIndex->publicArea.attributes))
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
{
NvGetIndexData(nvIndex, locator, 0, oldDigest.t.size, oldDigest.t.buffer);
}
@ -454,7 +454,7 @@ TPM2_NV_SetBits(
if(!IsNvBitsIndex(nvIndex->publicArea.attributes))
return TPM_RCS_ATTRIBUTES + RC_NV_SetBits_nvIndex;
// If index is not been written, initialize it
if(!IsNv_TPMA_NV_WRITTEN(nvIndex->publicArea.attributes))
if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
oldValue = 0;
else
// Read index data
@ -491,14 +491,14 @@ TPM2_NV_WriteLock(
}
// if neither TPMA_NV_WRITEDEFINE nor TPMA_NV_WRITE_STCLEAR is set, the index
// can not be write-locked
if(nvAttributes.TPMA_NV_WRITEDEFINE == CLEAR
&& nvAttributes.TPMA_NV_WRITE_STCLEAR == CLEAR)
if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITEDEFINE)
&& !IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITE_STCLEAR))
return TPM_RCS_ATTRIBUTES + RC_NV_WriteLock_nvIndex;
// Internal Data Update
// Set the WRITELOCK attribute.
// Note: if TPMA_NV_WRITELOCKED were already SET, then the write access check
// above would have failed and this code isn't executed.
nvAttributes.TPMA_NV_WRITELOCKED = SET;
SET_ATTRIBUTE(nvAttributes, TPMA_NV, WRITELOCKED);
// Write index info back
return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex, locator,
nvAttributes);
@ -522,6 +522,13 @@ TPM2_NV_GlobalWriteLock(
#include "Tpm.h"
#include "NV_Read_fp.h"
#ifdef TPM_CC_NV_Read // Conditional expansion of this file
/* TPM_RC_NV_AUTHORIZATION the authorization was valid but the authorizing entity (authHandle) is
not allowed to read from the Index referenced by nvIndex */
/* TPM_RC_NV_LOCKED the Index referenced by nvIndex is read locked */
/* TPM_RC_NV_RANGE read range defined by size and offset is outside the range of the Index
referenced by nvIndex */
/* TPM_RC_NV_UNINITIALIZED the Index referenced by nvIndex has not been initialized (written) */
/* TPM_RC_VALUE the read size is larger than the MAX_NV_BUFFER_SIZE */
TPM_RC
TPM2_NV_Read(
NV_Read_In *in, // IN: input parameter list
@ -583,11 +590,11 @@ TPM2_NV_ReadLock(
// If NvReadAccessChecks return TPM_RC_NV_UNINITALIZED, then continue.
// It is not an error to read lock an uninitialized Index.
// if TPMA_NV_READ_STCLEAR is not set, the index can not be read-locked
if(nvAttributes.TPMA_NV_READ_STCLEAR == CLEAR)
if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, READ_STCLEAR))
return TPM_RCS_ATTRIBUTES + RC_NV_ReadLock_nvIndex;
// Internal Data Update
// Set the READLOCK attribute
nvAttributes.TPMA_NV_READLOCKED = SET;
SET_ATTRIBUTE(nvAttributes, TPMA_NV, READLOCKED);
// Write NV info back
return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex,
locator,
@ -646,6 +653,10 @@ TPM2_NV_Certify(
if((UINT32)in->size + (UINT32)in->offset > (UINT32)nvIndex->publicArea.dataSize)
return TPM_RC_NV_RANGE;
// Make sure the data will fit the return buffer
// NOTE: This check may be modified if the output buffer will not hold the
// maximum sized NV buffer as part of the certified data. The difference in
// size could be substantial if the signature scheme was produced a large
// signature (e.g., RSA 4096).
if(in->size > MAX_NV_BUFFER_SIZE)
return TPM_RCS_VALUE + RC_NV_Certify_size;
// Command Output

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Dynamic space for user defined NV */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: NVDynamic.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: NVDynamic.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -64,6 +64,7 @@
#define NV_C
#include "Tpm.h"
#include "PlatformData.h"
#include "NVDynamic_fp.h"
/* 8.4.3 Local Functions */
/* 8.4.3.1 NvNext() */
/* This function provides a method to traverse every data entry in NV dynamic area. */
@ -200,7 +201,7 @@ NvTestSpace(
reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE;
}
// If this is not an index or is not a counter, reserve space for the
// required number of counter indices
// required number of counter indexes
if(!isIndex || !isCounter)
{
// Get the number of counters
@ -223,12 +224,16 @@ NvWriteNvListEnd(
NV_REF end
)
{
// Marker is initialized with zeros
BYTE listEndMarker[sizeof(NV_LIST_TERMINATOR)] = {0};
UINT64 maxCount = NvReadMaxCount();
//
// This is a constant check that can be resolved at compile time.
cAssert(sizeof(UINT64) <= sizeof(NV_LIST_TERMINATOR) - sizeof(UINT32));
// Copy the maxCount value to the marker buffer
MemoryCopy(&listEndMarker[sizeof(UINT32)], &maxCount, sizeof(UINT64));
pAssert(end + sizeof(NV_LIST_TERMINATOR) <= s_evictNvEnd);
// Write it to memory
NvWrite(end, sizeof(NV_LIST_TERMINATOR), &listEndMarker);
return end + sizeof(NV_LIST_TERMINATOR);
}
@ -256,7 +261,7 @@ NvAdd(
newAddr = NvGetEnd();
// Step over the forward pointer
nextAddr = newAddr + sizeof(UINT32);
// Optionally write the handle. For indices, the handle is TPM_RH_UNASSIGNED
// Optionally write the handle. For indexes, the handle is TPM_RH_UNASSIGNED
// so that the handle in the nvIndex is used instead of writing this value
if(handle != TPM_RH_UNASSIGNED)
{
@ -477,7 +482,7 @@ NvDeleteRAM(
SET_NV_UPDATE(UT_ORDERLY);
return;
}
/* 8.4.4.8 NvReadIndex() */
/* 8.4.4.9 NvReadIndex() */
/* This function is used to read the NV Index NV_INDEX. This is used so that the index information
can be compressed and only this function would be needed to decompress it. Mostly, compression
would only be able to save the space needed by the policy. */
@ -489,6 +494,7 @@ NvReadNvIndexInfo(
{
pAssert(nvIndex != NULL);
NvRead(nvIndex, ref, sizeof(NV_INDEX));
return;
}
/* 8.4.4.9 NvReadObject() */
/* This function is used to read a persistent object. This is used so that the object information
@ -500,6 +506,7 @@ NvReadObject(
)
{
NvRead(object, (ref + sizeof(TPM_HANDLE)), sizeof(OBJECT));
return;
}
/* 8.4.4.10 NvFindEvict() */
/* This function will return the NV offset of an evict object */
@ -603,6 +610,7 @@ NvWriteRamIndexAttributes(
{
MemoryCopy(ref + offsetof(NV_RAM_HEADER, attributes), &attributes,
sizeof(TPMA_NV));
return;
}
/* 8.4.5 Externally Accessible Functions */
/* 8.4.5.1 NvIsPlatformPersistentHandle() */
@ -648,6 +656,7 @@ NvIndexIsAccessible(
)
{
NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL);
//
if(nvIndex == NULL)
// If index is not found, return TPM_RC_HANDLE
return TPM_RC_HANDLE;
@ -655,7 +664,7 @@ NvIndexIsAccessible(
{
// if shEnable is CLEAR, an ownerCreate NV Index should not be
// indicated as present
if(!IsNv_TPMA_NV_PLATFORMCREATE(nvIndex->publicArea.attributes))
if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE))
{
if(gc.shEnable == FALSE)
return TPM_RC_HANDLE;
@ -665,9 +674,9 @@ NvIndexIsAccessible(
else if(gc.phEnableNV == FALSE)
return TPM_RC_HANDLE;
}
#if 0 // Writelock test
#if 0 // Writelock test for debug
// If the Index is write locked and this is an NV Write operation...
if(IsNv_TPMA_NV_WRITELOCKED(nvIndex->publicArea.attributes)
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITELOCKED)
&& IsWriteOperation(commandIndex))
{
// then return a locked indication unless the command is TPM2_NV_WriteLock
@ -676,9 +685,9 @@ NvIndexIsAccessible(
return TPM_RC_SUCCESS;
}
#endif
#if 0 // Readlock Test
#if 0 // Readlock Test for debug
// If the Index is read locked and this is an NV Read operation...
if(IsNv_TPMA_NV_READLOCKED(nvIndex->publicArea.attributes)
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, READLOCKED)
&& IsReadOperation(commandIndex))
{
// then return a locked indication unless the command is TPM2_NV_ReadLock
@ -721,6 +730,7 @@ NvIndexCacheInit(
s_cachedNvRef = NV_REF_INIT;
s_cachedNvRamRef = NV_RAM_REF_INIT;
s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED;
return;
}
/* 8.4.5.6 NvGetIndexData() */
/* This function is used to access the data in an NV Index. The data is returned as a byte
@ -737,10 +747,11 @@ NvGetIndexData(
)
{
TPMA_NV nvAttributes;
//
pAssert(nvIndex != NULL);
nvAttributes = nvIndex->publicArea.attributes;
pAssert(nvAttributes.TPMA_NV_WRITTEN == SET);
if(nvAttributes.TPMA_NV_ORDERLY == SET)
pAssert(IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN));
if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, ORDERLY))
{
// Get data from RAM buffer
NV_RAM_REF ramAddr = NvRamGetIndex(nvIndex->publicArea.nvIndex);
@ -785,7 +796,8 @@ NvWriteIndexAttributes(
)
{
TPM_RC result;
if(IsNv_TPMA_NV_ORDERLY(attributes))
//
if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY))
{
NV_RAM_REF ram = NvRamGetIndex(handle);
NvWriteRamIndexAttributes(ram, attributes);
@ -808,17 +820,23 @@ NvWriteIndexAuth(
TPM2B_AUTH *authValue // IN: the authValue to write
)
{
TPM_RC result;
if(locator == s_cachedNvRef)
{
MemoryCopy2B(&s_cachedNvIndex.authValue.b, &authValue->b,
sizeof(s_cachedNvIndex.authValue.t.buffer));
}
result = NvConditionallyWrite(
locator + offsetof(NV_INDEX, authValue),
sizeof(UINT16) + authValue->t.size,
authValue);
return result;
{
TPM_RC result;
//
// If the locator is pointing to the cached index value...
if(locator == s_cachedNvRef)
{
// copy the authValue to the cached index so it will be there if we
// look for it. This is a safety thing.
MemoryCopy2B(&s_cachedNvIndex.authValue.b, &authValue->b,
sizeof(s_cachedNvIndex.authValue.t.buffer));
}
result = NvConditionallyWrite(
locator + offsetof(NV_INDEX, authValue),
sizeof(UINT16) + authValue->t.size,
authValue);
return result;
}
}
/* 8.4.5.10 NvGetIndexInfo() */
/* This function loads the nvIndex Info into the NV cache and returns a pointer to the NV_INDEX. If
@ -840,7 +858,7 @@ NvGetIndexInfo(
if(s_cachedNvRef == 0)
return NULL;
NvReadNvIndexInfo(s_cachedNvRef, &s_cachedNvIndex);
if(IsNv_TPMA_NV_ORDERLY(s_cachedNvIndex.publicArea.attributes))
if(IS_ATTRIBUTE(s_cachedNvIndex.publicArea.attributes, TPMA_NV, ORDERLY))
{
s_cachedNvRamRef = NvRamGetIndex(nvHandle);
s_cachedNvIndex.publicArea.attributes =
@ -857,7 +875,7 @@ NvGetIndexInfo(
/* This function requires that the NV Index is defined, and the data is within the defined data
range for the index. */
/* Index data is only written due to a command that modifies the data in a single index. There is no
case where changes are made to multiple indices data at the same time. Multiple attributes may be
case where changes are made to multiple indexes data at the same time. Multiple attributes may be
change but not multiple index data. This is important because we will normally be handling the
index for which we have the cached pointer values. */
/* Error Returns Meaning */
@ -872,6 +890,7 @@ NvWriteIndexData(
)
{
TPM_RC result = TPM_RC_SUCCESS;
//
pAssert(nvIndex != NULL);
// Make sure that this is dealing with the 'default' index.
// Note: it is tempting to change the calling sequence so that the 'default' is
@ -881,13 +900,13 @@ NvWriteIndexData(
pAssert(offset <= nvIndex->publicArea.dataSize
&& size <= (nvIndex->publicArea.dataSize - offset));
// Update TPMA_NV_WRITTEN bit if necessary
if(!IsNv_TPMA_NV_WRITTEN(nvIndex->publicArea.attributes))
if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
{
// Update the in memory version of the attributes
nvIndex->publicArea.attributes.TPMA_NV_WRITTEN = SET;
SET_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN);
// If this is not orderly, then update the NV version of
// the attributes
if(!IsNv_TPMA_NV_ORDERLY(nvIndex->publicArea.attributes))
if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY))
{
result = NvWriteNvIndexAttributes(s_cachedNvRef,
nvIndex->publicArea.attributes);
@ -911,7 +930,7 @@ NvWriteIndexData(
SET_NV_UPDATE(UT_ORDERLY);
// If setting the written attribute on an ordinary index, make sure that
// the data is all cleared out in case there is a partial write. This
// is only necessary for ordinary indices because all of the other types
// is only necessary for ordinary indexes because all of the other types
// are always written in total.
else if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes))
MemorySet(s_cachedNvRamRef + sizeof(NV_RAM_HEADER),
@ -919,7 +938,7 @@ NvWriteIndexData(
}
}
// If this is orderly data, write it to RAM
if(IsNv_TPMA_NV_ORDERLY(nvIndex->publicArea.attributes))
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY))
{
// Note: if this is the first write to a counter, the code above will queue
// the write to NV of the RAM data in order to update TPMA_NV_WRITTEN. In
@ -1005,14 +1024,16 @@ NvDefineIndex(
TPM2B_AUTH *authValue // IN: The initial authorization value
)
{
// The buffer to be written to NV memory
NV_INDEX nvIndex; // the index data
UINT16 entrySize; // size of entry
TPM_RC result;
//
entrySize = sizeof(NV_INDEX);
// only allocate data space for Indices that are going to be written to NV.
// Orderly indices don't need space.
if(!IsNv_TPMA_NV_ORDERLY(publicArea->attributes))
// only allocate data space for indexes that are going to be written to NV.
// Orderly indexes don't need space.
if(!IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY))
entrySize += publicArea->dataSize;
// Check if we have enough space to create the NV Index
// In this implementation, the only resource limitation is the available NV
@ -1022,7 +1043,7 @@ NvDefineIndex(
return TPM_RC_NV_SPACE;
// if the index to be defined is RAM backed, check RAM space availability
// as well
if(IsNv_TPMA_NV_ORDERLY(publicArea->attributes)
if(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY)
&& !NvRamTestSpaceIndex(publicArea->dataSize))
return TPM_RC_NV_SPACE;
// Copy input value to nvBuffer
@ -1030,11 +1051,12 @@ NvDefineIndex(
// Copy the authValue
nvIndex.authValue = *authValue;
// Add index to NV memory
result = NvAdd(entrySize, sizeof(NV_INDEX), TPM_RH_UNASSIGNED, (BYTE *)&nvIndex);
result = NvAdd(entrySize, sizeof(NV_INDEX), TPM_RH_UNASSIGNED,
(BYTE *)&nvIndex);
if(result == TPM_RC_SUCCESS)
{
// If the data of NV Index is RAM backed, add the data area in RAM as well
if(IsNv_TPMA_NV_ORDERLY(publicArea->attributes))
if(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY))
NvAddRAM(publicArea);
}
return result;
@ -1081,18 +1103,19 @@ NvDeleteIndex(
)
{
TPM_RC result;
//
if(nvIndex != NULL)
{
// Whenever a counter is deleted, make sure that the MaxCounter value is
// updated to reflect the value
if(IsNvCounterIndex(nvIndex->publicArea.attributes)
&& IsNv_TPMA_NV_WRITTEN(nvIndex->publicArea.attributes))
&& IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
NvUpdateMaxCount(NvGetUINT64Data(nvIndex, entityAddr));
result = NvDelete(entityAddr);
if(result != TPM_RC_SUCCESS)
return result;
// If the NV Index is RAM backed, delete the RAM data as well
if(IsNv_TPMA_NV_ORDERLY(nvIndex->publicArea.attributes))
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY))
NvDeleteRAM(nvIndex->publicArea.nvIndex);
NvIndexCacheInit();
}
@ -1127,11 +1150,13 @@ NvFlushHierarchy(
NV_REF currentAddr;
TPM_HANDLE entityHandle;
TPM_RC result = TPM_RC_SUCCESS;
//
while((currentAddr = NvNext(&iter, &entityHandle)) != 0)
{
if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX)
{
NV_INDEX nvIndex;
//
// If flush endorsement or platform hierarchy, no NV Index would be
// flushed
if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM)
@ -1139,7 +1164,8 @@ NvFlushHierarchy(
// Get the index information
NvReadNvIndexInfo(currentAddr, &nvIndex);
// For storage hierarchy, flush OwnerCreated index
if(!IsNv_TPMA_NV_PLATFORMCREATE(nvIndex.publicArea.attributes))
if(!IS_ATTRIBUTE(nvIndex.publicArea.attributes, TPMA_NV,
PLATFORMCREATE))
{
// Delete the index (including RAM for orderly)
result = NvDeleteIndex(&nvIndex, currentAddr);
@ -1152,18 +1178,19 @@ NvFlushHierarchy(
else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT)
{
OBJECT_ATTRIBUTES attributes;
//
NvRead(&attributes,
(UINT32)(currentAddr
+ sizeof(TPM_HANDLE)
+ offsetof(OBJECT, attributes)),
sizeof(OBJECT_ATTRIBUTES));
// If the evict object belongs to the hierarchy to be flushed
if((hierarchy == TPM_RH_PLATFORM && attributes.ppsHierarchy == SET)
|| (hierarchy == TPM_RH_OWNER && attributes.spsHierarchy == SET)
// If the evict object belongs to the hierarchy to be flushed...
if((hierarchy == TPM_RH_PLATFORM && attributes.ppsHierarchy == SET)
|| (hierarchy == TPM_RH_OWNER && attributes.spsHierarchy == SET)
|| (hierarchy == TPM_RH_ENDORSEMENT
&& attributes.epsHierarchy == SET))
{
// Delete the evict object
// ...then delete the evict object
result = NvDelete(currentAddr);
if(result != TPM_RC_SUCCESS)
break;
@ -1179,7 +1206,7 @@ NvFlushHierarchy(
return result;
}
/* 8.4.5.20 NvSetGlobalLock() */
/* This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indices that have
/* This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indexes that have
TPMA_NV_GLOBALLOCK SET. This function is use by TPM2_NV_GlobalWriteLock(). */
/* Error Returns Meaning */
/* TPM_RC_NV_RATE NV is unavailable because of rate limit */
@ -1194,28 +1221,30 @@ NvSetGlobalLock(
NV_REF currentAddr;
NV_RAM_REF currentRamAddr;
TPM_RC result = TPM_RC_SUCCESS;
// Check all normal Indices
while((currentAddr = NvNextIndex(NULL, &iter)) != 0)
{
TPMA_NV attributes = NvReadNvIndexAttributes(currentAddr);
// See if it should be locked
if(!IsNv_TPMA_NV_ORDERLY(attributes)
&& IsNv_TPMA_NV_GLOBALLOCK(attributes))
{
attributes.TPMA_NV_WRITELOCKED = SET;
result = NvWriteNvIndexAttributes(currentAddr, attributes);
if(result != TPM_RC_SUCCESS)
return result;
}
}
//
// Check all normal indexes
while((currentAddr = NvNextIndex(NULL, &iter)) != 0)
{
TPMA_NV attributes = NvReadNvIndexAttributes(currentAddr);
//
// See if it should be locked
if(!IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)
&& IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK))
{
SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED);
result = NvWriteNvIndexAttributes(currentAddr, attributes);
if(result != TPM_RC_SUCCESS)
return result;
}
}
// Now search all the orderly attributes
while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0)
{
// See if it should be locked
TPMA_NV attributes = NvReadRamIndexAttributes(currentRamAddr);
if(IsNv_TPMA_NV_GLOBALLOCK(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK))
{
attributes.TPMA_NV_WRITELOCKED = SET;
SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED);
NvWriteRamIndexAttributes(currentRamAddr, attributes);
}
}
@ -1299,16 +1328,16 @@ NvCapGetPersistent(
// A handle with a value larger than start handle is a candidate
// for return. Insert sort it to the return list. Insert sort algorithm
// is chosen here for simplicity based on the assumption that the total
// number of NV Indices is small. For an implementation that may allow
// large number of NV Indices, a more efficient sorting algorithm may be
// number of NV Indexes is small. For an implementation that may allow
// large number of NV Indexes, a more efficient sorting algorithm may be
// used here.
InsertSort(handleList, count, entityHandle);
}
return more;
}
/* 8.4.5.23 NvCapGetIndex() */
/* This function returns a list of handles of NV Indices, starting from handle. Handle must be in
the range of NV Indices, but does not have to reference an existing NV Index. */
/* This function returns a list of handles of NV Indexes, starting from handle. Handle must be in
the range of NV Indexes, but does not have to reference an existing NV Index. */
/* Return Values Meaning */
/* YES if there are more handles to report */
/* NO all the available handles has been reported */
@ -1340,8 +1369,8 @@ NvCapGetIndex(
// A handle with a value larger than start handle is a candidate
// for return. Insert sort it to the return list. Insert sort algorithm
// is chosen here for simplicity based on the assumption that the total
// number of NV Indices is small. For an implementation that may allow
// large number of NV Indices, a more efficient sorting algorithm may be
// number of NV Indexes is small. For an implementation that may allow
// large number of NV Indexes, a more efficient sorting algorithm may be
// used here.
InsertSort(handleList, count, nvHandle);
}
@ -1399,7 +1428,7 @@ NvCapGetPersistentAvail(
return availNVSpace / NV_EVICT_OBJECT_SIZE;
}
/* 8.4.5.27 NvCapGetCounterNumber() */
/* Get the number of defined NV Indexes that are counter indices. */
/* Get the number of defined NV Indexes that are counter indexes. */
UINT32
NvCapGetCounterNumber(
void
@ -1425,20 +1454,22 @@ NvSetStartupAttributes(
)
{
// Clear read lock
attributes.TPMA_NV_READLOCKED = CLEAR;
CLEAR_ATTRIBUTE(attributes, TPMA_NV, READLOCKED);
// Will change a non counter index to the unwritten state if:
// a) TPMA_NV_CLEAR_STCLEAR is SET
// b) orderly and TPM Reset
if(!IsNvCounterIndex(attributes))
{
if(IsNv_TPMA_NV_CLEAR_STCLEAR(attributes)
|| (IsNv_TPMA_NV_ORDERLY(attributes) && (type == SU_RESET)))
attributes.TPMA_NV_WRITTEN = CLEAR;
if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR)
|| (IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)
&& (type == SU_RESET)))
CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITTEN);
}
// Unlock any index that is not written or that does not have
// TPMA_NV_WRITEDEFINE SET.
if(!IsNv_TPMA_NV_WRITTEN(attributes) || !IsNv_TPMA_NV_WRITEDEFINE(attributes))
attributes.TPMA_NV_WRITELOCKED = CLEAR;
if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN)
|| !IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE))
CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED);
return attributes;
}
/* 8.4.5.29 NvEntityStartup() */
@ -1471,13 +1502,13 @@ NvEntityStartup(
{
attributes = NvReadNvIndexAttributes(currentAddr);
// If this is an orderly index, defer processing until loop below
if(IsNv_TPMA_NV_ORDERLY(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY))
continue;
// Set the attributes appropriate for this startup type
attributes = NvSetStartupAttributes(attributes, type);
NvWriteNvIndexAttributes(currentAddr, attributes);
}
// Iterate all the orderly indices to clear the locks and initialize counters
// Iterate all the orderly indexes to clear the locks and initialize counters
while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0)
{
attributes = NvReadRamIndexAttributes(currentRamAddr);
@ -1502,7 +1533,7 @@ NvEntityStartup(
return;
}
/* 8.4.5.30 NvCapGetCounterAvail() */
/* This function returns an estimate of the number of additional counter type NV Indices that can be
/* This function returns an estimate of the number of additional counter type NV Indexes that can be
defined. */
UINT32
NvCapGetCounterAvail(

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Dynamic space for user defined NV */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: NVDynamic_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: NVDynamic_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: NV_spt.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: NV_spt.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -80,7 +80,7 @@ NvReadAccessChecks(
)
{
// If data is read locked, returns an error
if(IsNv_TPMA_NV_READLOCKED(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, READLOCKED))
return TPM_RC_NV_LOCKED;
// If the authorization was provided by the owner or platform, then check
// that the attributes allow the read. If the authorization handle
@ -89,13 +89,13 @@ NvReadAccessChecks(
if(authHandle == TPM_RH_OWNER)
{
// If Owner provided authorization then ONWERWRITE must be SET
if(!IsNv_TPMA_NV_OWNERREAD(attributes))
if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERREAD))
return TPM_RC_NV_AUTHORIZATION;
}
else if(authHandle == TPM_RH_PLATFORM)
{
// If Platform provided authorization then PPWRITE must be SET
if(!IsNv_TPMA_NV_PPREAD(attributes))
if(!IS_ATTRIBUTE(attributes, TPMA_NV, PPREAD))
return TPM_RC_NV_AUTHORIZATION;
}
// If neither Owner nor Platform provided authorization, make sure that it was
@ -105,7 +105,7 @@ NvReadAccessChecks(
// If the index has not been written, then the value cannot be read
// NOTE: This has to come after other access checks to make sure that
// the proper authorization is given to TPM2_NV_ReadLock()
if(!IsNv_TPMA_NV_WRITTEN(attributes))
if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN))
return TPM_RC_NV_UNINITIALIZED;
return TPM_RC_SUCCESS;
}
@ -124,7 +124,7 @@ NvWriteAccessChecks(
)
{
// If data is write locked, returns an error
if(IsNv_TPMA_NV_WRITELOCKED(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED))
return TPM_RC_NV_LOCKED;
// If the authorization was provided by the owner or platform, then check
// that the attributes allow the write. If the authorization handle
@ -133,13 +133,13 @@ NvWriteAccessChecks(
if(authHandle == TPM_RH_OWNER)
{
// If Owner provided authorization then ONWERWRITE must be SET
if(!IsNv_TPMA_NV_OWNERWRITE(attributes))
if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERWRITE))
return TPM_RC_NV_AUTHORIZATION;
}
else if(authHandle == TPM_RH_PLATFORM)
{
// If Platform provided authorization then PPWRITE must be SET
if(!IsNv_TPMA_NV_PPWRITE(attributes))
if(!IS_ATTRIBUTE(attributes, TPMA_NV, PPWRITE))
return TPM_RC_NV_AUTHORIZATION;
}
// If neither Owner nor Platform provided authorization, make sure that it was

View File

@ -3,7 +3,7 @@
/* Manage the object store of the TPM. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Object.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Object.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -76,7 +76,6 @@ ObjectFlush(
)
{
object->attributes.occupied = CLEAR;
// MemorySet(&object->attributes, 0, sizeof(OBJECT_ATTRIBUTES));
}
/* 8.6.3.2 ObjectSetInUse() */
/* This access function sets the occupied attribute of an object slot. */
@ -317,9 +316,12 @@ ObjectSetLoadedAttributes(
)
{
OBJECT *parent = HandleToObject(parentHandle);
TPMA_OBJECT objectAttributes = object->publicArea.objectAttributes;
//
// Copy the stClear attribute from the public area. This could be overwritten
// if the parent has stClear SET
object->attributes.stClear = object->publicArea.objectAttributes.stClear;
object->attributes.stClear =
IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear);
// If parent handle is a permanent handle, it is a primary (unless it is NULL
if(parent == NULL)
{
@ -346,7 +348,7 @@ ObjectSetLoadedAttributes(
{
// is this a stClear object
object->attributes.stClear =
(object->publicArea.objectAttributes.stClear == SET
(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear)
|| (parent->attributes.stClear == SET));
object->attributes.epsHierarchy = parent->attributes.epsHierarchy;
object->attributes.spsHierarchy = parent->attributes.spsHierarchy;
@ -363,9 +365,9 @@ ObjectSetLoadedAttributes(
else
{
// check attributes for different types of parents
if(object->publicArea.objectAttributes.restricted
if(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, restricted)
&& !object->attributes.publicOnly
&& object->publicArea.objectAttributes.decrypt
&& IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, decrypt)
&& object->publicArea.nameAlg != TPM_ALG_NULL)
{
// This is a parent. If it is not a KEYEDHASH, it is an ordinary parent.
@ -404,6 +406,7 @@ ObjectLoad(
{
TPM_RC result = TPM_RC_SUCCESS;
BOOL doCheck;
//
// Do validations of public area object descriptions
// Is this public only or a no-name object?
if(sensitive == NULL || publicArea->nameAlg == TPM_ALG_NULL)
@ -414,6 +417,13 @@ ObjectLoad(
}
else
{
// For any sensitive area, make sure that the seedSize is no larger than the
// digest size of nameAlg
#if 1 //??
if(sensitive->seedValue.t.size
> CryptHashGetDigestSize(publicArea->nameAlg))
return TPM_RC_SENSITIVE; // not a 'safe' return code so no add
#endif
// Check attributes and schemes for consistency
result = PublicAttributesValidation(parent, publicArea);
}
@ -426,7 +436,8 @@ ObjectLoad(
// If the parent is not NULL, then this is an ordinary load and we only check
// if the parent is not fixedTPM
else if(parent != NULL)
doCheck = parent->publicArea.objectAttributes.fixedTPM == CLEAR;
doCheck = !IS_ATTRIBUTE(parent->publicArea.objectAttributes,
TPMA_OBJECT, fixedTPM);
else
// This is a loadExternal. Check everything.
// Note: the check functions will filter things based on the name algorithm
@ -495,7 +506,7 @@ AllocateSequenceSlot(
// be marked as temporary so that it can't be persisted
object->attributes.temporary = SET;
// A sequence object is DA exempt.
object->objectAttributes.noDA = SET;
SET_ATTRIBUTE(object->objectAttributes, TPMA_OBJECT, noDA);
// Copy the authorization value
if(auth != NULL)
object->auth = *auth;
@ -508,6 +519,7 @@ AllocateSequenceSlot(
/* This function creates an internal HMAC sequence object. */
/* Error Returns Meaning */
/* TPM_RC_OBJECT_MEMORY if there is no free slot for an object */
#if defined TPM_CC_HMAC_Start || defined TPM_CC_MAC_Start
TPM_RC
ObjectCreateHMACSequence(
TPMI_ALG_HASH hashAlg, // IN: hash algorithm
@ -517,17 +529,27 @@ ObjectCreateHMACSequence(
)
{
HASH_OBJECT *hmacObject;
//
// Try to allocate a slot for new object
hmacObject = AllocateSequenceSlot(newHandle, auth);
if(hmacObject == NULL)
return TPM_RC_OBJECT_MEMORY;
// Set HMAC sequence bit
hmacObject->attributes.hmacSeq = SET;
CryptHmacStart(&hmacObject->state.hmacState, hashAlg,
keyObject->sensitive.sensitive.bits.b.size,
keyObject->sensitive.sensitive.bits.b.buffer);
#ifndef SMAC_IMPLEMENTED
if(CryptHmacStart(&hmacObject->state.hmacState, hashAlg,
keyObject->sensitive.sensitive.bits.b.size,
keyObject->sensitive.sensitive.bits.b.buffer) == 0)
#else
if(CryptMacStart(&hmacObject->state.hmacState,
&keyObject->publicArea.parameters,
hashAlg, &keyObject->sensitive.sensitive.any.b) == 0)
#endif // SMAC_IMPLEMENTED
return TPM_RC_FAILURE;
return TPM_RC_SUCCESS;
}
#endif
/* 8.6.3.18 ObjectCreateHashSequence() */
/* This function creates a hash sequence object. */
/* Error Returns Meaning */
@ -587,7 +609,7 @@ ObjectTerminateEvent(
if(hashObject->attributes.eventSeq)
{
// If it is, close any open hash contexts. This is done in case
// the crypto implementation has some context values that need to be
// the cryptographic implementation has some context values that need to be
// cleaned up (hygiene).
//
for(count = 0; CryptHashGetAlgByIndex(count) != TPM_ALG_NULL; count++)
@ -738,18 +760,15 @@ ObjectLoadEvict(
TPM2B_NAME *
ObjectComputeName(
UINT32 size, // IN: the size of the area to digest
BYTE *publicArea, // IN: the public area to digest area
BYTE *publicArea, // IN: the public area to digest
TPM_ALG_ID nameAlg, // IN: the hash algorithm to use
TPM2B_NAME *name // OUT: Computed name
)
{
HASH_STATE hashState; // hash state
// Start hash stack
name->t.size = CryptHashStart(&hashState, nameAlg);
// Adding public area
CryptDigestUpdate(&hashState, size, publicArea);
// Complete hash leaving room for the name algorithm
CryptHashEnd(&hashState, name->t.size, &name->t.name[2]);
// Hash the publicArea into the name buffer leaving room for the nameAlg
name->t.size = CryptHashBlock(nameAlg, size, publicArea,
sizeof(name->t.name) - 2,
&name->t.name[2]);
// set the nameAlg
UINT16_TO_BYTE_ARRAY(nameAlg, name->t.name);
name->t.size += 2;
@ -781,20 +800,11 @@ PublicMarshalAndComputeName(
}
return name;
}
/* 8.6.3.27 AlgOfName() */
/* This function as a macro returns the nameAlg from a TPM2B_NAME. */
TPMI_ALG_HASH
AlgOfName(
TPM2B_NAME *name
)
{
return BYTE_ARRAY_TO_UINT16(name->t.name);
}
/* 8.6.3.28 ComputeQualifiedName() */
/* This function computes the qualified name of an object. */
void
ComputeQualifiedName(
TPM_HANDLE parentHandle, // IN: parent's name
TPM_HANDLE parentHandle, // IN: parent's handle
TPM_ALG_ID nameAlg, // IN: name hash
TPM2B_NAME *name, // IN: name of the object
TPM2B_NAME *qualifiedName // OUT: qualified name of the object
@ -804,6 +814,7 @@ ComputeQualifiedName(
TPM2B_NAME parentName;
if(parentHandle == TPM_RH_UNASSIGNED)
{
MemoryCopy2B(&qualifiedName->b, &name->b, sizeof(qualifiedName->t.name));
*qualifiedName = *name;
}
else
@ -838,10 +849,11 @@ ObjectIsStorage(
{
OBJECT *object = HandleToObject(handle);
TPMT_PUBLIC *publicArea = ((object != NULL) ? &object->publicArea : NULL);
//
return (publicArea != NULL
&& publicArea->objectAttributes.restricted == SET
&& publicArea->objectAttributes.decrypt == SET
&& publicArea->objectAttributes.sign == CLEAR
&& IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
&& IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
&& !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)
&& (object->publicArea.type == ALG_RSA_VALUE
|| object->publicArea.type == ALG_ECC_VALUE));
}

View File

@ -3,7 +3,7 @@
/* Object Commands */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: ObjectCommands.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: ObjectCommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -203,9 +203,11 @@ TPM2_LoadExternal(
// An external object with a sensitive area must have fixedTPM == CLEAR
// fixedParent == CLEAR so that it does not appear to be a key created by
// this TPM.
if(in->inPublic.publicArea.objectAttributes.fixedTPM != CLEAR
|| in->inPublic.publicArea.objectAttributes.fixedParent != CLEAR
|| in->inPublic.publicArea.objectAttributes.restricted != CLEAR)
if(IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, fixedTPM)
|| IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT,
fixedParent)
|| IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT,
restricted))
return TPM_RCS_ATTRIBUTES + RC_LoadExternal_inPublic;
// Have sensitive point to something other than NULL so that object
// initialization will load the sensitive part too
@ -269,8 +271,9 @@ TPM2_ActivateCredential(
activateObject = HandleToObject(in->activateHandle);
// input decrypt key must be an asymmetric, restricted decryption key
if(!CryptIsAsymAlgorithm(object->publicArea.type)
|| object->publicArea.objectAttributes.decrypt == CLEAR
|| object->publicArea.objectAttributes.restricted == CLEAR)
|| !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
|| !IS_ATTRIBUTE(object->publicArea.objectAttributes,
TPMA_OBJECT, restricted))
return TPM_RCS_TYPE + RC_ActivateCredential_keyHandle;
// Command output
// Decrypt input credential data via asymmetric decryption. A
@ -314,8 +317,8 @@ TPM2_MakeCredential(
// input key must be an asymmetric, restricted decryption key
// NOTE: Needs to be restricted to have a symmetric value.
if(!CryptIsAsymAlgorithm(object->publicArea.type)
|| object->publicArea.objectAttributes.decrypt == CLEAR
|| object->publicArea.objectAttributes.restricted == CLEAR)
|| !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
|| !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted))
return TPM_RCS_TYPE + RC_MakeCredential_handle;
// The credential information may not be larger than the digest size used for
// the Name of the key associated with handle.
@ -349,9 +352,9 @@ TPM2_Unseal(
// Input handle must be a data object
if(object->publicArea.type != TPM_ALG_KEYEDHASH)
return TPM_RCS_TYPE + RC_Unseal_itemHandle;
if(object->publicArea.objectAttributes.decrypt == SET
|| object->publicArea.objectAttributes.sign == SET
|| object->publicArea.objectAttributes.restricted == SET)
if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
|| IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign)
|| IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted))
return TPM_RCS_ATTRIBUTES + RC_Unseal_itemHandle;
// Command Output
// Copy data
@ -407,9 +410,7 @@ TPM2_CreateLoaded(
CreateLoaded_Out *out // OUT: output parameter list
)
{
// Local variables
TPM_RC result = TPM_RC_SUCCESS;
// These are the values used in object creation
OBJECT *parent = HandleToObject(in->parentHandle);
OBJECT *newObject;
BOOL derivation;
@ -439,7 +440,8 @@ TPM2_CreateLoaded(
// unmarshaled like other public areas. Since it is not, this command needs its
// on template that is a TPM2B that is unmarshaled as a BYTE array with a
// its own unmarshal function.
result = UnmarshalToPublic(publicArea, &in->inPublic, derivation);
result = UnmarshalToPublic(publicArea, &in->inPublic, derivation,
&labelContext);
if(result != TPM_RC_SUCCESS)
return result + RC_CreateLoaded_inPublic;
// Validate that the authorization size is appropriate
@ -459,7 +461,8 @@ TPM2_CreateLoaded(
return TPM_RCS_TYPE + RC_CreateLoaded_inPublic;
// sensitiveDataOrigin has to be CLEAR in a derived object. Since this
// is specific to a derived object, it is checked here.
if(publicArea->objectAttributes.sensitiveDataOrigin)
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT,
sensitiveDataOrigin))
return TPM_RCS_ATTRIBUTES;
// Check the reset of the attributes
result = PublicAttributesValidation(parent, publicArea);
@ -467,8 +470,7 @@ TPM2_CreateLoaded(
return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
// Process the template and sensitive areas to get the actual 'label' and
// 'context' values to be used for this derivation.
result = SetLabelAndContext(&labelContext, publicArea,
&in->inSensitive.sensitive.data);
result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data);
if(result != TPM_RC_SUCCESS)
return result;
// Set up the KDF for object generation
@ -477,7 +479,8 @@ TPM2_CreateLoaded(
scheme->details.xorr.kdf,
&parent->sensitive.sensitive.bits.b,
&labelContext.label.b,
&labelContext.context.b);
&labelContext.context.b,
TPM_MAX_DERIVATION_BITS);
// Clear the sensitive size so that the creation functions will not try
// to use this value.
in->inSensitive.sensitive.data.t.size = 0;

View File

@ -3,7 +3,7 @@
/* Object Command Support */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Object_spt.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Object_spt.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -321,13 +321,13 @@ CreateChecks(
//
// If the caller indicates that they have provided the data, then make sure that
// they have provided some data.
if((attributes.sensitiveDataOrigin == CLEAR)
if((!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
&& (sensitiveDataSize == 0))
return TPM_RCS_ATTRIBUTES;
// For an ordinary object, data can only be provided when sensitiveDataOrigin
// is CLEAR
if((parentObject != NULL)
&& (attributes.sensitiveDataOrigin == SET)
&& (IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
&& (sensitiveDataSize != 0))
return TPM_RCS_ATTRIBUTES;
switch(publicArea->type)
@ -335,8 +335,9 @@ CreateChecks(
case TPM_ALG_KEYEDHASH:
// if this is a data object (sign == decrypt == CLEAR) then the
// TPM cannot be the data source.
if(!attributes.sign && !attributes.decrypt
&& attributes.sensitiveDataOrigin)
if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)
&& IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
result = TPM_RC_ATTRIBUTES;
// comment out the next line in order to prevent a fixedTPM derivation
// parent
@ -345,13 +346,14 @@ CreateChecks(
// A restricted key symmetric key (SYMCIPHER and KEYEDHASH)
// must have sensitiveDataOrigin SET unless it has fixedParent and
// fixedTPM CLEAR.
if(attributes.restricted)
if(!attributes.sensitiveDataOrigin)
if(attributes.fixedParent || attributes.fixedTPM)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)
|| IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
result = TPM_RCS_ATTRIBUTES;
break;
default: // Asymmetric keys cannot have the sensitive portion provided
if(!attributes.sensitiveDataOrigin)
if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
result = TPM_RCS_ATTRIBUTES;
break;
}
@ -382,24 +384,33 @@ SchemeChecks(
TPM_ALG_ID scheme = TPM_ALG_NULL;
TPMA_OBJECT attributes = publicArea->objectAttributes;
TPMU_PUBLIC_PARMS *parms = &publicArea->parameters;
//
switch(publicArea->type)
{
case TPM_ALG_SYMCIPHER:
symAlgs = &parms->symDetail.sym;
// If this is a decrypt key, then only the block cipher modes (not
// SMAC) are valid. TPM_ALG_NULL is OK too. If this is a 'sign' key,
// then any mode that got through the unmarshaling is OK.
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)
&& !CryptSymModeIsValid(symAlgs->mode.sym, TRUE))
return TPM_RCS_SCHEME;
break;
case TPM_ALG_KEYEDHASH:
scheme = parms->keyedHashDetail.scheme.scheme;
// if both sign and decrypt
if(attributes.sign == attributes.decrypt)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)
== IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
{
// if both sign and decrypt are set or clear, then need
// TPM_ALG_NULL as scheme
if(scheme != TPM_ALG_NULL)
return TPM_RCS_SCHEME;
}
else if(attributes.sign && scheme != TPM_ALG_HMAC)
else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)
&& scheme != TPM_ALG_HMAC)
return TPM_RCS_SCHEME;
else if(attributes.decrypt)
else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
{
if(scheme != TPM_ALG_XOR)
return TPM_RCS_SCHEME;
@ -407,7 +418,7 @@ SchemeChecks(
// SP800-108 for this implementation. This is the only derivation
// supported by this implementation. Other implementations could
// support additional schemes. There is no default.
if(attributes.restricted)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
{
if(parms->keyedHashDetail.scheme.details.xorr.kdf
!= TPM_ALG_KDF1_SP800_108)
@ -425,13 +436,14 @@ SchemeChecks(
// if the key is both sign and decrypt, then the scheme must be
// TPM_ALG_NULL because there is no way to specify both a sign and a
// decrypt scheme in the key.
if(attributes.sign == attributes.decrypt)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)
== IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
{
// scheme must be TPM_ALG_NULL
if(scheme != TPM_ALG_NULL)
return TPM_RCS_SCHEME;
}
else if(attributes.sign)
else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign))
{
// If this is a signing key, see if it has a signing scheme
if(CryptIsAsymSignScheme(publicArea->type, scheme))
@ -446,13 +458,14 @@ SchemeChecks(
// signing key that does not have a proper signing scheme.
// This is OK if the key is not restricted and its scheme
// is TPM_ALG_NULL
if(attributes.restricted || scheme != TPM_ALG_NULL)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)
|| scheme != TPM_ALG_NULL)
return TPM_RCS_SCHEME;
}
}
else if(attributes.decrypt)
else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
{
if(attributes.restricted)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
{
// for a restricted decryption key (a parent), scheme
// is required to be TPM_ALG_NULL
@ -468,7 +481,8 @@ SchemeChecks(
return TPM_RCS_SCHEME;
}
}
if(!attributes.restricted || !attributes.decrypt)
if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)
|| !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
{
// For an asymmetric key that is not a parent, the symmetric
// algorithms must be TPM_ALG_NULL
@ -508,7 +522,9 @@ SchemeChecks(
// If this is a restricted decryption key with symmetric algorithms, then it
// is an ordinary parent (not a derivation parent). It needs to specific
// symmetric algorithms other than TPM_ALG_NULL
if(symAlgs != NULL && attributes.restricted && attributes.decrypt)
if(symAlgs != NULL
&& IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)
&& IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
{
if(symAlgs->algorithm == TPM_ALG_NULL)
return TPM_RCS_SYMMETRIC;
@ -521,7 +537,8 @@ SchemeChecks(
#endif
// If this parent is not duplicable, then the symmetric algorithms
// (encryption and hash) must match those of its parent
if(attributes.fixedParent && (parentObject != NULL))
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)
&& (parentObject != NULL))
{
if(publicArea->nameAlg != parentObject->publicArea.nameAlg)
return TPM_RCS_HASH;
@ -553,6 +570,7 @@ PublicAttributesValidation(
{
TPMA_OBJECT attributes = publicArea->objectAttributes;
TPMA_OBJECT parentAttributes = {0};
//
if(parentObject != NULL)
parentAttributes = parentObject->publicArea.objectAttributes;
if(publicArea->nameAlg == TPM_ALG_NULL)
@ -565,48 +583,56 @@ PublicAttributesValidation(
return TPM_RCS_SIZE;
// If the parent is fixedTPM (including a Primary Object) the object must have
// the same value for fixedTPM and fixedParent
if(parentObject == NULL || parentAttributes.fixedTPM == SET)
if(parentObject == NULL
|| IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM))
{
if(attributes.fixedParent != attributes.fixedTPM)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)
!= IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
return TPM_RCS_ATTRIBUTES;
}
else
{
// The parent is not fixedTPM so the object can't be fixedTPM
if(attributes.fixedTPM == SET)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
return TPM_RCS_ATTRIBUTES;
}
// See if sign and decrypt are the same
if(attributes.sign == attributes.decrypt)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)
== IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
{
// a restricted key cannot have both SET or both CLEAR
if(attributes.restricted)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
return TPM_RC_ATTRIBUTES;
// only a data object may have both sign and decrypt CLEAR
// BTW, since we know that decrypt==sign, no need to check both
if(publicArea->type != TPM_ALG_KEYEDHASH && !attributes.sign)
if(publicArea->type != TPM_ALG_KEYEDHASH
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign))
return TPM_RC_ATTRIBUTES;
}
// If the object can't be duplicated (directly or indirectly) then there
// is no justification for having encryptedDuplication SET
if(attributes.fixedTPM == SET && attributes.encryptedDuplication == SET)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)
&& IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
return TPM_RCS_ATTRIBUTES;
// If a parent object has fixedTPM CLEAR, the child must have the
// same encryptedDuplication value as its parent.
// Primary objects are considered to have a fixedTPM parent (the seeds).
if(parentObject != NULL && parentAttributes.fixedTPM == CLEAR)
if(parentObject != NULL
&& !IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM))
{
if(attributes.encryptedDuplication != parentAttributes.encryptedDuplication)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)
!= IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, encryptedDuplication))
return TPM_RCS_ATTRIBUTES;
}
// Special checks for derived objects
if((parentObject != NULL) && (parentObject->attributes.derivation == SET))
{
// A derived object has the same settings for fixedTPM as its parent
if(attributes.fixedTPM != parentAttributes.fixedTPM)
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)
!= IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM))
return TPM_RCS_ATTRIBUTES;
// A derived object is required to be fixedParent
if(!attributes.fixedParent)
if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent))
return TPM_RCS_ATTRIBUTES;
}
return SchemeChecks(parentObject, publicArea);
@ -836,7 +862,7 @@ UnwrapOuter(
}
}
// If no errors, decrypt private in place. Since this function uses CFB,
// CryptSymmetricDecrypt() will not return any errors It may fail but it will
// CryptSymmetricDecrypt() will not return any errors. It may fail but it will
// not return an error.
if(result == TPM_RC_SUCCESS)
CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits,
@ -854,7 +880,7 @@ MarshalSensitive(
TPMI_ALG_HASH nameAlg // IN:
)
{
BYTE *sizeField = buffer;; // saved so that size can be
BYTE *sizeField = buffer; // saved so that size can be
// marshaled after it is known
UINT16 retVal;
// Pad the authValue if needed
@ -1300,38 +1326,34 @@ MemoryRemoveTrailingZeros(
can end up being an Empty Buffer. */
TPM_RC
SetLabelAndContext(
TPMS_DERIVE *labelContext, // OUT: the recovered label and context
TPMT_PUBLIC *publicArea, // IN/OUT: the public area containing the
// unmarshaled template
TPMS_DERIVE *labelContext, // IN/OUT: the recovered label and context
TPM2B_SENSITIVE_DATA *sensitive // IN: the sensitive data
)
{
TPMS_DERIVE sensitiveValue;
TPM_RC result;
INT32 size;
BYTE *buff;
//
// In case neither the sensitive nor publicArea have a label or a context
labelContext->label.b.size = 0;
labelContext->context.b.size = 0;
// Unmarshal a TPMS_DERIVE from the TPM2B_SENSITIVE_DATA buffer
// If there is something to unmarshal...
if(sensitive->t.size != 0)
{
size = sensitive->t.size;
buff = sensitive->t.buffer;
result = TPMS_DERIVE_Unmarshal(labelContext, &buff, &size);
result = TPMS_DERIVE_Unmarshal(&sensitiveValue, &buff, &size);
if(result != TPM_RC_SUCCESS)
return result;
// If there was a label in the public area leave it there, otherwise, copy
// the new value
if(labelContext->label.t.size == 0)
MemoryCopy2B(&labelContext->label.b, &sensitiveValue.label.b,
sizeof(labelContext->label.t.buffer));
// if there was a context string in publicArea, it overrides
if(labelContext->context.t.size == 0)
MemoryCopy2B(&labelContext->context.b, &sensitiveValue.context.b,
sizeof(labelContext->label.t.buffer));
}
// If there is a label string in publicArea, it overrides
if(publicArea->unique.derive.label.t.size != 0)
MemoryCopy2B(&labelContext->label.b, &publicArea->unique.derive.label.b,
sizeof(labelContext->label.t.buffer));
// if there is a context string in publicArea, it overrides
if(publicArea->unique.derive.context.t.size != 0)
MemoryCopy2B(&labelContext->context.b,
&publicArea->unique.derive.context.b,
sizeof(labelContext->label.t.buffer));
return TPM_RC_SUCCESS;
}
/* 7.6.3.19 UnmarshalToPublic() */
@ -1341,9 +1363,10 @@ SetLabelAndContext(
contain a label and context that are unmarshaled into derive. */
TPM_RC
UnmarshalToPublic(
TPMT_PUBLIC *tOut, // OUT: output
TPM2B_TEMPLATE *tIn, // IN:
BOOL derivation // IN: indicates if this is for a derivation
TPMT_PUBLIC *tOut, // OUT: output
TPM2B_TEMPLATE *tIn, // IN:
BOOL derivation, // IN: indicates if this is for a derivation
TPMS_DERIVE *labelContext // OUT: label and context if derivation
)
{
BYTE *buffer = tIn->t.buffer;
@ -1353,57 +1376,33 @@ UnmarshalToPublic(
// make sure that tOut is zeroed so that there are no remnants from previous
// uses
MemorySet(tOut, 0, sizeof(TPMT_PUBLIC));
// Unmarshal a TPMT_PUBLIC but don't allow a nameAlg of TPM_ALG_NULL
result = TPMT_PUBLIC_Unmarshal(tOut, &buffer, &size, FALSE);
if((result == TPM_RC_SUCCESS) && (derivation == TRUE))
{
// Make sure that the unmarshaled value is a valid label (not too big)
if(tOut->unique.derive.label.t.size
> sizeof(tOut->unique.derive.label.t.buffer))
{
result = TPM_RC_SIZE;
}
else
{
#if ALG_ECC
// If we just unmarshaled an ECC public key, then the label value is in the
// correct spot but the context value is in the wrong place if the
// maximum ECC parameter size is larger than the largest digest.
// So, move it.
if(tOut->type == ALG_ECC_VALUE)
#if LABEL_MAX_BUFFER != MAX_ECC_KEY_BYTES
{
TPM2B_LABEL context;
// Make sure that the context is not too big
if(tOut->unique.ecc.y.t.size > sizeof(context.t.buffer))
{
result = TPM_RC_SIZE;
}
else
{
// This could probably be a direct copy because we are moving
// data to lower addresses but, just to be safe...
MemoryCopy2B(&context.b, &tOut->unique.ecc.y.b,
sizeof(context.t.buffer));
MemoryCopy2B(&tOut->unique.derive.context.b, &context.b,
sizeof(tOut->unique.derive.context.t.buffer));
}
}
#else
{
// if the label buffer and ECC key sizes match, everything is where it
// should be so nothing else to do
}
#endif // LABEL_MAX_BUFFER != MAX_ECC_KEY_BYTES
else
#endif // ALG_ECC
// For object types other than ECC, should have completed
// unmarshaling with data left in the buffer so try to unmarshal
// the remainder as a TPM2B_LABEL into the context
result = TPM2B_LABEL_Unmarshal(&tOut->unique.derive.context,
&buffer, &size);
}
}
// Unmarshal the components of the TPMT_PUBLIC up to the unique field
result = TPMI_ALG_PUBLIC_Unmarshal(&tOut->type, &buffer, &size);
if(result != TPM_RC_SUCCESS)
return result;
result = TPMI_ALG_HASH_Unmarshal(&tOut->nameAlg, &buffer, &size, FALSE);
if(result != TPM_RC_SUCCESS)
return result;
result = TPMA_OBJECT_Unmarshal(&tOut->objectAttributes, &buffer, &size);
if(result != TPM_RC_SUCCESS)
return result;
result = TPM2B_DIGEST_Unmarshal(&tOut->authPolicy, &buffer, &size);
if(result != TPM_RC_SUCCESS)
return result;
result = TPMU_PUBLIC_PARMS_Unmarshal(&tOut->parameters, &buffer, &size,
tOut->type);
if(result != TPM_RC_SUCCESS)
return result;
// No unmarshal a TPMS_DERIVE if this is for derivation
if(derivation)
result = TPMS_DERIVE_Unmarshal(labelContext, &buffer, &size);
else
// otherwise, unmarshal a TPMU_PUBLIC_ID
result = TPMU_PUBLIC_ID_Unmarshal(&tOut->unique, &buffer, &size,
tOut->type);
// Make sure the template was used up
if((result == TPM_RC_SUCCESS) && (size != 0))
result = TPM_RC_SIZE;
return result;
}
/* 7.6.3.20 ObjectSetExternal() */

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Object Command Support */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Object_spt_fp.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Object_spt_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -224,15 +224,14 @@ MemoryRemoveTrailingZeros(
TPM_RC
SetLabelAndContext(
TPMS_DERIVE *labelContext, // OUT: the recovered label and context
TPMT_PUBLIC *publicArea, // IN/OUT: the public area containing
// the unmarshaled template
TPM2B_SENSITIVE_DATA *sensitive // IN: the sensitive data
);
TPM_RC
UnmarshalToPublic(
TPMT_PUBLIC *tOut, // OUT: output
TPM2B_TEMPLATE *tIn, // IN:
BOOL derivation // IN: indicates if this is for a derivation
BOOL derivation, // IN: indicates if this is for a derivation
TPMS_DERIVE *labelContext // OUT: label and context if derivation
);
void
ObjectSetHierarchy(

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: PCR.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: PCR.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -792,7 +792,7 @@ PCRRead(
pcr++;
}
// Exit inner loop
break;;
break;
}
// Need the size of each digest
digest->digests[digest->count].t.size =

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Instance data for the Platform module. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: PlatformData.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: PlatformData.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017. */
/* */
/********************************************************************************/
@ -72,10 +72,6 @@
canceled */
extern int s_isCanceled;
#include <time.h>
typedef struct {
time_t tv_sec; // Seconds - >= 0
long tv_nsec; // Nanoseconds - [0, 999999999]
} timespec_t;
#ifndef HARDWARE_CLOCK
/* This is the value returned the last time that the system clock was read. This is only relevant
for a simulator or virtual TPM. */

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Platform_fp.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Platform_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -89,7 +89,8 @@ _plat__ClearCancel(
/* C.8.2. From Clock.c */
/* C.8.2.1. _plat__TimerReset() */
/* This function sets current system clock time as t0 for counting TPM time. This function is called
at a power on event to reset the clock. */
at a power on event to reset the clock. When the clock is reset, the indication that the clock
was stopped is also set. */
LIB_EXPORT void
_plat__TimerReset(
void

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: PropertyCap.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: PropertyCap.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -202,13 +202,13 @@ TPMPropertyIsDefined(
{
TPMA_MEMORY att;
UINT32 u32;
} attributes = {{0}};
attributes.att.sharedNV = SET;
attributes.att.objectCopiedToRam = SET;
// Copy the bytes of the TPMA_MEMORY to the 32 bit integer assuming
// that the structure is going to be packed and, because the union
// contains a UINT32, it will be properly aligned. Note: this will
// get and could get byte swapped if the CPU is little-endian.
} attributes = {0};
SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, sharedNV);
SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, objectCopiedToRam);
// Note: For a LSb0 machine, the bits in a bit field are in the correct
// order even if the machine is MSB0. For a MSb0 machine, a TPMA will
// be an integer manipulated by masking (NO_BIT_FIELD_STRUCTURES will
// be defined) so the bits are manipulated correctly.
*value = attributes.u32;
break;
}
@ -393,41 +393,52 @@ TPMPropertyIsDefined(
case TPM_PT_PERMANENT:
// TPMA_PERMANENT
{
TPMA_PERMANENT flags = {0};
union {
TPMA_PERMANENT attr;
UINT32 u32;
} flags = {0};
if(gp.ownerAuth.t.size != 0)
flags.ownerAuthSet = SET;
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, ownerAuthSet);
if(gp.endorsementAuth.t.size != 0)
flags.endorsementAuthSet = SET;
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, endorsementAuthSet);
if(gp.lockoutAuth.t.size != 0)
flags.lockoutAuthSet = SET;
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, lockoutAuthSet);
if(gp.disableClear)
flags.disableClear = SET;
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, disableClear);
if(gp.failedTries >= gp.maxTries)
flags.inLockout = SET;
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, inLockout);
// In this implementation, EPS is always generated by TPM
flags.tpmGeneratedEPS = SET;
// Note: Different compilers may require a different method to cast
// a bit field structure to a UINT32.
*value = *(UINT32 *)&flags;
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, tpmGeneratedEPS);
// Note: For a LSb0 machine, the bits in a bit field are in the correct
// order even if the machine is MSB0. For a MSb0 machine, a TPMA will
// be an integer manipulated by masking (NO_BIT_FIELD_STRUCTURES will
// be defined) so the bits are manipulate correctly.
*value = flags.u32;
break;
}
case TPM_PT_STARTUP_CLEAR:
// TPMA_STARTUP_CLEAR
{
TPMA_STARTUP_CLEAR flags = {0};
union {
TPMA_STARTUP_CLEAR attr;
UINT32 u32;
} flags = {0};
//
if(g_phEnable)
flags.phEnable = SET;
SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnable);
if(gc.shEnable)
flags.shEnable = SET;
SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, shEnable);
if(gc.ehEnable)
flags.ehEnable = SET;
SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, ehEnable);
if(gc.phEnableNV)
flags.phEnableNV = SET;
SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnableNV);
if(g_prevOrderlyState != SU_NONE_VALUE)
flags.orderly = SET;
// Note: Different compilers may require a different method to cast
// a bit field structure to a UINT32.
*value = *(UINT32 *)&flags;
SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, orderly);
// Note: For a LSb0 machine, the bits in a bit field are in the correct
// order even if the machine is MSB0. For a MSb0 machine, a TPMA will
// be an integer manipulated by masking (NO_BIT_FIELD_STRUCTURES will
// be defined) so the bits are manipulate correctly.
*value = flags.u32;
break;
}
case TPM_PT_HR_NV_INDEX:

View File

@ -3,7 +3,7 @@
/* Manage the session context counter */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Session.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Session.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -199,9 +199,9 @@ SessionIsSaved(
return FALSE;
return TRUE;
}
/* 8.9.5.3 SequenceNumbereForSavedContextIsValid() */
/* 8.9.5.3 SequenceNumberForSavedContextIsValid() */
BOOL
SequenceNumbereForSavedContextIsValid(
SequenceNumberForSavedContextIsValid(
TPMS_CONTEXT *context // IN: pointer to a context
// structure to be validated
)

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Session Commands */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: SessionCommands.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: SessionCommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -97,7 +97,7 @@ TPM2_StartAuthSession(
return TPM_RCS_HANDLE + RC_StartAuthSession_tpmKey;
// HMAC session input handle check.
// tpmKey should be a decryption key
if(tpmKey->publicArea.objectAttributes.decrypt != SET)
if(!IS_ATTRIBUTE(tpmKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
return TPM_RCS_ATTRIBUTES + RC_StartAuthSession_tpmKey;
// Secret Decryption. A TPM_RC_VALUE, TPM_RC_KEY or Unmarshal errors
// may be returned at this point

View File

@ -3,7 +3,7 @@
/* Process the Authorization Sessions */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: SessionProcess.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: SessionProcess.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -79,6 +79,7 @@ IsDAExempted(
)
{
BOOL result = FALSE;
//
switch(HandleGetType(handle))
{
case TPM_HT_PERMANENT:
@ -90,13 +91,14 @@ IsDAExempted(
// into an object slot and assigned a transient handle.
case TPM_HT_TRANSIENT:
{
result = (ObjectGetPublicAttributes(handle).noDA == SET);
TPMA_OBJECT attributes = ObjectGetPublicAttributes(handle);
result = IS_ATTRIBUTE(attributes, TPMA_OBJECT, noDA);
break;
}
case TPM_HT_NV_INDEX:
{
NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL);
result = (nvIndex->publicArea.attributes.TPMA_NV_NO_DA == SET);
result = IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, NO_DA);
break;
}
case TPM_HT_PCR:
@ -120,6 +122,7 @@ IncrementLockout(
TPM_HANDLE handle = s_associatedHandles[sessionIndex];
TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex];
SESSION *session = NULL;
//
// Don't increment lockout unless the handle associated with the session
// is DA protected or the session is bound to a DA protected entity.
if(sessionHandle == TPM_RS_PW)
@ -232,7 +235,8 @@ IsPolicySessionRequired(
if(type == TPM_HT_TRANSIENT)
{
OBJECT *object = HandleToObject(s_associatedHandles[sessionIndex]);
if(object->publicArea.objectAttributes.adminWithPolicy == CLEAR)
if(!IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT,
adminWithPolicy))
return FALSE;
}
return TRUE;
@ -268,6 +272,7 @@ IsAuthValueAvailable(
)
{
BOOL result = FALSE;
//
switch(HandleGetType(handle))
{
case TPM_HT_PERMANENT:
@ -302,7 +307,10 @@ IsAuthValueAvailable(
// handle changed.
{
OBJECT *object;
TPMA_OBJECT attributes;
//
object = HandleToObject(handle);
attributes = object->publicArea.objectAttributes;
// authValue is always available for a sequence object.
// An alternative for this is to SET
// object->publicArea.objectAttributes.userWithAuth when the
@ -317,10 +325,9 @@ IsAuthValueAvailable(
// 1. userWithAuth bit is SET, or
// 2. ADMIN role is required
if(object->attributes.publicOnly == CLEAR
&& (object->publicArea.objectAttributes.userWithAuth == SET
&& (IS_ATTRIBUTE(attributes, TPMA_OBJECT, userWithAuth)
|| (CommandAuthRole(commandIndex, sessionIndex) == AUTH_ADMIN
&& object->publicArea.objectAttributes.adminWithPolicy
== CLEAR)))
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, adminWithPolicy))))
result = TRUE;
}
break;
@ -330,12 +337,13 @@ IsAuthValueAvailable(
NV_REF locator;
NV_INDEX *nvIndex = NvGetIndexInfo(handle, &locator);
TPMA_NV nvAttributes;
//
pAssert(nvIndex != 0);
nvAttributes = nvIndex->publicArea.attributes;
if(IsWriteOperation(commandIndex))
{
// AuthWrite can't be set for a PIN index
if(nvAttributes.TPMA_NV_AUTHWRITE == SET)
if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHWRITE))
result = TRUE;
}
else
@ -347,15 +355,15 @@ IsAuthValueAvailable(
|| IsNvPinPassIndex(nvAttributes))
{
NV_PIN pin;
if(nvAttributes.TPMA_NV_WRITTEN != SET)
if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN))
break; // return false
// get the index values
pin.intVal = NvGetUINT64Data(nvIndex, locator);
if(pin.pin.pinCount < pin.pin.pinLimit)
result = TRUE;
}
// For non-PIN Indices, need to allow use of the authValue
else if(nvAttributes.TPMA_NV_AUTHREAD == SET)
// For non-PIN Indexes, need to allow use of the authValue
else if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHREAD))
result = TRUE;
}
}
@ -371,6 +379,8 @@ IsAuthValueAvailable(
}
return result;
}
/* 6.4.3.6 IsAuthPolicyAvailable() */
/* This function indicates if an authPolicy is available and allowed. */
/* This function does not check that the handle reference is valid or if the entity is in an enabled
hierarchy. Those checks are assumed to have been performed during the handle unmarshaling. */
@ -385,6 +395,7 @@ IsAuthPolicyAvailable(
)
{
BOOL result = FALSE;
//
switch(HandleGetType(handle))
{
case TPM_HT_PERMANENT:
@ -433,6 +444,7 @@ IsAuthPolicyAvailable(
{
NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL);
TPMA_NV attributes = nvIndex->publicArea.attributes;
//
// If the policy size is not zero, check if policy can be used.
if(nvIndex->publicArea.authPolicy.t.size != 0)
{
@ -444,12 +456,12 @@ IsAuthPolicyAvailable(
// attributes.
else if(IsWriteOperation(commandIndex))
{
if(IsNv_TPMA_NV_POLICYWRITE(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICYWRITE))
result = TRUE;
}
else
{
if(IsNv_TPMA_NV_POLICYREAD(attributes))
if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICYREAD))
result = TRUE;
}
}
@ -609,13 +621,14 @@ GetCpHash(
)
{
TPM2B_DIGEST *cpHash = GetCpHashPointer(command, hashAlg);
//
pAssert(cpHash->t.size != 0);
return cpHash;
}
/* 6.4.4.6 CompareTemplateHash() */
/* This function computes the template hash and compares it to the session templateHash. It is the
hash of the second parameter assuming that the command is TPM2_Create(), TPM2_CreatePrimary(), or
TPM2_Derive() */
TPM2_CreateLoaded() */
static BOOL
CompareTemplateHash(
COMMAND *command, // IN: parsing structure
@ -824,7 +837,7 @@ CheckSessionHMAC(
{
TPM2B_DIGEST hmac; // authHMAC for comparing
// Compute authHMAC
ComputeCommandHMAC(command, sessionIndex, &hmac);
ComputeCommandHMAC(command, sessionIndex, &hmac);
// Compare the input HMAC with the authHMAC computed above.
if(!MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &hmac.b))
{
@ -918,7 +931,7 @@ CheckPolicyAuthSession(
BYTE sessionLocality[sizeof(TPMA_LOCALITY)];
BYTE *buffer = sessionLocality;
// Get existing locality setting in canonical form
sessionLocality[0] = 0; // Code analysis says that this is not initialized
sessionLocality[0] = 0;
TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL);
// See if the locality has been set
if(sessionLocality[0] != 0)
@ -975,7 +988,7 @@ CheckPolicyAuthSession(
// Get the index data
nvIndex = NvGetIndexInfo(s_associatedHandles[sessionIndex], &locator);
// Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired state
if((IsNv_TPMA_NV_WRITTEN(nvIndex->publicArea.attributes))
if((IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
!= (session->attributes.nvWrittenState == SET))
return TPM_RC_POLICY_FAIL;
}
@ -997,6 +1010,7 @@ RetrieveSessionData(
int i;
TPM_RC result;
SESSION *session;
TPMA_SESSION sessionAttributes;
TPM_HT sessionType;
INT32 sessionIndex;
TPM_RC errorIndex;
@ -1039,15 +1053,16 @@ RetrieveSessionData(
&command->authSize);
if(result != TPM_RC_SUCCESS)
return result + errorIndex;
sessionAttributes = s_attributes[sessionIndex];
if(s_sessionHandles[sessionIndex] == TPM_RS_PW)
{
// A PWAP session needs additional processing.
// Can't have any attributes set other than continueSession bit
if(s_attributes[sessionIndex].encrypt
|| s_attributes[sessionIndex].decrypt
|| s_attributes[sessionIndex].audit
|| s_attributes[sessionIndex].auditExclusive
|| s_attributes[sessionIndex].auditReset)
if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt)
|| IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt)
|| IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit)
|| IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive)
|| IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset))
return TPM_RCS_ATTRIBUTES + errorIndex;
// The nonce size must be zero.
if(s_nonceCaller[sessionIndex].t.size != 0)
@ -1073,9 +1088,9 @@ RetrieveSessionData(
return TPM_RCS_HANDLE + errorIndex;
}
// If the session is used for parameter encryption or audit as well, set
// the corresponding indices.
// the corresponding Indexes.
// First process decrypt.
if(s_attributes[sessionIndex].decrypt)
if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt))
{
// Check if the commandCode allows command parameter encryption.
if(DecryptSize(command->index) == 0)
@ -1091,7 +1106,7 @@ RetrieveSessionData(
s_decryptSessionIndex = sessionIndex;
}
// Now process encrypt.
if(s_attributes[sessionIndex].encrypt)
if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt))
{
// Check if the commandCode allows response parameter encryption.
if(EncryptSize(command->index) == 0)
@ -1107,7 +1122,7 @@ RetrieveSessionData(
s_encryptSessionIndex = sessionIndex;
}
// At last process audit.
if(s_attributes[sessionIndex].audit)
if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit))
{
// Audit attribute can only appear in one session.
if(s_auditSessionIndex != UNDEFINED_INDEX)
@ -1119,12 +1134,12 @@ RetrieveSessionData(
// If this is a reset of the audit session, or the first use
// of the session as an audit session, it doesn't matter what
// the exclusive state is. The session will become exclusive.
if(s_attributes[sessionIndex].auditReset == CLEAR
if(!IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset)
&& session->attributes.isAudit == SET)
{
// Not first use or reset. If auditExlusive is SET, then this
// session must be the current exclusive session.
if(s_attributes[sessionIndex].auditExclusive == SET
if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive)
&& g_exclusiveAuditSession != s_sessionHandles[sessionIndex])
return TPM_RC_EXCLUSIVE;
}
@ -1294,7 +1309,7 @@ CheckAuthSession(
result = CheckPWAuthSession(sessionIndex);
else
result = CheckSessionHMAC(command, sessionIndex);
// Do processing for PIN indices are only three possibilities for 'result' at
// Do processing for PIN Indexes are only three possibilities for 'result' at
// this point.
// TPM_RC_SUCCESS
// TPM_RC_AUTH_FAIL
@ -1312,7 +1327,8 @@ CheckAuthSession(
nvAttributes = nvIndex->publicArea.attributes;
// If this is a PIN FAIL index and the value has been written
// then we can update the counter (increment or clear)
if(IsNvPinFailIndex(nvAttributes) && nvAttributes.TPMA_NV_WRITTEN == SET)
if(IsNvPinFailIndex(nvAttributes)
&& IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN))
{
pinData.intVal = NvGetUINT64Data(nvIndex, locator);
if(result != TPM_RC_SUCCESS)
@ -1327,8 +1343,8 @@ CheckAuthSession(
// would not get here because the authorization value would not
// be available and the TPM would have returned before it gets here
else if(IsNvPinPassIndex(nvAttributes)
&& nvAttributes.TPMA_NV_WRITTEN == SET
&& result == TPM_RC_SUCCESS)
&& IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)
&& result == TPM_RC_SUCCESS)
{
// If the access is valid, then increment the use counter
pinData.intVal = NvGetUINT64Data(nvIndex, locator);
@ -1422,9 +1438,9 @@ ParseSessionBuffer(
if(s_associatedHandles[sessionIndex] == TPM_RH_UNASSIGNED)
return TPM_RCS_HANDLE + errorIndex;
// a password session can't be audit, encrypt or decrypt
if(s_attributes[sessionIndex].audit == SET
|| s_attributes[sessionIndex].encrypt == SET
|| s_attributes[sessionIndex].decrypt == SET)
if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)
|| IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt)
|| IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt))
return TPM_RCS_ATTRIBUTES + errorIndex;
session = NULL;
}
@ -1446,7 +1462,7 @@ ParseSessionBuffer(
return result;
}
// If this session is for auditing, make sure the cpHash is computed.
if(s_attributes[sessionIndex].audit)
if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit))
ComputeCpHash(command, session->authHashAlg);
}
// if the session has an associated handle, check the authorization
@ -1460,9 +1476,9 @@ ParseSessionBuffer(
{
// a session that is not for authorization must either be encrypt,
// decrypt, or audit
if(s_attributes[sessionIndex].audit == CLEAR
&& s_attributes[sessionIndex].encrypt == CLEAR
&& s_attributes[sessionIndex].decrypt == CLEAR)
if(!IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)
&& !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt)
&& !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt))
return TPM_RCS_ATTRIBUTES + errorIndex;
// no authValue included in any of the HMAC computations
pAssert(session != NULL);
@ -1691,7 +1707,7 @@ UpdateAuditSessionStatus(
continue;
session = SessionGet(s_sessionHandles[i]);
// If a session is used for audit
if(s_attributes[i].audit == SET)
if(IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, audit))
{
// An audit session has been found
auditSession = s_sessionHandles[i];
@ -1699,7 +1715,7 @@ UpdateAuditSessionStatus(
// the auditSetting bits indicate a reset, initialize it and set
// it to be the exclusive session
if(session->attributes.isAudit == CLEAR
|| s_attributes[i].auditReset == SET)
|| IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditReset))
{
InitAuditSession(session);
g_exclusiveAuditSession = auditSession;
@ -1714,11 +1730,11 @@ UpdateAuditSessionStatus(
// Report audit session exclusivity.
if(g_exclusiveAuditSession == auditSession)
{
s_attributes[i].auditExclusive = SET;
SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive);
}
else
{
s_attributes[i].auditExclusive = CLEAR;
CLEAR_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive);
}
// Extend audit log.
Audit(command, session);
@ -1761,8 +1777,8 @@ ComputeResponseHMAC(
// s_associatedHandles[] value for the session is now set to TPM_RH_NULL so
// this will return the authValue associated with TPM_RH_NULL and that is
// and empty buffer.
// Get the authValue with trailing zeros removed
TPM2B_AUTH authValue;
// Get the authValue with trailing zeros removed
EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue);
// Add it to the key
MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer));
@ -1802,7 +1818,7 @@ UpdateInternalSession(
// If nonce is rolling in a policy session, the policy related data
// will be re-initialized.
if(HandleGetType(s_sessionHandles[i]) == TPM_HT_POLICY_SESSION
&& s_attributes[i].continueSession != CLEAR)
&& IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession))
{
// When the nonce rolls it starts a new timing interval for the
// policy session.
@ -1928,7 +1944,7 @@ BuildResponseSession(
// to keep track of the closed sessions.
if(s_sessionHandles[i] == TPM_RS_PW)
{
s_attributes[i].continueSession = SET;
SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession);
responseAuth.t.size = 0;
nonceTPM = (TPM2B_NONCE *)&responseAuth;
}
@ -1947,7 +1963,7 @@ BuildResponseSession(
command->authSize += TPM2B_DIGEST_Marshal(&responseAuth,
&command->responseBuffer,
NULL);
if(s_attributes[i].continueSession == CLEAR)
if(!IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession))
SessionFlush(s_sessionHandles[i]);
}
}

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Session_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: Session_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -75,7 +75,7 @@ SessionIsSaved(
TPM_HANDLE handle // IN: session handle
);
BOOL
SequenceNumbereForSavedContextIsValid(
SequenceNumberForSavedContextIsValid(
TPMS_CONTEXT *context // IN: pointer to a context structure to be
// validated
);

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: SigningCommands.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: SigningCommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -73,7 +73,7 @@ TPM2_VerifySignature(
TPMI_RH_HIERARCHY hierarchy;
// Input Validation
// The object to validate the signature must be a signing key.
if(signObject->publicArea.objectAttributes.sign != SET)
if(!IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, sign))
return TPM_RCS_ATTRIBUTES + RC_VerifySignature_keyHandle;
// Validate Signature. TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE
// error may be returned by CryptCVerifySignatrue()
@ -123,7 +123,7 @@ TPM2_Sign(
return TPM_RCS_SCHEME + RC_Sign_inScheme;
// If validation is provided, or the key is restricted, check the ticket
if(in->validation.digest.t.size != 0
|| signObject->publicArea.objectAttributes.restricted == SET)
|| IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, restricted))
{
// Compute and compare ticket
TicketComputeHashCheck(in->validation.hierarchy,

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: SupportLibraryFunctionPrototypes_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: SupportLibraryFunctionPrototypes_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,13 +55,12 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
#ifndef SUPPORTLIBRARYFUNCTIONPROTOTYPES_FP_H
#define SUPPORTLIBRARYFUNCTIONPROTOTYPES_FP_H
#ifndef SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H
#define SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H
/* This file contains the function prototypes for the functions that need to be present in the
selected match library. For each function listed, there should be a small stub function. That
@ -69,8 +68,6 @@
function will only need to do a format conversion between the TPM big number and the support
library big number. The TPM big number format was chosen to make this relatively simple and
fast. */
#ifndef SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H
#define SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H
LIB_EXPORT int SupportLibInit(void);
/* MathLibraryCompatibililtyCheck() This function is only used during development to make sure that
the library that is being referenced is using the same size of data structures as the TPM. */
@ -79,53 +76,49 @@ MathLibraryCompatibilityCheck(
void
);
/* 5.19.2 BnModMult() */
/* Does multiply and divide returning the remainder of the divide. */
/* Does multiply op1 * op2 and divide by modulus returning the remainder of the divide. */
LIB_EXPORT BOOL
BnModMult(bigNum result, bigConst op1, bigConst op2, bigConst modulus);
/* 5.19.3 BnMult() */
/* Multiplies two numbers */
/* Multiplies two numbers and returns the result */
LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier);
/* 5.19.4 BnDiv() */
/* This function divides two bigNum values. The function always returns TRUE. */
/* This function divides two bigNum values. The function returns FALSE if there is an error in the
operation. */
LIB_EXPORT BOOL BnDiv(bigNum quotient, bigNum remainder,
bigConst dividend, bigConst divisor);
/* 5.19.5 BnMod() */
#define BnMod(a, b) BnDiv(NULL, (a), (a), (b))
#ifdef TPM_ALG_RSA
/* 5.19.6 BnGcd() */
/* Get the greatest common divisor of two numbers */
/* Get the greatest common divisor of two numbers. This function is only needed when the TPM
implements RSA. */
LIB_EXPORT BOOL BnGcd(bigNum gcd, bigConst number1, bigConst number2);
/* 5.19.7 BnModExp() */
/* Do modular exponentiation using bigNum values. */
/* Do modular exponentiation using bigNum values. This function is only needed when the TPM
implements RSA. */
LIB_EXPORT BOOL BnModExp(bigNum result, bigConst number,
bigConst exponent, bigConst modulus);
/* 5.19.8 BnModInverse() */
/* Modular multiplicative inverse */
/* Modular multiplicative inverse. This function is only needed when the TPM implements RSA. */
LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number,
bigConst modulus);
#endif // TPM_ALG_RSA
#ifdef TPM_ALG_ECC
/* 5.19.9 BnEccModMult() */
/* This function does a point multiply of the form R = [d]S */
/* Return Value Meaning */
/* FALSE failure in operation; treat as result being point at infinity */
/* This function does a point multiply of the form R = [d]S. A return of FALSE indicates that the
result was the point at infinity. This function is only needed if the TPM supports ECC. */
LIB_EXPORT BOOL BnEccModMult(bigPoint R, pointConst S, bigConst d, bigCurve E);
/* 5.19.10 BnEccModMult2() */
/* This function does a point multiply of the form R = [d]S + [u]Q */
/* Return Value Meaning */
/* FALSE failure in operation; treat as result being point at infinity */
/* This function does a point multiply of the form R = [d]S + [u]Q. A return of FALSE indicates that
the result was the point at infinity. This function is only needed if the TPM supports ECC */
LIB_EXPORT BOOL BnEccModMult2(bigPoint R, pointConst S, bigConst d,
pointConst Q, bigConst u, bigCurve E);
/* 5.19.11 BnEccAdd() */
/* This function does a point add R = S + Q */
/* Return Values Meaning */
/* FALSE failure in operation; treat as result being point at infinity */
/* This function does a point add R = S + Q. A return of FALSE indicates that the result was the
point at infinity. This function is only needed if the TPM supports ECC. */
LIB_EXPORT BOOL BnEccAdd(bigPoint R, pointConst S, pointConst Q, bigCurve E);
/* 5.19.12 BnCurveInitialize() */
/* This function is used to initialize the pointers of a bnCurve_t structure. The structure is a set
of pointers to bigNum values. The curve-dependent values are set by a different function. */
of pointers to bigNum values. The curve-dependent values are set by a different function. This
function is only needed if the TPM supports ECC.*/
LIB_EXPORT bigCurve BnCurveInitialize(bigCurve E, TPM_ECC_CURVE curveId);
#endif // TPM_ALG_ECC
#endif
#endif

View File

@ -3,7 +3,7 @@
/* Symmetric Commands */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: SymmetricCommands.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: SymmetricCommands.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -259,10 +259,12 @@ TPM2_HMAC(
if(publicArea->type != TPM_ALG_KEYEDHASH)
return TPM_RCS_TYPE + RC_HMAC_handle;
// and that it is unrestricted
if(publicArea->objectAttributes.restricted == SET)
if (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
// if(publicArea->objectAttributes.restricted == SET) kgold
return TPM_RCS_ATTRIBUTES + RC_HMAC_handle;
// and that it is a signing key
if(publicArea->objectAttributes.sign != SET)
if (!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
// if(publicArea->objectAttributes.sign != SET) kgold
return TPM_RCS_KEY + RC_HMAC_handle;
// See if the key has a default
if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL)
@ -291,3 +293,56 @@ TPM2_HMAC(
return TPM_RC_SUCCESS;
}
#endif // CC_HMAC
#include "Tpm.h"
#include "MAC_fp.h"
#if defined TPM_CC_MAC // Conditional expansion of this file
/* Error Returns Meaning */
/* TPM_RC_ATTRIBUTES key referenced by handle is a restricted key */
/* TPM_RC_KEY handle does not reference a signing key */
/* TPM_RC_TYPE key referenced by handle is not an HMAC key */
/* TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of the object
referenced by handle */
TPM_RC
TPM2_MAC(
MAC_In *in, // IN: input parameter list
MAC_Out *out // OUT: output parameter list
)
{
OBJECT *keyObject;
HMAC_STATE state;
TPMT_PUBLIC *publicArea;
TPM_RC result;
// Input Validation
// Get MAC key object and public area pointers
keyObject = HandleToObject(in->handle);
publicArea = &keyObject->publicArea;
// If the key is not able to do a MAC, indicate that the handle selects an
// object that can't do a MAC
result = CryptSelectMac(publicArea, &in->inScheme);
if(result == TPM_RCS_TYPE)
return TPM_RCS_TYPE + RC_MAC_handle;
// If there is another error type, indicate that the scheme and key are not
// compatible
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result, RC_MAC_inScheme);
// Make sure that the key is not restricted
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
return TPM_RCS_ATTRIBUTES + RC_MAC_handle;
// and that it is a signing key
if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
return TPM_RCS_KEY + RC_MAC_handle;
// Command Output
out->outMAC.t.size = CryptMacStart(&state, &publicArea->parameters,
in->inScheme,
&keyObject->sensitive.sensitive.any.b);
// If the mac can't start, treat it as a fatal error
if(out->outMAC.t.size == 0)
return TPM_RC_FAILURE;
CryptDigestUpdate2B(&state.hashState, &in->buffer.b);
// If the MAC result is not what was expected, it is a fatal error
if(CryptHmacEnd2B(&state, &out->outMAC.b) != out->outMAC.t.size)
return TPM_RC_FAILURE;
return TPM_RC_SUCCESS;
}
#endif // CC_MAC

View File

@ -3,7 +3,7 @@
/* Structures and data definitions for the symmetric tests */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: SymmetricTest.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: SymmetricTest.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -72,7 +72,7 @@
#define _SYMMETRIC_TEST_H
#include "SymmetricTestData.h"
/* 10.1.11.2 Structures */
/* 10.1.11.2 Symmetric Test Structures */
const SYMMETRIC_TEST_VECTOR c_symTestValues[NUM_SYMS] = {
#undef COMMA

View File

@ -3,7 +3,7 @@
/* Process the commands */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: TPMCmdp.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: TPMCmdp.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -216,7 +216,8 @@ _rpc__Signal_HashEnd(
_TPM_Hash_End();
return;
}
/* Command interface Entry of a RPC call */
/* D.5.3.10. rpc_Send_Command() */
/* This is the interface to the TPM code. */
void
_rpc__Send_Command(
unsigned char locality,

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: TcpServer.c 812 2016-11-16 21:28:29Z kgoldman $ */
/* $Id: TcpServer.c 1048 2017-07-20 20:28:26Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -66,9 +66,12 @@
#include "TpmBuildSwitches.h"
#include <stdio.h>
#ifdef TPM_WINDOWS
#include <windows.h>
#include <winsock.h>
#else
typedef int SOCKET
#endif
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Functions used for ticket computations. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Ticket.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: Ticket.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -102,7 +102,7 @@ TicketComputeVerified(
TPMT_TK_VERIFIED *ticket // OUT: verified ticket
)
{
TPM2B_AUTH *proof;
TPM2B_PROOF *proof;
HMAC_STATE hmacState;
//
// Fill in ticket fields
@ -137,7 +137,7 @@ TicketComputeAuth(
TPMT_TK_AUTH *ticket // OUT: Created ticket
)
{
TPM2B_AUTH *proof;
TPM2B_PROOF *proof;
HMAC_STATE hmacState;
//
// Get proper proof
@ -182,7 +182,7 @@ TicketComputeHashCheck(
TPMT_TK_HASHCHECK *ticket // OUT: Created ticket
)
{
TPM2B_AUTH *proof;
TPM2B_PROOF *proof;
HMAC_STATE hmacState;
//
// Get proper proof
@ -213,7 +213,7 @@ TicketComputeCreation(
TPMT_TK_CREATION *ticket // OUT: created ticket
)
{
TPM2B_AUTH *proof;
TPM2B_PROOF *proof;
HMAC_STATE hmacState;
// Get proper proof
proof = HierarchyGetProof(hierarchy);

View File

@ -3,7 +3,7 @@
/* Functions relating to the TPM's time functions */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Time.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Time.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -124,7 +124,7 @@ TimeStartup(
an NV write occurs, then go.safe is SET. */
void
TimeClockUpdate(
UINT64 newTime
UINT64 newTime // IN: New time value in mS.
)
{
#define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1)

View File

@ -3,7 +3,7 @@
/* Root header file for building any TPM.lib code */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Tpm.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Tpm.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -59,14 +59,14 @@
/* */
/********************************************************************************/
/* 5.20 Tpm.h */
/* 5.19 Tpm.h */
/* Root header file for building any TPM.lib code */
#ifndef _TPM_H_
#define _TPM_H_
#include "Implementation.h"
#include "LibSupport.h" // Types from the library. These need to come before
/* Global.h because some of the structures in that file depend on the structures used by the
cryptographic libraries. */
#include "LibSupport.h" /* Types from the library. These need to come before Global.h
because some of the structures in that file depend on the
structures used by the cryptographic libraries. */
#include "GpMacros.h" // Define additional macros
#include "Global.h" // Define other TPM types
#include "InternalRoutines.h" // Function prototypes

View File

@ -3,7 +3,7 @@
/* Build Switches */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: TpmBuildSwitches.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: TpmBuildSwitches.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -151,13 +151,13 @@
#endif // SIMULATION
#ifndef NDEBUG
/* In some cases, the relationship between two values may be dependent on things that change based
on various selections like the chosen crypto libraries. It is possible that these selections will
result in incompatible settings. These are often detectable by the compiler but it isn't always
possible to do the check in the preprocessor code. For example, when the check requires use of
'sizeof()' then the preprocessor can't do the comparison. For these cases, we include a special
macro that, depending on the compiler will generate a warning to indicate if the check always
passes or always fails because it involves fixed constants. To run these checks, define
COMPILER_CHECKS. */
on various selections like the chosen cryptographic libraries. It is possible that these
selections will result in incompatible settings. These are often detectable by the compiler but
it isn't always possible to do the check in the preprocessor code. For example, when the check
requires use of 'sizeof()' then the preprocessor can't do the comparison. For these cases, we
include a special macro that, depending on the compiler will generate a warning to indicate if
the check always passes or always fails because it involves fixed constants. To run these checks,
define COMPILER_CHECKS. */
#ifndef COMPILER_CHECKS
//# define COMPILER_CHECKS
#endif
@ -168,17 +168,17 @@
#ifndef RUNTIME_SIZE_CHECKS
#define RUNTIME_SIZE_CHECKS
#endif
/* If doing debug, can set the DRBG to print out the intermediate test values. Before enabling this,
make sure that the dbgDumpMemBlock() function has been added someplace (preferably, somewhere in
CryptRand.c) */
#ifndef DRBG_DEBUG_PRINT
//# define DRBG_DEBUG_PRINT
#endif
/* If an assertion event it not going to produce any trace information (function and line number)
then define NO_FAIL_TRACE */
#ifndef NO_FAIL_TRACE
# define NO_FAIL_TRACE
//# define NO_FAIL_TRACE
#endif
#endif // NDEBUG
/* If the implementation is going to give lockout time credit for time up to the last orderly
@ -186,5 +186,30 @@
#ifndef ACCUMULATE_SELF_HEAL_TIMER
#define ACCUMULATE_SELF_HEAL_TIMER
#endif // ACCUMULATE_SELF_HEAL_TIMER
/* If the implementation is to compute the sizes of the proof and primary seed size values based on
the implemented algorithms, then use this define. */
#ifndef USE_SPEC_COMPLIANT_PROOFS
#define USE_SPEC_COMPLIANT_PROOFS
#endif
/* Comment this out to allow compile to continue even though the chosen proof values do not match
the compliant values. This is written so that someone would have to proactively ignore errors. */
#ifndef SKIP_PROOF_ERRORS
//#define SKIP_PROOF_ERRORS
#endif
/* This define is used to eliminate the use of bit-fields. It can be enable for big- or
little-endian machines but is required of big-endian system that number bits in registers from
left to right. Little-endian machines number from right to left with the least significant bit
having assigned a bit number of 0. These are LSb0() machines (they are also little-endian so they
are also least-significant byte 0 (LSB0) machines. Big-endian (MSB0) machines may number in
either direction (MSb0() or LSb0()). For an MSB0+MSb0() machine this value should be defined */
#ifndef NO_BIT_FIELD_STRUCTURES
//# define NO_BIT_FIELD_STRUCTURES
#endif
/* Change these definitions to turn all algorithms or commands ON or OFF. That is, to turn all
algorithms on, set ALG_NO to YES. This is mostly useful as a debug feature. */
#define ALG_YES YES
#define ALG_NO NO
#define CC_YES YES
#define CC_NO NO
#endif // _TPM_BUILD_SWITCHES_H_

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: TpmFail.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: TpmFail.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -194,10 +194,10 @@ TpmFail(
// On a 64-bit machine, this may truncate the address of the string
// of the function name where the error occurred.
#ifndef NO_FAIL_TRACE
s_failFunction = *(UINT32*)&function;
s_failFunction = *(UINT32 *)&function;
s_failLine = line;
#else
s_failFunction = 0; /* kgold was NULL */
s_failFunction = (UINT32)NULL;
s_failLine = 0;
#endif
s_failCode = code;

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
/* Parameter Unmarshaling */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Unmarshal.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Unmarshal.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* (c) Copyright IBM Corporation 2015, 2016 */
/* */
@ -470,10 +470,10 @@ TPMA_ALGORITHM_Unmarshal(TPMA_ALGORITHM *target, BYTE **buffer, INT32 *size)
TPM_RC rc = TPM_RC_SUCCESS;
if (rc == TPM_RC_SUCCESS) {
rc = UINT32_Unmarshal((UINT32 *)target, buffer, size);
rc = UINT32_Unmarshal(target, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
if (*(UINT32 *)target & TPMA_ALGORITHM_RESERVED) {
if (*target & TPMA_ALGORITHM_reserved) {
rc = TPM_RC_RESERVED_BITS;
}
}
@ -488,10 +488,10 @@ TPMA_OBJECT_Unmarshal(TPMA_OBJECT *target, BYTE **buffer, INT32 *size)
TPM_RC rc = TPM_RC_SUCCESS;
if (rc == TPM_RC_SUCCESS) {
rc = UINT32_Unmarshal((UINT32 *)target, buffer, size);
rc = UINT32_Unmarshal(target, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
if (*(UINT32 *)target & TPMA_OBJECT_RESERVED) {
if (*target & TPMA_OBJECT_reserved) {
rc = TPM_RC_RESERVED_BITS;
}
}
@ -506,10 +506,10 @@ TPMA_SESSION_Unmarshal(TPMA_SESSION *target, BYTE **buffer, INT32 *size)
TPM_RC rc = TPM_RC_SUCCESS;
if (rc == TPM_RC_SUCCESS) {
rc = UINT8_Unmarshal(&target->val, buffer, size);
rc = UINT8_Unmarshal(target, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
if (target->val & TPMA_SESSION_RESERVED) {
if (*target & TPMA_SESSION_reserved) {
rc = TPM_RC_RESERVED_BITS;
}
}
@ -524,7 +524,7 @@ TPMA_LOCALITY_Unmarshal(TPMA_LOCALITY *target, BYTE **buffer, INT32 *size)
TPM_RC rc = TPM_RC_SUCCESS;
if (rc == TPM_RC_SUCCESS) {
rc = UINT8_Unmarshal(&target->val, buffer, size);
rc = UINT8_Unmarshal(target, buffer, size);
}
return rc;
}
@ -537,10 +537,10 @@ TPMA_CC_Unmarshal(TPMA_CC *target, BYTE **buffer, INT32 *size)
TPM_RC rc = TPM_RC_SUCCESS;
if (rc == TPM_RC_SUCCESS) {
rc = UINT32_Unmarshal((UINT32 *)target, buffer, size);
rc = UINT32_Unmarshal(target, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
if (*(UINT32 *)target & TPMA_CC_RESERVED) {
if (*target & TPMA_CC_reserved) {
rc = TPM_RC_RESERVED_BITS;
}
}
@ -1162,6 +1162,9 @@ TPMI_ALG_SYM_MODE_Unmarshal(TPMI_ALG_SYM_MODE *target, BYTE **buffer, INT32 *siz
#endif
#ifdef TPM_ALG_ECB
case TPM_ALG_ECB:
#endif
#ifdef TPM_ALG_CMAC
case TPM_ALG_CMAC:
#endif
break;
case TPM_ALG_NULL:
@ -1311,7 +1314,88 @@ TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32
}
return rc;
}
/* Table 70 TPMI_ALG_MAC_SCHEME */
TPM_RC
TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull)
{
TPM_RC rc = TPM_RC_SUCCESS;
if (rc == TPM_RC_SUCCESS) {
rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
switch (*target) {
#ifdef TPM_ALG_SHA1
case TPM_ALG_SHA1:
#endif
#ifdef TPM_ALG_SHA256
case TPM_ALG_SHA256:
#endif
#ifdef TPM_ALG_SHA384
case TPM_ALG_SHA384:
#endif
#ifdef TPM_ALG_SHA512
case TPM_ALG_SHA512:
#endif
#ifdef TPM_ALG_SM3_256
case TPM_ALG_SM3_256:
#endif
#ifdef TPM_ALG_CMAC
case TPM_ALG_CMAC:
#endif
break;
case TPM_ALG_NULL:
if (allowNull) {
break;
}
default:
rc = TPM_RC_SYMMETRIC;
}
}
return rc;
}
/* Table 70 TPMI_ALG_CIPHER_MODE */
TPM_RC
TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32 *size, BOOL allowNull)
{
TPM_RC rc = TPM_RC_SUCCESS;
if (rc == TPM_RC_SUCCESS) {
rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
switch (*target) {
#ifdef TPM_ALG_CTR
case TPM_ALG_CTR:
#endif
#ifdef TPM_ALG_OFB
case TPM_ALG_OFB:
#endif
#ifdef TPM_ALG_CBC
case TPM_ALG_CBC:
#endif
#ifdef TPM_ALG_CFB
case TPM_ALG_CFB:
#endif
#ifdef TPM_ALG_ECB
case TPM_ALG_ECB:
#endif
break;
case TPM_ALG_NULL:
if (allowNull) {
break;
}
default:
rc = TPM_RC_MODE;
}
}
return rc;
}
/* Table 68 - Definition of TPMS_EMPTY Structure <IN/OUT> */
TPM_RC
@ -1493,7 +1577,7 @@ TPM2B_TIMEOUT_Unmarshal(TPM2B_TIMEOUT *target, BYTE **buffer, INT32 *size)
TPM_RC rc = TPM_RC_SUCCESS;
if (rc == TPM_RC_SUCCESS) {
rc = TPM2B_DIGEST_Unmarshal(target, buffer, size);
rc = TPM2B_Unmarshal(&target->b, sizeof(target->t.buffer), buffer, size);
}
return rc;
}
@ -4128,10 +4212,10 @@ TPMA_NV_Unmarshal(TPMA_NV *target, BYTE **buffer, INT32 *size)
TPM_RC rc = TPM_RC_SUCCESS;
if (rc == TPM_RC_SUCCESS) {
rc = UINT32_Unmarshal(&target->val, buffer, size);
rc = UINT32_Unmarshal(target, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
if (target->val & TPMA_NV_RESERVED) {
if (*target & TPMA_NV_RESERVED) {
rc = TPM_RC_RESERVED_BITS;
}
}

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: Unmarshal_fp.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: Unmarshal_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -187,6 +187,10 @@ extern "C" {
LIB_EXPORT TPM_RC
TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32 *size);
LIB_EXPORT TPM_RC
TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull);
LIB_EXPORT TPM_RC
TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32 *size, BOOL allowNull);
LIB_EXPORT TPM_RC
TPMS_EMPTY_Unmarshal(TPMS_EMPTY *target, BYTE **buffer, INT32 *size);
LIB_EXPORT TPM_RC
TPMU_HA_Unmarshal(TPMU_HA *target, BYTE **buffer, INT32 *size, UINT32 selector);

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptEcc.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptEcc.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */

View File

@ -3,7 +3,7 @@
/* Hash structure definitions */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptHash.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CryptHash.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -62,8 +62,10 @@
#ifndef CRYPTHASH_H
#define CRYPTHASH_H
/* 10.1.3 CryptHash.h */
/* 10.1.3.1 Hash Related Structures */
/* This header contains the hash structure definitions used in the TPM code to define the amount of
space to be reserved for the hash state. This allows the TPM code to not have to import all of
the symbols used by the hash computations. This lets the build environment of the TPM code not to
have include the header files associated with the CryptoEngine() code. */
typedef struct
{
const TPM_ALG_ID alg;
@ -72,6 +74,43 @@ typedef struct
const UINT16 derSize;
const BYTE der[20];
} HASH_INFO;
union SMAC_STATES;
/* These definitions add the high-level methods for processing state that may be an SMAC */
typedef void(* SMAC_DATA_METHOD)(
union SMAC_STATES *state,
UINT32 size,
const BYTE *buffer
);
typedef UINT16(* SMAC_END_METHOD)(
union SMAC_STATES *state,
UINT32 size,
BYTE *buffer
);
typedef struct sequenceMethods {
SMAC_DATA_METHOD data;
SMAC_END_METHOD end;
} SMAC_METHODS;
#if defined TPM_CC_MAC || defined TPM_CC_MAC_Start
# define SMAC_IMPLEMENTED
#endif
/* These definitions are here because the SMAC state is in the union of hash states. */
typedef struct tpmCmacState {
TPM_ALG_ID symAlg;
UINT16 keySizeBits;
INT16 bcount; // current count of bytes accumulated in IV
TPM2B_IV iv; // IV buffer
TPM2B_SYM_KEY symKey;
} tpmCmacState_t;
typedef union SMAC_STATES {
#ifdef TPM_ALG_CMAC
tpmCmacState_t cmac;
#endif
UINT64 pad;
} SMAC_STATES;
typedef struct SMAC_STATE {
SMAC_METHODS smacMethods;
SMAC_STATES state;
} SMAC_STATE;
typedef union
{
#ifdef TPM_ALG_SHA1
@ -85,6 +124,10 @@ typedef union
#endif
#ifdef TPM_ALG_SHA512
tpmHashStateSHA512_t Sha512;
#endif
// Additions for symmetric block cipher MAC
#ifdef SMAC_IMPLEMENTED
SMAC_STATE smac;
#endif
// to force structure alignment to be no worse than HASH_ALIGNMENT
#if HASH_ALIGNMENT == 4
@ -124,10 +167,10 @@ typedef ANY_HASH_STATE ALIGNED_HASH_STATE;
# define HASH_STATE_EXPORT_METHOD_DEF void (HASH_STATE_EXPORT_METHOD)(void)
#endif
#ifndef HASH_STATE_IMPORT_METHOD_DEF
# define HASH_STATE_IMPORT_METHOD_DEF void ( HASH_STATE_IMPORT_METHOD)(void)
# define HASH_STATE_IMPORT_METHOD_DEF void (HASH_STATE_IMPORT_METHOD)(void)
#endif
/* Define the prototypical function call for each of the methods. This defines the order in
which the parameters are passed to the underlying function. */
/* Define the prototypical function call for each of the methods. This defines the order in which
the parameters are passed to the underlying function. */
typedef HASH_START_METHOD_DEF;
typedef HASH_DATA_METHOD_DEF;
typedef HASH_END_METHOD_DEF;
@ -139,10 +182,10 @@ typedef struct _HASH_METHODS
HASH_START_METHOD *start;
HASH_DATA_METHOD *data;
HASH_END_METHOD *end;
HASH_STATE_COPY_METHOD *copy; // Copy a hash block
HASH_STATE_EXPORT_METHOD *copyOut; // Copy a hash block from a hash
HASH_STATE_COPY_METHOD *copy; // Copy a hash block
HASH_STATE_EXPORT_METHOD *copyOut; // Copy a hash block from a hash
// context
HASH_STATE_IMPORT_METHOD *copyIn; // Copy a hash block to a proper hash
HASH_STATE_IMPORT_METHOD *copyIn; // Copy a hash block to a proper hash
// context
} HASH_METHODS, *PHASH_METHODS;
#if ALG_SHA1
@ -184,13 +227,16 @@ typedef const struct
HASH##_DIGEST_SIZE, /*data size */ \
sizeof(tpmHashState##HASH##_t), \
TPM_ALG_##HASH}
/* These definitions are for the types that can be in a hash state structure. These types are
used in the crypto utilities. This is a define rather than an enum so that the size of this
field can be explicit. */
/* These definitions are for the types that can be in a hash state structure. These types are used
in the cryptographic utilities. This is a define rather than an enum so that the size of this
field can be explicit. */
typedef BYTE HASH_STATE_TYPE;
#define HASH_STATE_EMPTY ((HASH_STATE_TYPE) 0)
#define HASH_STATE_HASH ((HASH_STATE_TYPE) 1)
#define HASH_STATE_HMAC ((HASH_STATE_TYPE) 2)
#if defined TPM_CC_MAC || defined TPM_CC_MAC_Start
#define HASH_STATE_SMAC ((HASH_STATE_TYPE) 3)
#endif
/* This is the structure that is used for passing a context into the hashing functions. It should be
the same size as the function context used within the hashing functions. This is checked when the
hash function is initialized. This version uses a new layout for the contexts and a different
@ -198,14 +244,18 @@ typedef BYTE HASH_STATE_TYPE;
the structure on a HASH_UNIT boundary. If the structure is not properly aligned, the code that
manipulates the structure will copy to a properly aligned structure before it is used and copy
the result back. This just makes things slower. */
/* NOTE: This version of the state had the pointer to the update method in the state. This is to
allow the SMAC functions to use the same structure without having to replicate the entire
HASH_DEF structure. */
typedef struct _HASH_STATE
{
PHASH_DEF def;
TPM_ALG_ID hashAlg;
HASH_STATE_TYPE type; // type of the context
TPM_ALG_ID hashAlg;
PHASH_DEF def;
ANY_HASH_STATE state;
} HASH_STATE, *PHASH_STATE;
typedef const HASH_STATE *PCHASH_STATE;
/* 10.1.3.2 HMAC State Structures */
/* This header contains the hash structure definitions used in the TPM code to define the amount of
space to be reserved for the hash state. This allows the TPM code to not have to import all of
@ -215,7 +265,7 @@ typedef const HASH_STATE *PCHASH_STATE;
/* An HMAC_STATE structure contains an opaque HMAC stack state. A caller would use this structure
when performing incremental HMAC operations. This structure contains a hash state and an HMAC key
and allows slightly better stack optimization than adding an HMAC key to each hash state. */
typedef struct
typedef struct hmacState
{
HASH_STATE hashState; // the hash state
TPM2B_HASH_BLOCK hmacKey; // the HMAC key

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Implementation of cryptographic functions for hashing. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptHash_fp.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CryptHash_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -75,10 +75,10 @@ CryptGetHashDef(
TPM_ALG_ID hashAlg
);
BOOL
CryptHashIsImplemented(
TPM_ALG_ID hashAlg,
BOOL flag
);
CryptHashIsValidAlg(
TPM_ALG_ID hashAlg,
BOOL flag
);
LIB_EXPORT TPM_ALG_ID
CryptHashGetAlgByIndex(
UINT32 index // IN: the index
@ -202,11 +202,7 @@ CryptKDFa(
UINT32 sizeInBits, // IN: size of generated key in bits
BYTE *keyStream, // OUT: key buffer
UINT32 *counterInOut, // IN/OUT: caller may provide the iteration
// counter for incremental operations to
// avoid large intermediate buffers.
BOOL once // IN: TRUE - only 1 iteration is performed
// FALSE if iteration count determined by
// "sizeInBits"
UINT16 blocks // IN: If non-zero, this is the maximum number
);
LIB_EXPORT UINT16
CryptKDFe(

View File

@ -3,7 +3,7 @@
/* DRBG with a behavior according to SP800-90A */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptRand.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CryptRand.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -149,11 +149,14 @@ typedef struct
{
UINT64 counter;
UINT32 magic;
UINT32 limit;
TPM2B *seed;
const TPM2B *label;
TPM2B *context;
TPM_ALG_ID hash;
TPM_ALG_ID kdf;
UINT16 digestSize;
TPM2B_DIGEST residual;
} KDF_STATE, *pKDR_STATE;
#define KDF_MAGIC ((UINT32) 0x4048444a) // "KDF " backwards
/* Make sure that any other structures added to this union start with a 64-bit counter and a 32-bit

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* DRBG with a behavior according to SP800-90A */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptRand_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptRand_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -113,7 +113,8 @@ DRBG_InstantiateSeededKdf(
TPM_ALG_ID kdf, // IN: the KDF to use
TPM2B *seed, // IN: the seed to use
const TPM2B *label, // IN: a label for the generation process.
TPM2B *context // IN: the context value
TPM2B *context, // IN: the context value
UINT32 limit // IN: Maximum number of bits from the KDF
);
LIB_EXPORT void
DRBG_AdditionalData(

153
src/tpm2/crypto/CryptSym.h Normal file
View File

@ -0,0 +1,153 @@
/********************************************************************************/
/* */
/* Implementation of the symmetric block cipher modes */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptSym.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
/* 1. Copyright Licenses: */
/* */
/* - Trusted Computing Group (TCG) grants to the user of the source code in */
/* this specification (the "Source Code") a worldwide, irrevocable, */
/* nonexclusive, royalty free, copyright license to reproduce, create */
/* derivative works, distribute, display and perform the Source Code and */
/* derivative works thereof, and to grant others the rights granted herein. */
/* */
/* - The TCG grants to the user of the other parts of the specification */
/* (other than the Source Code) the rights to reproduce, distribute, */
/* display, and perform the specification solely for the purpose of */
/* developing products based on such documents. */
/* */
/* 2. Source Code Distribution Conditions: */
/* */
/* - Redistributions of Source Code must retain the above copyright licenses, */
/* this list of conditions and the following disclaimers. */
/* */
/* - Redistributions in binary form must reproduce the above copyright */
/* licenses, this list of conditions and the following disclaimers in the */
/* documentation and/or other materials provided with the distribution. */
/* */
/* 3. Disclaimers: */
/* */
/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */
/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */
/* information on specification licensing rights available through TCG */
/* membership agreements. */
/* */
/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */
/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */
/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */
/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */
/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */
/* */
/* - Without limitation, TCG and its members and licensors disclaim all */
/* liability, including liability for infringement of any proprietary */
/* rights, relating to use of information in this specification and to the */
/* implementation of this specification, and TCG disclaims all liability for */
/* cost of procurement of substitute goods or services, lost profits, loss */
/* of use, loss of data or any incidental, consequential, direct, indirect, */
/* or special damages, whether under contract, tort, warranty or otherwise, */
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2017 */
/* */
/********************************************************************************/
/* kgold - Missing in 146 code merge. Taken from 142. */
#ifndef CRYPTSYM_H
#define CRYPTSYM_H
union tpmCryptKeySchedule_t {
#ifdef TPM_ALG_AES
tpmKeyScheduleAES AES;
#endif
#ifdef TPM_ALG_SM4
tpmKeyScheduleSM4 SM4;
#endif
#ifdef TPM_ALG_CAMELLIA
tpmKeyScheduleCAMELLIA CAMELLIA;
#endif
#ifdef TPM_ALG_TDES
tpmKeyScheduleTDES TDES[3];
#endif
#if SYMMETRIC_ALIGNMENT == 8
uint64_t alignment;
#else
uint32_t alignment;
#endif
};
/* Each block cipher within a library is expected to conform to the same calling conventions with
three parameters (keySchedule, in, and out) in the same order. That means that all algorithms
would use the same order of the same parameters. The code is written assuming the (keySchedule,
in, and out) order. However, if the library uses a different order, the order can be changed with
a SWIZZLE macro that puts the parameters in the correct order. Note that all algorithms have to
use the same order and number of parameters because the code to build the calling list is common
for each call to encrypt or decrypt with the algorithm chosen by setting a function pointer to
select the algorithm that is used. */
# define ENCRYPT(keySchedule, in, out) \
encrypt(SWIZZLE(keySchedule, in, out))
# define DECRYPT(keySchedule, in, out) \
decrypt(SWIZZLE(keySchedule, in, out))
/* Note that the macros rely on encrypt as local values in the functions that use these
macros. Those parameters are set by the macro that set the key schedule to be used for the
call. */
#define ENCRYPT_CASE(ALG) \
case TPM_ALG_##ALG: \
TpmCryptSetEncryptKey##ALG(key, keySizeInBits, &keySchedule.ALG); \
encrypt = (TpmCryptSetSymKeyCall_t)TpmCryptEncrypt##ALG; \
break;
#define DECRYPT_CASE(ALG) \
case TPM_ALG_##ALG: \
TpmCryptSetDecryptKey##ALG(key, keySizeInBits, &keySchedule.ALG); \
decrypt = (TpmCryptSetSymKeyCall_t)TpmCryptDecrypt##ALG; \
break;
#ifdef TPM_ALG_AES
#define ENCRYPT_CASE_AES ENCRYPT_CASE(AES)
#define DECRYPT_CASE_AES DECRYPT_CASE(AES)
#else
#define ENCRYPT_CASE_AES
#define DECRYPT_CASE_AES
#endif
#ifdef TPM_ALG_SM4
#define ENCRYPT_CASE_SM4 ENCRYPT_CASE(SM4)
#define DECRYPT_CASE_SM4 DECRYPT_CASE(SM4)
#else
#define ENCRYPT_CASE_SM4
#define DECRYPT_CASE_SM4
#endif
#ifdef TPM_ALG_CAMELLIA
#define ENCRYPT_CASE_CAMELLIA ENCRYPT_CASE(CAMELLIA)
#define DECRYPT_CASE_CAMELLIA DECRYPT_CASE(CAMELLIA)
#else
#define ENCRYPT_CASE_CAMELLIA
#define DECRYPT_CASE_CAMELLIA
#endif
#ifdef TPM_ALG_TDES
#define ENCRYPT_CASE_TDES ENCRYPT_CASE(TDES)
#define DECRYPT_CASE_TDES DECRYPT_CASE(TDES)
#else
#define ENCRYPT_CASE_TDES
#define DECRYPT_CASE_TDES
#endif
/* For each algorithm the case will either be defined or null. */
#define SELECT(direction) \
switch(algorithm) \
{ \
direction##_CASE_AES \
direction##_CASE_SM4 \
direction##_CASE_CAMELLIA \
direction##_CASE_TDES \
default: \
return TPM_RC_FAILURE; \
}
#endif

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptSym_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptSym_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */

View File

@ -3,7 +3,7 @@
/* constant definitions used for self-test. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptTest.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CryptTest.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -65,12 +65,14 @@
/* 10.1.7 CryptTest.h */
/* This file contains constant definitions used for self test */
/* This is the definition of a bit array with one bit per algorithm */
/* NOTE: Since bit numbering starts at zero, when ALG_LAST_VALUE is a multiple of 8,
ALGORITHM_VECTOR will need to have byte for the single bit in the last byte. So, for example,
when ALG_LAST_VECTOR is 8, ALGORITHM_VECTOR will need 2 bytes. */
#define ALGORITHM_VECTOR_BYTES ((ALG_LAST_VALUE + 8) / 8)
typedef BYTE ALGORITHM_VECTOR[ALGORITHM_VECTOR_BYTES];
#ifdef TEST_SELF_TEST
LIB_EXPORT extern ALGORITHM_VECTOR LibToTest;
#endif
/* 10.1.7.2 Self-test */
/* This structure is used to contain self-test tracking information for the cryptographic
modules. Each of the major modules is given a 32-bit value in which it may maintain its own self
test information. The convention for this state is that when all of the bits in this structure
@ -87,7 +89,6 @@ typedef struct
UINT32 ecc;
#endif
} CRYPTO_SELF_TEST_STATE;
/* 10.1.7.2.1 g_cryptoSelfTestState */
/* This structure contains the cryptographic self-test state values. */
extern CRYPTO_SELF_TEST_STATE g_cryptoSelfTestState;
#endif // _CRYPT_TEST_H

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptUtil_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptUtil_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -220,6 +220,26 @@ void
CryptAlgsSetImplemented(
void
);
TPM_RC
CryptSelectMac(
TPMT_PUBLIC *publicArea,
TPMI_ALG_MAC_SCHEME *inMac
);
BOOL
CryptMacIsValidForKey(
TPM_ALG_ID keyType,
TPM_ALG_ID macAlg,
BOOL flag
);
BOOL
CryptSmacIsValidAlg(
TPM_ALG_ID alg,
BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid
);
BOOL
CryptSymModeIsValid(
TPM_ALG_ID mode,
BOOL flag
);
#endif

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptDataEcc.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptDataEcc.c 1012 2017-05-23 21:45:57Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -300,7 +300,7 @@ const TPM2B_32_BYTE_VALUE BN_P256_p = {32,
const TPM2B_1_BYTE_VALUE BN_P256_a = {1,{0}};
const TPM2B_1_BYTE_VALUE BN_P256_b = {1,{3}};
const TPM2B_1_BYTE_VALUE BN_P256_gX = {1,{1}};
const TPM2B_1_BYTE_VALUE BN_P256_gY = {1,{2}};;
const TPM2B_1_BYTE_VALUE BN_P256_gY = {1,{2}};
const TPM2B_32_BYTE_VALUE BN_P256_n = {32,
{0xFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFC, 0XF0, 0XCD,
0X46, 0XE5, 0XF2, 0X5E, 0XEE, 0X71, 0XA4, 0X9E,

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptDes.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptDes.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -167,7 +167,8 @@ CryptGenerateKeyDes(
BYTE *pK = sensitive->sensitive.sym.t.buffer;
int i = (sensitive->sensitive.sym.t.size + 7) / 8;
// Use the random number generator to generate the required number of bits
DRBG_Generate(rand, pK, sensitive->sensitive.sym.t.size);
if(DRBG_Generate(rand, pK, sensitive->sensitive.sym.t.size) == 0)
return TPM_RC_NO_RESULT;
for(; i > 0; pK += 8, i--)
{
UINT64 k = BYTE_ARRAY_TO_UINT64(pK);

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Functions that are used for the two-phase, ECC, key-exchange protocols */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptEccKeyExchange.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptEccKeyExchange.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptEccMain.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CryptEccMain.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -333,8 +333,6 @@ CryptGenerateR(
// requirements of the random value.
// want to generate a new r.
r->t.size = n.t.size;
// Arbitrary upper limit on the number of times that we can look for
// a suitable random value. The normally number of tries will be 1.
for(iterations = 1; iterations < 1000000;)
{
int i;
@ -489,7 +487,7 @@ CryptEccIsValidPrivateKey(
/* Error Returns Meaning */
/* TPM_RC_NO_RESULTS result of multiplication is a point at infinity */
/* TPM_RC_ECC_POINT S or Q is not on the curve */
/* TPM_RC_VALUE d or u is not 0 < d < n */
/* TPM_RC_VALUE d or u is not < n */
TPM_RC
BnPointMult(
bigPoint R, // OUT: computed point
@ -543,6 +541,9 @@ BnPointMult(
search will take more than one iteration is very small. As a consequence, the weighted-average
run time for this function is significantly less than the method of key pair generation with
extra random bits. */
/* Return Value Meaning */
/* TRUE value generated */
/* FALSE failure generating private key */
BOOL
BnEccGetPrivate(
bigNum dOut, // OUT: the qualified random value
@ -551,16 +552,31 @@ BnEccGetPrivate(
RAND_STATE *rand // IN: state for DRBG
)
{
//
bigConst order = CurveGetOrder(C);
BOOL OK;
UINT32 orderBits = BnSizeInBits(order);
#if 1 // This is the "extra bits" method of key generation
UINT32 orderBytes = BITS_TO_BYTES(orderBits);
BN_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64);
BN_VAR(nMinus1, MAX_ECC_KEY_BITS);
//
OK = BnGetRandomBits(bnExtraBits, (orderBytes * 8) + 64, rand);
OK = OK && BnSubWord(nMinus1, order, 1);
OK = OK && BnMod(bnExtraBits, nMinus1);
OK = OK && BnAddWord(dOut, bnExtraBits, 1);
#else
// This is the "testing candidates" version of key generation
do
{
BnGetRandomBits(dOut, BnSizeInBits(order), rand);
BnAddWord(dOut, dOut, 1);
} while(BnUnsignedCmp(dOut, order) >= 0);
return TRUE;
OK = BnGetRandomBits(dOut, BnSizeInBits(order), rand);
OK = OK && BnAddWord(dOut, dOut, 1);
} while(OK && BnUnsignedCmp(dOut, order) >= 0);
#endif
return OK;
}
/* 10.2.11.2.21 BnEccGenerateKeyPair() */
/* This function gets a private scalar from the source of random bits and does the point multiply to
get the public key. */
BOOL
BnEccGenerateKeyPair(
bigNum bnD, // OUT: private scalar
@ -570,14 +586,10 @@ BnEccGenerateKeyPair(
)
{
BOOL OK = FALSE;
int limit;
for(limit = 100; (limit > 0) && !OK; limit--)
{
// Get a private scalar
BnEccGetPrivate(bnD, E->C, rand);
// Do a point multiply
OK = BnEccModMult(ecQ, NULL, bnD, E);
}
// Get a private scalar
OK = BnEccGetPrivate(bnD, E->C, rand);
// Do a point multiply
OK = OK && BnEccModMult(ecQ, NULL, bnD, E);
if(!OK)
BnSetWord(ecQ->z, 0);
else
@ -688,7 +700,7 @@ CryptEccIsPointOnCurve(
key */
/* Error Returns Meaning */
/* TPM_RC_CURVE curve is not supported */
/* TPM_RC_FAIL ??? */
/* TPM_RC_NO_RESULT could not verify key with signature (FIPS only) */
LIB_EXPORT TPM_RC
CryptEccGenerateKey(
TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for
@ -706,9 +718,8 @@ CryptEccGenerateKey(
CURVE_INITIALIZED(E, publicArea->parameters.eccDetail.curveID);
ECC_NUM(bnD);
POINT(ecQ);
const UINT32 MaxCount = 100;
UINT32 count = 0;
TPM_RC retVal = TPM_RC_NO_RESULT;
BOOL OK;
TPM_RC retVal;
TEST(TPM_ALG_ECDSA); // ECDSA is used to verify each key
// Validate parameters
if(E == NULL)
@ -716,37 +727,32 @@ CryptEccGenerateKey(
publicArea->unique.ecc.x.t.size = 0;
publicArea->unique.ecc.y.t.size = 0;
sensitive->sensitive.ecc.t.size = 0;
// Start search for key (should be quick)
for(count = 1; (count < MaxCount) && (retVal != TPM_RC_SUCCESS); count++)
OK = BnEccGenerateKeyPair(bnD, ecQ, E, rand);
if(OK)
{
if(!BnEccGenerateKeyPair(bnD, ecQ, E, rand))
FAIL(FATAL_ERROR_INTERNAL);
retVal = TPM_RC_SUCCESS;
#ifdef FIPS_COMPLIANT
// See if PWCT is required
if(publicArea->objectAttributes.sign)
{
ECC_NUM(bnT);
ECC_NUM(bnS);
TPM2B_DIGEST digest;
TEST(TPM_ALG_ECDSA);
digest.t.size =
(UINT16)BITS_TO_BYTES(BnSizeInBits(CurveGetPrime(
AccessCurveData(E))));
// Get a random value to sign using the current DRBG state
DRBG_Generate(NULL, digest.t.buffer, digest.t.size);
BnSignEcdsa(bnT, bnS, E, bnD, &digest, NULL);
// and make sure that we can validate the signature
retVal = BnValidateSignatureEcdsa(bnT, bnS, E, ecQ, &digest);
}
#endif
BnPointTo2B(&publicArea->unique.ecc, ecQ, E);
BnTo2B(bnD, &sensitive->sensitive.ecc.b, publicArea->unique.ecc.x.t.size);
}
// if counter maxed out, put the TPM to failure mode
if(count == MaxCount)
FAIL(FATAL_ERROR_INTERNAL);
// Convert results
BnPointTo2B(&publicArea->unique.ecc, ecQ, E);
BnTo2B(bnD, &sensitive->sensitive.ecc.b, publicArea->unique.ecc.x.t.size);
#if defined FIPS_COMPLIANT || 1
// See if PWCT is required
if(OK && (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))) // kgold
// if(OK && publicArea->objectAttributes.sign)
{
ECC_NUM(bnT);
ECC_NUM(bnS);
TPM2B_DIGEST digest;
TEST(TPM_ALG_ECDSA);
digest.t.size =
(UINT16)BITS_TO_BYTES(BnSizeInBits(CurveGetPrime(
AccessCurveData(E))));
// Get a random value to sign using the built in DRBG state
DRBG_Generate(NULL, digest.t.buffer, digest.t.size);
BnSignEcdsa(bnT, bnS, E, bnD, &digest, NULL);
// and make sure that we can validate the signature
OK = BnValidateSignatureEcdsa(bnT, bnS, E, ecQ, &digest) == TPM_RC_SUCCESS;
}
#endif
retVal = (OK) ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;
Exit:
CURVE_FREE(E);
return retVal;

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptEccSignature.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: CryptEccSignature.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -216,6 +216,7 @@ BnSignEcdsa(
this function u */
/* Error Returns Meaning */
/* TPM_RC_SCHEME unsupported hash algorithm */
/* TPM_RC_NO_RESULT cannot get values from random number generator */
static TPM_RC
BnSignEcdaa(
TPM2B_ECC_PARAMETER *nonceK, // OUT: nonce component of the signature
@ -242,14 +243,18 @@ BnSignEcdaa(
retVal = TPM_RC_VALUE;
else
{
// This allocation is here because k is not defined until CrypGenerateR()
// is done.
// This allocation is here because 'r' doesn't have a value until
// CrypGenerateR() is done.
ECC_INITIALIZED(bnR, &r);
do
{
// generate nonceK such that 0 < nonceK < n
// use bnT as a temp.
BnEccGetPrivate(bnT, AccessCurveData(E), rand);
if(!BnEccGetPrivate(bnT, AccessCurveData(E), rand))
{
retVal = TPM_RC_NO_RESULT;
break;
}
BnTo2B(bnT, &nonceK->b, 0);
T.t.size = CryptHashStart(&state, scheme->details.ecdaa.hashAlg);
if(T.t.size == 0)
@ -397,7 +402,7 @@ BnSignEcSm2(
// debug)
)
{
BN_MAX_INITIALIZZED(bnE, digest); // Don't know how big digest might be
BN_MAX_INITIALIZED(bnE, digest); // Don't know how big digest might be
ECC_NUM(bnN);
ECC_NUM(bnK);
ECC_NUM(bnX1);

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Implementation of cryptographic functions for hashing. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptHash.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CryptHash.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -81,6 +81,8 @@ HASH_DEF_TEMPLATE(SHA512);
#endif
HASH_DEF nullDef = {{0}};
/* 10.2.14.3 Obligatory Initialization Functions */
/* This function is called by _TPM_Init() do perform the initialization operations for the
library. */
BOOL
CryptHashInit(
void
@ -89,6 +91,9 @@ CryptHashInit(
LibHashInit();
return TRUE;
}
/* 10.2.13.3.2 CryptHashStartup() */
/* This function is called by TPM2_Startup() in case there is work to do at startup. Currently, this
is a placeholder. */
BOOL
CryptHashStartup(
void
@ -136,17 +141,17 @@ CryptGetHashDef(
}
return retVal;
}
/* 10.2.14.4.3 CryptHashIsImplemented() */
/* 10.2.13.4.3 CryptHashIsValidAlg() */
/* This function tests to see if an algorithm ID is a valid hash algorithm. If flag is true, then
TPM_ALG_NULL is a valid hash. */
/* Return Values Meaning */
/* TRUE hashAlg is a valid, implemented hash on this TPM. */
/* FALSE not valid */
/* Return Value Meaning */
/* TRUE hashAlg is a valid, implemented hash on this TPM. */
/* FALSE not valid */
BOOL
CryptHashIsImplemented(
TPM_ALG_ID hashAlg,
BOOL flag
)
CryptHashIsValidAlg(
TPM_ALG_ID hashAlg,
BOOL flag
)
{
switch(hashAlg)
{
@ -263,7 +268,6 @@ CryptHashGetContextAlg(
return state->hashAlg;
}
/* 10.2.14.5 State Import and Export */
#if 1
/* 10.2.14.5.1 CryptHashCopyState */
/* This function is used to clone a HASH_STATE. */
LIB_EXPORT void
@ -290,7 +294,6 @@ CryptHashCopyState(
}
return;
}
#endif //0
/* 10.2.14.5.2 CryptHashExportState() */
/* This function is used to export a hash or HMAC hash state. This function would be called when
preparing to context save a sequence object. */
@ -304,11 +307,21 @@ CryptHashExportState(
BYTE *outBuf = (BYTE *)externalFmt;
//
cAssert(sizeof(HASH_STATE) <= sizeof(EXPORT_HASH_STATE));
// the following #define is used to move data from an aligned internal data
// structure to a byte buffer (external format data.
#define CopyToOffset(value) \
memcpy(&outBuf[offsetof(HASH_STATE,value)], &internalFmt->value, \
sizeof(internalFmt->value))
// Copy the hashAlg
CopyToOffset(hashAlg);
CopyToOffset(type);
#ifdef HASH_STATE_SMAC
if(internalFmt->type == HASH_STATE_SMAC)
{
memcpy(outBuf, internalFmt, sizeof(HASH_STATE));
return;
}
#endif
if(internalFmt->type == HASH_STATE_HMAC)
{
HMAC_STATE *from = (HMAC_STATE *)internalFmt;
@ -339,6 +352,13 @@ CryptHashImportState(
CopyFromOffset(type);
if(internalFmt->hashAlg != TPM_ALG_NULL)
{
#ifdef HASH_STATE_SMAC
if(internalFmt->type == HASH_STATE_SMAC)
{
memcpy(internalFmt, inBuf, sizeof(HASH_STATE));
return;
}
#endif
internalFmt->def = CryptGetHashDef(internalFmt->hashAlg);
HASH_STATE_IMPORT(internalFmt, inBuf);
if(internalFmt->type == HASH_STATE_HMAC)
@ -362,7 +382,8 @@ HashEnd(
)
{
BYTE temp[MAX_DIGEST_SIZE];
if(hashState->hashAlg == TPM_ALG_NULL)
if((hashState->hashAlg == TPM_ALG_NULL)
|| (hashState->type != HASH_STATE_HASH))
dOutSize = 0;
if(dOutSize > 0)
{
@ -377,7 +398,6 @@ HashEnd(
memcpy(dOut, &temp, dOutSize);
}
hashState->type = HASH_STATE_EMPTY;
// hashState->hashAlg = TPM_ALG_ERROR;
return (UINT16)dOutSize;
}
/* 10.2.14.6.2 CryptHashStart() */
@ -415,9 +435,9 @@ CryptHashStart(
hashState->type = HASH_STATE_HASH;
return retVal;
}
/* 10.2.14.6.3 CryptDigestUpdate() */
/* Add data to a hash or HMAC stack. */
LIB_EXPORT void
/* 10.2.13.6.3 CryptDigestUpdate() */
/* Add data to a hash or HMAC, SMAC stack. */
void
CryptDigestUpdate(
PHASH_STATE hashState, // IN: the hash context information
UINT32 dataSize, // IN: the size of data to be added
@ -426,10 +446,21 @@ CryptDigestUpdate(
{
if(hashState->hashAlg != TPM_ALG_NULL)
{
#ifndef SMAC_IMPLEMENTED
pAssert((hashState->type == HASH_STATE_HASH)
|| (hashState->type == HASH_STATE_HMAC));
hashState->def = CryptGetHashDef(hashState->hashAlg);
//?? hashState->def = CryptGetHashDef(hashState->hashAlg);
HASH_DATA(hashState, dataSize, (BYTE *)data);
#else
if((hashState->type == HASH_STATE_HASH)
|| (hashState->type == HASH_STATE_HMAC))
HASH_DATA(hashState, dataSize, (BYTE *)data);
else if(hashState->type == HASH_STATE_SMAC)
(hashState->state.smac.smacMethods.data)(&hashState->state.smac.state,
dataSize, data);
else
FAIL(FATAL_ERROR_INTERNAL);
#endif // SMAC_IMPLEMENTED
}
return;
}
@ -489,7 +520,7 @@ CryptDigestUpdate2B(
return;
}
/* 10.2.14.6.7 CryptHashEnd2B() */
/* This function is the same as CypteCompleteHash() but the digest is placed in a TPM2B. This is the
/* This function is the same as CryptCompleteHash() but the digest is placed in a TPM2B. This is the
most common use and this is provided for specification clarity. 'digest.size' should be set to
indicate the number of bytes to place in the buffer */
/* Return Values Meaning */
@ -513,7 +544,7 @@ CryptDigestUpdateInt(
UINT64 intValue // IN: integer value to be hashed
)
{
#if LITTLE_ENDIAN_TPM == YES
#if LITTLE_ENDIAN_TPM
intValue = REVERSE_ENDIAN_64(intValue);
#endif
CryptDigestUpdate(state, intSize, &((BYTE *)&intValue)[8 - intSize]);
@ -593,6 +624,13 @@ CryptHmacEnd(
{
BYTE temp[MAX_DIGEST_SIZE];
PHASH_STATE hState = (PHASH_STATE)&state->hashState;
#ifdef SMAC_IMPLEMENTED
if(hState->type == HASH_STATE_SMAC)
return (state->hashState.state.smac.smacMethods.end)
(&state->hashState.state.smac.state,
dOutSize,
dOut);
#endif
pAssert(hState->type == HASH_STATE_HMAC);
hState->def = CryptGetHashDef(hState->hashAlg);
// Change the state type for completion processing
@ -713,18 +751,18 @@ CryptKDFa(
UINT32 *counterInOut, // IN/OUT: caller may provide the iteration
// counter for incremental operations to
// avoid large intermediate buffers.
BOOL once // IN: TRUE - only 1 iteration is performed
// FALSE if iteration count determined by
// "sizeInBits"
UINT16 blocks // IN: If non-zero, this is the maximum number
// of blocks to be returned, regardless
// of sizeInBit
)
{
UINT32 counter = 0; // counter value
INT16 bytes; // number of bytes to produce
UINT32 counter = 0; // counter value
INT16 bytes; // number of bytes to produce
UINT16 generated; // number of bytes generated
BYTE *stream = keyStream;
HMAC_STATE hState;
UINT16 digestSize = CryptHashGetDigestSize(hashAlg);
pAssert(key != NULL && keyStream != NULL);
pAssert(once == FALSE || (sizeInBits & 7) == 0);
if(digestSize == 0)
return 0;
if(counterInOut != NULL)
@ -732,13 +770,16 @@ CryptKDFa(
// If the size of the request is larger than the numbers will handle,
// it is a fatal error.
pAssert(((sizeInBits + 7) / 8) <= INT16_MAX);
bytes = once ? digestSize : (INT16)((sizeInBits + 7) / 8);
// The number of bytes to be generated is the smaller of the sizeInBits bytes or
// the number of requested blocks. The number of blocks is the smaller of the
// number requested or the number allowed by sizeInBits. A partial block is
// a full block.
bytes = (blocks > 0) ? blocks * digestSize : (UINT16)BITS_TO_BYTES(sizeInBits);
generated = bytes;
// Generate required bytes
for(; bytes > 0; bytes -= digestSize)
{
counter++;
if(bytes < digestSize)
digestSize = bytes;
// Start HMAC
if(CryptHmacStart(&hState, hashAlg, key->size, key->buffer) == 0)
return 0;
@ -764,15 +805,22 @@ CryptKDFa(
HASH_DATA(&hState.hashState, contextV->size, contextV->buffer);
// Adding size in bits
CryptDigestUpdateInt(&hState.hashState, 4, sizeInBits);
CryptHmacEnd(&hState, digestSize, stream);
// Complete and put the data in the buffer
CryptHmacEnd(&hState, bytes, stream);
stream = &stream[digestSize];
}
// Mask off bits if the required bits is not a multiple of byte size
if((sizeInBits % 8) != 0)
// Mask off bits if the required bits is not a multiple of byte size. Only do
// this if this is a call that is returning all the blocks indicated in
// sizeInBits
#if 0 //?? Masking in the KDF is disabled. If the calling function wants something
//?? less than even number of bytes, then the caller should do the masking
//?? because there is no universal way to do it here
if((blocks == 0) && (sizeInBits % 8) != 0)
keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
#endif
if(counterInOut != NULL)
*counterInOut = counter;
return (UINT16)((sizeInBits + 7) / 8);
return generated;
}
/* 10.2.14.8.3 CryptKDFe() */
/* KDFe() as defined in TPM specification part 1. */

View File

@ -3,7 +3,7 @@
/* DRBG with a behavior according to SP800-90A */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptRand.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CryptRand.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -119,13 +119,13 @@ DfStart(
BYTE init[8];
int i;
UINT32 drbgSeedSize = sizeof(DRBG_SEED);
const BYTE dfKey[] = {
const BYTE dfKey[DRBG_KEY_SIZE_BYTES] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
/* #if DRBG_KEY_SIZE_WORDS > 4 kgold */
#if DRBG_KEY_SIZE_BYTES > 16
,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
/* #endif */
#endif
};
memset(dfState, 0, sizeof(DF_STATE));
DRBG_ENCRYPT_SETUP(&dfKey[0], DRBG_KEY_SIZE_BITS, &dfState->keySchedule);
@ -543,16 +543,20 @@ DRBG_InstantiateSeededKdf(
TPM_ALG_ID kdf, // IN: the KDF to use
TPM2B *seed, // IN: the seed to use
const TPM2B *label, // IN: a label for the generation process.
TPM2B *context // IN: the context value
TPM2B *context, // IN: the context value
UINT32 limit // IN: Maximum number of bits from the KDF
)
{
state->magic = KDF_MAGIC;
state->limit = limit;
state->seed = seed;
state->hash = hashAlg;
state->kdf = kdf;
state->label = label;
state->context = context;
state->counter = 1;
state->digestSize = CryptHashGetDigestSize(hashAlg);
state->counter = 0;
state->residual.t.size = 0;
return TRUE;
}
/* 10.2.18.4.5 DRBG_AdditionalData() */
@ -654,18 +658,73 @@ DRBG_Generate(
UINT16 randomSize // IN: the number of bytes to generate
)
{
//
if(state == NULL)
state = (RAND_STATE *)&drbgDefault;
// If the caller used a KDF state, generate a sequence from the KDF
// If the caller used a KDF state, generate a sequence from the KDF not to
// exceed the limit.
if(state->kdf.magic == KDF_MAGIC)
{
KDF_STATE *kdf = (KDF_STATE *)state;
UINT32 count = (UINT32)kdf->counter;
if((randomSize != 0) && (random != NULL))
CryptKDFa(kdf->hash, kdf->seed, kdf->label, kdf->context, NULL,
randomSize * 8, random, &count, 0);
kdf->counter = count;
UINT32 counter = (UINT32)kdf->counter;
INT32 bytesLeft = randomSize;
if(random == NULL)
return 0;
// If the number of bytes to be returned would put the generator
// over the limit, then return 0
if((((kdf->counter * kdf->digestSize) + randomSize) * 8) > kdf->limit)
return 0;
// Process partial and full blocks until all requested bytes provided
while(bytesLeft > 0)
{
// If there is any residual data in the buffer, copy it to the output
// buffer
if(kdf->residual.t.size > 0)
{
INT32 size;
//
// Don't use more of the residual than will fit or more than are
// available
size = MIN(kdf->residual.t.size, bytesLeft);
// Copy some or all of the residual to the output. The residual is
// at the end of the buffer. The residual might be a full buffer.
MemoryCopy(random,
&kdf->residual.t.buffer
[kdf->digestSize - kdf->residual.t.size], size);
// Advance the buffer pointer
random += size;
// Reduce the number of bytes left to get
bytesLeft -= size;
// And reduce the residual size appropriately
kdf->residual.t.size -= (UINT16)size;
}
else
{
UINT16 blocks = (UINT16)(bytesLeft / kdf->digestSize);
//
// Get the number of required full blocks
if(blocks > 0)
{
UINT16 size = blocks * kdf->digestSize;
// Get some number of full blocks and put them in the return buffer
CryptKDFa(kdf->hash, kdf->seed, kdf->label, kdf->context, NULL,
kdf->limit, random, &counter, blocks);
// reduce the size remaining to be moved and advance the pointer
bytesLeft -= size;
random += size;
}
else
{
// Fill the residual buffer with a full block and then loop to
// top to get part of it copied to the output.
kdf->residual.t.size = CryptKDFa(kdf->hash, kdf->seed,
kdf->label, kdf->context, NULL,
kdf->limit,
kdf->residual.t.buffer,
&counter, 1);
}
}
}
kdf->counter = counter;
return randomSize;
}
else if(state->drbg.magic == DRBG_MAGIC)
@ -762,6 +821,7 @@ DRBG_Uninstantiate(
/* This function generates a value that as not larger than (2^max) - 1 and no smaller than 2^(min -
1). For example, if max == 4 and min == 2, then the number will be between 0x0010 and 0x1111
inclusively. If max == 4 and min == 4 then the number will be between 0x1000 and 0x1111. */
#if 0
LIB_EXPORT NUMBYTES
CryptRandMinMax(
BYTE *out,
@ -780,3 +840,4 @@ CryptRandMinMax(
BnToBytes(bn, out, &size);
return size;
}
#endif

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* implementation of cryptographic primitives for RSA */
/* Implementation of cryptographic primitives for RSA */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptRsa.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CryptRsa.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -410,12 +410,12 @@ OaepDecode(
dataOut->size = 0;
return retVal;
}
/* 10.2.19.4.7 PKSC1v1_5Encode() */
/* 10.2.19.4.7 PKCS1v1_5Encode() */
/* This function performs the encoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 */
/* Error Returns Meaning */
/* TPM_RC_VALUE message size is too large */
static TPM_RC
RSAES_PKSC1v1_5Encode(
RSAES_PKCS1v1_5Encode(
TPM2B *padded, // OUT: the pad data
TPM2B *message, // IN: the message being padded
RAND_STATE *rand
@ -638,7 +638,7 @@ static TPM_RC
RSASSA_Encode(
TPM2B *pOut, // IN:OUT on in, the size of the public key
// on out, the encoded area
TPM_ALG_ID hashAlg, // IN: hash algorithm for PKSC1v1_5
TPM_ALG_ID hashAlg, // IN: hash algorithm for PKCS1v1_5
TPM2B *hIn // IN: digest value to encode
)
{
@ -863,7 +863,7 @@ CryptRsaEncrypt(
}
break;
case TPM_ALG_RSAES:
retVal = RSAES_PKSC1v1_5Encode(&cOut->b, dIn, rand);
retVal = RSAES_PKCS1v1_5Encode(&cOut->b, dIn, rand);
break;
case TPM_ALG_OAEP:
retVal = OaepEncode(&cOut->b, scheme->details.oaep.hashAlg, label, dIn,
@ -1143,7 +1143,7 @@ CryptRsaGenerateKey(
}
retVal = TPM_RC_SUCCESS;
// Do a trial encryption decryption if this is a signing key
if(publicArea->objectAttributes.sign)
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
{
BN_RSA(temp1);
BN_RSA(temp2);

View File

@ -3,7 +3,7 @@
/* Symmetric block cipher modes */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: CryptSym.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: CryptSym.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -59,98 +59,15 @@
/* */
/********************************************************************************/
/* 10.2.20 CryptSym.c */
/* 10.2.20.1 Introduction */
/* 10.2.19 CryptSym.c */
/* 10.2.19.1 Introduction */
/* This file contains the implementation of the symmetric block cipher modes allowed for a
TPM. These functions only use the single block encryption functions of the selected symmetric
crypto library. */
/* 10.2.20.2 Includes, Defines, and Typedefs */
/* 10.2.19.2 Includes, Defines, and Typedefs */
#include "Tpm.h"
union tpmCryptKeySchedule_t {
#ifdef TPM_ALG_AES
tpmKeyScheduleAES AES;
#endif
#ifdef TPM_ALG_SM4
tpmKeyScheduleSM4 SM4;
#endif
#ifdef TPM_ALG_CAMELLIA
tpmKeyScheduleCAMELLIA CAMELLIA;
#endif
#ifdef TPM_ALG_TDES
tpmKeyScheduleTDES TDES[3];
#endif
#if SYMMETRIC_ALIGNMENT == 8
uint64_t alignment;
#else
uint32_t alignment;
#endif
};
/* Each block cipher within a library is expected to conform to the same calling conventions with
three parameters (keySchedule, in, and out) in the same order. That means that all algorithms
would use the same order of the same parameters. The code is written assuming the (keySchedule,
in, and out) order. However, if the library uses a different order, the order can be changed with
a SWIZZLE macro that puts the parameters in the correct order. Note that all algorithms have to
use the same order and number of parameters because the code to build the calling list is common
for each call to encrypt or decrypt with the algorithm chosen by setting a function pointer to
select the algorithm that is used. */
# define ENCRYPT(keySchedule, in, out) \
encrypt(SWIZZLE(keySchedule, in, out))
# define DECRYPT(keySchedule, in, out) \
decrypt(SWIZZLE(keySchedule, in, out))
/* Note that the macros rely on encrypt as local values in the functions that use these
macros. Those parameters are set by the macro that set the key schedule to be used for the
call. */
#define ENCRYPT_CASE(ALG) \
case TPM_ALG_##ALG: \
TpmCryptSetEncryptKey##ALG(key, keySizeInBits, &keySchedule.ALG); \
encrypt = (TpmCryptSetSymKeyCall_t)TpmCryptEncrypt##ALG; \
break;
#define DECRYPT_CASE(ALG) \
case TPM_ALG_##ALG: \
TpmCryptSetDecryptKey##ALG(key, keySizeInBits, &keySchedule.ALG); \
decrypt = (TpmCryptSetSymKeyCall_t)TpmCryptDecrypt##ALG; \
break;
#ifdef TPM_ALG_AES
#define ENCRYPT_CASE_AES ENCRYPT_CASE(AES)
#define DECRYPT_CASE_AES DECRYPT_CASE(AES)
#else
#define ENCRYPT_CASE_AES
#define DECRYPT_CASE_AES
#endif
#ifdef TPM_ALG_SM4
#define ENCRYPT_CASE_SM4 ENCRYPT_CASE(SM4)
#define DECRYPT_CASE_SM4 DECRYPT_CASE(SM4)
#else
#define ENCRYPT_CASE_SM4
#define DECRYPT_CASE_SM4
#endif
#ifdef TPM_ALG_CAMELLIA
#define ENCRYPT_CASE_CAMELLIA ENCRYPT_CASE(CAMELLIA)
#define DECRYPT_CASE_CAMELLIA DECRYPT_CASE(CAMELLIA)
#else
#define ENCRYPT_CASE_CAMELLIA
#define DECRYPT_CASE_CAMELLIA
#endif
#ifdef TPM_ALG_TDES
#define ENCRYPT_CASE_TDES ENCRYPT_CASE(TDES)
#define DECRYPT_CASE_TDES DECRYPT_CASE(TDES)
#else
#define ENCRYPT_CASE_TDES
#define DECRYPT_CASE_TDES
#endif
/* For each algorithm the case will either be defined or null. */
#define SELECT(direction) \
switch(algorithm) \
{ \
direction##_CASE_AES \
direction##_CASE_SM4 \
direction##_CASE_CAMELLIA \
direction##_CASE_TDES \
default: \
return TPM_RC_FAILURE; \
}
/* 10.2.20.3 Obligatory Initialization Functions */
/* 10.2.20.3.1 CryptSymInit() */
#include "CryptSym.h"
/* 10.2.19.3.1 CryptSymInit() */
/* This function is called to do _TPM_Init() processing */
BOOL
CryptSymInit(
@ -159,7 +76,7 @@ CryptSymInit(
{
return TRUE;
}
/* 10.2.20.3.2 CryptSymStartup() */
/* 10.2.19.3.2 CryptSymStartup() */
/* This function is called to do TPM2_Startup() processing */
BOOL
CryptSymStartup(

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: TpmToOsslDesSupport.c 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: TpmToOsslDesSupport.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */

View File

@ -3,7 +3,7 @@
/* Used to splice the OpenSSL() hash code into the TPM code */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: TpmToOsslHash.h 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: TpmToOsslHash.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -72,9 +72,10 @@
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/ossl_typ.h>
/* Redefine the internal name used for each of the hash state structures to the name used by the
library. These defines need to be known in all parts of the TPM so that the structure sizes
can be properly computed when needed. */
/* B.2.2.1.2. Links to the OpenSSL HASH code */
/* Redefine the internal name used for each of the hash state structures to the name used by the
library. These defines need to be known in all parts of the TPM so that the structure sizes can
be properly computed when needed. */
#define tpmHashStateSHA1_t SHA_CTX
#define tpmHashStateSHA256_t SHA256_CTX
#define tpmHashStateSHA384_t SHA512_CTX
@ -82,9 +83,9 @@
#ifdef TPM_ALG_SM3
# error "The version of OpenSSL used by this code does not support SM3"
#endif
/* The defines below are only needed when compiling CryptHash.c. This isolation is primarily to
avoid name space collision. However, if there is a real collision, it will likely show up
when the linker tries to put things together. */
/* The defines below are only needed when compiling CryptHash.c or CryptSmac.c. This isolation
is primarily to avoid name space collision. However, if there is a real collision, it will
likely show up when the linker tries to put things together. */
#ifdef _CRYPT_HASH_C_
typedef BYTE *PBYTE;
typedef const BYTE *PCBYTE;

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: TpmToOsslMath.c 953 2017-03-06 20:31:40Z kgoldman $ */
/* $Id: TpmToOsslMath.c 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -72,22 +72,6 @@
#include "Tpm.h"
#if MATH_LIB == OSSL
#include "TpmToOsslMath_fp.h"
/* B.2.3.2.3. Functions */
#if 0
INLINE void
SetSizeOsslToTpm(
bigNum a,
BIGNUM *b
)
{
if(a != NULL)
{
pAssert(((crypt_uword_t *)b->d == &a->d[0])
&& ((unsigned)b->top <= a->allocated));
a->size = b->top;
}
}
#endif
/* B.2.3.2.3.1. OsslToTpmBn() */
/* This function converts an OpenSSL() BIGNUM to a TPM bignum. In this implementation it is assumed
that OpenSSL() used the same format for a big number as does the TPM -- an array of native-endian
@ -220,8 +204,11 @@ BnModMult(
pAssert(BnGetAllocated(result) >= BnGetSize(modulus));
OK = BN_mul(bnTemp, bnOp1, bnOp2, CTX);
OK = OK && BN_div(NULL, bnResult, bnTemp, bnMod, CTX);
result->size = bnResult->top;
OsslToTpmBn(result, bnResult);
if(OK)
{
result->size = bnResult->top;
OsslToTpmBn(result, bnResult);
}
OSSL_LEAVE();
return OK;
}
@ -244,13 +231,17 @@ BnMult(
(BITS_TO_CRYPT_WORDS(BnSizeInBits(multiplicand)
+ BnSizeInBits(multiplier))));
OK = BN_mul(bnTemp, bnA, bnB, CTX);
OsslToTpmBn(temp, bnTemp);
if(OK)
{
OsslToTpmBn(temp, bnTemp);
BnCopy(result, temp);
}
OSSL_LEAVE();
BnCopy(result, temp);
return OK;
}
/* B.2.3.2.3.4. BnDiv() */
/* This function divides two bigNum values. The function always returns TRUE. */
/* This function divides two bigNum values. The function returns FALSE if there is an error in the
operation. */
LIB_EXPORT BOOL
BnDiv(
bigNum quotient,
@ -282,8 +273,11 @@ BnDiv(
pAssert((remainder == NULL)
|| (remainder->allocated >= divisor->size));
OK = BN_div(bnQ, bnR, bnDend, bnSor, CTX);
OsslToTpmBn(quotient, bnQ);
OsslToTpmBn(remainder, bnR);
if(OK)
{
OsslToTpmBn(quotient, bnQ);
OsslToTpmBn(remainder, bnR);
}
}
DEBUG_PRINT("In BnDiv:\n");
BIGNUM_PRINT(" bnDividend: ", bnDend, TRUE);
@ -310,8 +304,11 @@ BnGcd(
BOOL OK;
pAssert(gcd != NULL);
OK = BN_gcd(bnGcd, bn1, bn2, CTX);
OsslToTpmBn(gcd, bnGcd);
gcd->size = bnGcd->top;
if(OK)
{
OsslToTpmBn(gcd, bnGcd);
gcd->size = bnGcd->top;
}
OSSL_LEAVE();
return OK;
}
@ -334,7 +331,10 @@ BnModExp(
BOOL OK;
//
OK = BN_mod_exp(bnResult, bnN, bnE, bnM, CTX);
OsslToTpmBn(result, bnResult);
if(OK)
{
OsslToTpmBn(result, bnResult);
}
OSSL_LEAVE();
return OK;
}
@ -353,7 +353,10 @@ BnModInverse(
BIG_INITIALIZED(bnM, modulus);
BOOL OK;
OK = (BN_mod_inverse(bnResult, bnN, bnM, CTX) != NULL);
OsslToTpmBn(result, bnResult);
if(OK)
{
OsslToTpmBn(result, bnResult);
}
OSSL_LEAVE();
return OK;
}

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: TpmToOsslMath.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: TpmToOsslMath.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -73,7 +73,8 @@
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
/* Make sure that the library is using the correct size for a crypt word */
/* B.2.2.2.2. Macros and Defines */
/* Make sure that the library is using the correct size for a crypt word */
#if defined THIRTY_TWO_BIT && (RADIX_BITS != 32) \
|| defined SIXTY_FOUR_BIT && (RADIX_BITS != 64)
# error "Ossl library is using different radix"

View File

@ -1,9 +1,9 @@
/********************************************************************************/
/* */
/* */
/* Splice the OpenSSL() library into the TPM code. */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: TpmToOsslSym.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: TpmToOsslSym.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -55,7 +55,7 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 */
/* (c) Copyright IBM Corp. and others, 2016, 2017 */
/* */
/********************************************************************************/
@ -74,6 +74,7 @@
#include <openssl/des.h>
#include <openssl/bn.h>
#include <openssl/ossl_typ.h>
/* B.2.2.3.2. Links to the OpenSSL AES code */
#ifdef TPM_ALG_SM4
#error "SM4 is not available"
#endif

View File

@ -3,7 +3,7 @@
/* */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: swap.h 809 2016-11-16 18:31:54Z kgoldman $ */
/* $Id: swap.h 1047 2017-07-20 18:27:34Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -62,7 +62,7 @@
#ifndef SWAP_H
#define SWAP_H
#if LITTLE_ENDIAN_TPM == YES
#if LITTLE_ENDIAN_TPM
#define TO_BIG_ENDIAN_UINT16(i) REVERSE_ENDIAN_16(i)
#define FROM_BIG_ENDIAN_UINT16(i) REVERSE_ENDIAN_16(i)
#define TO_BIG_ENDIAN_UINT32(i) REVERSE_ENDIAN_32(i)