diff --git a/src/tpm2/AttestationCommands.c b/src/tpm2/AttestationCommands.c index 07ed5624..c1faf8eb 100644 --- a/src/tpm2/AttestationCommands.c +++ b/src/tpm2/AttestationCommands.c @@ -1,3 +1,4 @@ + /********************************************************************************/ /* */ /* Attestation Commands */ @@ -22,7 +23,7 @@ /* */ /* 2. Source Code Distribution Conditions: */ /* */ -/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* - 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 */ diff --git a/src/tpm2/Global.h b/src/tpm2/Global.h index 84a0d13e..901c0248 100644 --- a/src/tpm2/Global.h +++ b/src/tpm2/Global.h @@ -3,7 +3,6 @@ /* Internal Global Type Definitions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ -/* $Id: Global.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ @@ -55,7 +54,7 @@ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ -/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* (c) Copyright IBM Corp. and others, 2016 - 2023 */ /* */ /********************************************************************************/ @@ -222,9 +221,9 @@ typedef struct OBJECT OBJECT_ATTRIBUTES attributes; // object attributes TPMT_PUBLIC publicArea; // public area of an object TPMT_SENSITIVE sensitive; // sensitive area of an object -#if ALG_RSA +#if ALG_RSA // libtpms added begin: keep privateExponent_t privateExponent; // Additional field for the private -#endif +#endif // libtpms added end TPM2B_NAME qualifiedName; // object qualified name TPMI_DH_OBJECT evictHandle; // if the object is an evict object, // the original handle is kept here. @@ -480,7 +479,7 @@ typedef UINT32 NV_REF; typedef BYTE *NV_RAM_REF; /* 5.9.8.3 NV_PIN */ -/* This structure deals with the possible endianness differences between the canonical form of the +/* This structure deals with the possible endianess differences between the canonical form of the TPMS_NV_PIN_COUNTER_PARAMETERS structure and the internal value. The structures allow the data in a PIN index to be read as an 8-octet value using NvReadUINT64Data(). That function will byte swap all the values on a little endian system. This will put the bytes with the 4-octet values in the diff --git a/src/tpm2/HierarchyCommands.c b/src/tpm2/HierarchyCommands.c index cbf777dc..52461902 100644 --- a/src/tpm2/HierarchyCommands.c +++ b/src/tpm2/HierarchyCommands.c @@ -281,7 +281,7 @@ TPM2_SetPrimaryPolicy( break; FOR_EACH_ACT(SET_ACT_POLICY) - + default: FAIL(FATAL_ERROR_INTERNAL); break; @@ -512,3 +512,4 @@ TPM2_HierarchyChangeAuth( return TPM_RC_SUCCESS; } #endif // CC_HierarchyChangeAuth + diff --git a/src/tpm2/RandomCommands.c b/src/tpm2/RandomCommands.c index b6573a5d..315232da 100644 --- a/src/tpm2/RandomCommands.c +++ b/src/tpm2/RandomCommands.c @@ -1,9 +1,9 @@ /********************************************************************************/ /* */ -/* */ +/* Random Number Generator */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ -/* $Id: RandomCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* $Id: RandomCommands.c 1671 2021-06-03 18:30:41Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ diff --git a/src/tpm2/SigningCommands.c b/src/tpm2/SigningCommands.c index 529c40c7..2699b454 100644 --- a/src/tpm2/SigningCommands.c +++ b/src/tpm2/SigningCommands.c @@ -117,7 +117,7 @@ TPM2_Sign( // Input Validation if(!IsSigningObject(signObject)) return TPM_RCS_KEY + RC_Sign_keyHandle; - + // A key that will be used for x.509 signatures can't be used in TPM2_Sign(). if(IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, x509sign)) return TPM_RCS_ATTRIBUTES + RC_Sign_keyHandle; diff --git a/src/tpm2/TPMCmdp.c b/src/tpm2/TPMCmdp.c index 041b7803..3e77a29d 100644 --- a/src/tpm2/TPMCmdp.c +++ b/src/tpm2/TPMCmdp.c @@ -155,7 +155,9 @@ _rpc__ForceFailureMode( void ) { +#if SIMULATION SetForceFailureMode(); +#endif return; } /* D.4.3.5. _rpc__Signal_PhysicalPresenceOn() */ diff --git a/src/tpm2/TestingCommands.c b/src/tpm2/TestingCommands.c index 27a23529..6a8bc512 100644 --- a/src/tpm2/TestingCommands.c +++ b/src/tpm2/TestingCommands.c @@ -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-2018 */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ diff --git a/src/tpm2/TpmSizeChecks.c b/src/tpm2/TpmSizeChecks.c index 01d07771..7785ec1b 100644 --- a/src/tpm2/TpmSizeChecks.c +++ b/src/tpm2/TpmSizeChecks.c @@ -72,7 +72,9 @@ extern uint32_t MarshalDataSize; #endif +#if DEBUG static int once = 0; +#endif //** TpmSizeChecks() // This function is used during the development process to make sure that the diff --git a/src/tpm2/crypto/CryptPrimeSieve_fp.h b/src/tpm2/crypto/CryptPrimeSieve_fp.h index 66639a38..56f111e5 100644 --- a/src/tpm2/crypto/CryptPrimeSieve_fp.h +++ b/src/tpm2/crypto/CryptPrimeSieve_fp.h @@ -3,7 +3,7 @@ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ -/* $Id: CryptPrimeSieve_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ +/* $Id: CryptPrimeSieve_fp.h 809M 2021-01-21 21:40:52Z (local) $ */ /* */ /* 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 - 2021 */ /* */ /********************************************************************************/ diff --git a/src/tpm2/crypto/CryptRsa_fp.h b/src/tpm2/crypto/CryptRsa_fp.h index ff5527f0..47ca40f2 100644 --- a/src/tpm2/crypto/CryptRsa_fp.h +++ b/src/tpm2/crypto/CryptRsa_fp.h @@ -3,7 +3,6 @@ /* Implementation of cryptographic primitives for RSA */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ -/* $Id: CryptRsa_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ @@ -55,7 +54,7 @@ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ -/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* (c) Copyright IBM Corp. and others, 2016 - 2023 */ /* */ /********************************************************************************/ diff --git a/src/tpm2/crypto/openssl/CryptRsa.c b/src/tpm2/crypto/openssl/CryptRsa.c index c140e80a..d3b93447 100644 --- a/src/tpm2/crypto/openssl/CryptRsa.c +++ b/src/tpm2/crypto/openssl/CryptRsa.c @@ -3,7 +3,6 @@ /* Implementation of cryptographic primitives for RSA */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ -/* $Id: CryptRsa.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ @@ -55,7 +54,7 @@ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ -/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* (c) Copyright IBM Corp. and others, 2016 - 2023 */ /* */ /********************************************************************************/ @@ -92,6 +91,12 @@ CryptRsaStartup( return TRUE; } /* 10.2.17.4 Internal Functions */ + +/* 10.2.17.4.1 RsaInitializeExponent() */ +/* This function initializes the bignum data structure that holds the private exponent. This + function returns the pointer to the private exponent value so that it can be used in an + initializer for a data declaration */ + void RsaInitializeExponent( privateExponent_t *pExp @@ -102,7 +107,83 @@ RsaInitializeExponent( BN_INIT(pExp->dQ); BN_INIT(pExp->qInv); } -/* 10.2.17.4.1 ComputePrivateExponent() */ + +#if 0 // libtpms added +/* 10.2.17.4.2 MakePgreaterThanQ() */ +/* This function swaps the pointers for P and Q if Q happens to be larger than Q. */ +static void +MakePgreaterThanQ( + privateExponent *Z + ) +{ + if(BnUnsignedCmp(Z->P, Z->Q) < 0) + { + bigNum bnT = Z->P; + Z->P = Z->Q; + Z->Q = bnT; + } +} + +/* 10.2.17.4.3 PackExponent() */ +/* This function takes the bignum private exponent and converts it into TPM2B form. In this form, + the size field contains the overall size of the packed data. The buffer contains 5, equal sized + values in P, Q, dP, dQ, qInv order. For example, if a key has a 2Kb public key, then the packed + private key will contain 5, 1Kb values. This form makes it relatively easy to load and save the + values without changing the normal unmarshaling to do anything more than allow a larger TPM2B for + the private key. Also, when exporting the value, all that is needed is to change the size field + of the private key in order to save just the P value. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) failure -- The data is too big to fit */ +static BOOL +PackExponent( + TPM2B_PRIVATE_KEY_RSA *packed, + privateExponent *Z + ) +{ + int i; + UINT16 primeSize = (UINT16)BITS_TO_BYTES(BnMsb(Z->P)); + UINT16 pS = primeSize; + // + pAssert((primeSize * 5) <= sizeof(packed->t.buffer)); + packed->t.size = (primeSize * 5) + RSA_prime_flag; + for(i = 0; i < 5; i++) + if(!BnToBytes((bigNum)&Z->entries[i], &packed->t.buffer[primeSize * i], &pS)) + return FALSE; + if(pS != primeSize) + return FALSE; + return TRUE; +} +/* 10.2.17.4.4 UnpackExponent() */ +/* This function unpacks the private exponent from its TPM2B form into its bignum form. */ +/* Return Value Meaning */ +/* TRUE(1) success */ +/* FALSE(0) TPM2B is not the correct size */ +static BOOL +UnpackExponent( + TPM2B_PRIVATE_KEY_RSA *b, + privateExponent *Z + ) +{ + UINT16 primeSize = b->t.size & ~RSA_prime_flag; + int i; + bigNum *bn = &Z->P; + // + VERIFY(b->t.size & RSA_prime_flag); + RsaInitializeExponent(Z); + VERIFY((primeSize % 5) == 0); + primeSize /= 5; + for(i = 0; i < 5; i++) + VERIFY(BnFromBytes(bn[i], &b->t.buffer[primeSize * i], primeSize) + != NULL); + MakePgreaterThanQ(Z); + return TRUE; + Error: + return FALSE; +} +#endif // libtpms added + +/* 10.2.17.4.5 ComputePrivateExponent() */ /* This function computes the private exponent from the primes. */ /* Return Value Meaning */ /* TRUE(1) success */ @@ -144,7 +225,8 @@ ComputePrivateExponent( BnSetWord(Q, 0); return pOK && qOK; } -/* 10.2.17.4.2 RsaPrivateKeyOp() */ + +/* 10.2.17.4.6 RsaPrivateKeyOp() */ /* This function is called to do the exponentiation with the private key. Compile options allow use of the simple (but slow) private exponent, or the more complex but faster CRT method. */ /* Return Value Meaning */ @@ -189,7 +271,8 @@ RsaPrivateKeyOp( Error: return FALSE; } -/* 10.2.17.4.3 RSAEP() */ + +/* 10.2.17.4.7 RSAEP() */ /* This function performs the RSAEP operation defined in PKCS#1v2.1. It is an exponentiation of a value (m) with the public exponent (e), modulo the public (n). */ /* Error Returns Meaning */ @@ -222,7 +305,8 @@ RSAEP( key->publicArea.unique.rsa.t.size, key->publicArea.unique.rsa.t.buffer); } -/* 10.2.17.4.4 RSADP() */ + +/* 10.2.17.4.8 RSADP() */ /* This function performs the RSADP operation defined in PKCS#1v2.1. It is an exponentiation of a value (c) with the private exponent (d), modulo the public modulus (n). The decryption is in place. */ @@ -258,7 +342,8 @@ RSADP( Error: return TPM_RC_FAILURE; } -/* 10.2.17.4.5 OaepEncode() */ + +/* 10.2.17.4.9 OaepEncode() */ /* This function performs OAEP padding. The size of the buffer to receive the OAEP padded data must equal the size of the modulus */ /* Error Returns Meaning */ @@ -282,32 +367,40 @@ OaepEncode( BYTE *pp; BYTE *pm; TPM_RC retVal = TPM_RC_SUCCESS; + pAssert(padded != NULL && message != NULL); + // A value of zero is not allowed because the KDF can't produce a result // if the digest size is zero. if(hLen == 0) return TPM_RC_VALUE; + // Basic size checks // make sure digest isn't too big for key size if(padded->size < (2 * hLen) + 2) ERROR_RETURN(TPM_RC_HASH); + // and that message will fit messageSize <= k - 2hLen - 2 if(message->size > (padded->size - (2 * hLen) - 2)) ERROR_RETURN(TPM_RC_VALUE); + // Hash L even if it is null // Offset into padded leaving room for masked seed and byte of zero pp = &padded->buffer[hLen + 1]; if(CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer, hLen, pp) != hLen) ERROR_RETURN(TPM_RC_FAILURE); + // concatenate PS of k mLen 2hLen 2 padLen = padded->size - message->size - (2 * hLen) - 2; MemorySet(&pp[hLen], 0, padLen); pp[hLen + padLen] = 0x01; padLen += 1; memcpy(&pp[hLen + padLen], message->buffer, message->size); + // The total size of db = hLen + pad + mSize; dbSize = hLen + padLen + message->size; + // If testing, then use the provided seed. Otherwise, use values // from the RNG CryptRandomGenerate(hLen, mySeed); @@ -316,14 +409,17 @@ OaepEncode( ERROR_RETURN(TPM_RC_FAILURE); // mask = MGF1 (seed, nSize hLen 1) CryptMGF_KDF(dbSize, mask, hashAlg, hLen, seed, 0); + // Create the masked db pm = mask; for(i = dbSize; i > 0; i--) *pp++ ^= *pm++; pp = &padded->buffer[hLen + 1]; + // Run the masked data through MGF1 if(CryptMGF_KDF(hLen, &padded->buffer[1], hashAlg, dbSize, pp, 0) != (unsigned)hLen) ERROR_RETURN(TPM_RC_VALUE); + // Now XOR the seed to create masked seed pp = &padded->buffer[1]; pm = seed; @@ -334,7 +430,7 @@ OaepEncode( Exit: return retVal; } -/* 10.2.17.4.6 OaepDecode() */ +/* 10.2.17.4.10 OaepDecode() */ /* This function performs OAEP padding checking. The size of the buffer to receive the recovered data. If the padding is not valid, the dSize size is set to zero and the function returns TPM_RC_VALUE. */ @@ -354,6 +450,7 @@ OaepDecode( UINT32 i; BYTE seedMask[MAX_DIGEST_SIZE]; UINT32 hLen = CryptHashGetDigestSize(hashAlg); + BYTE mask[MAX_RSA_KEY_BYTES]; BYTE *pp; BYTE *pm; @@ -364,21 +461,28 @@ OaepDecode( ERROR_RETURN(TPM_RC_VALUE); // Use the hash size to determine what to put through MGF1 in order // to recover the seedMask - CryptMGF_KDF(hLen, seedMask, hashAlg, padded->size - hLen - 1, + CryptMGF_KDF(hLen, + seedMask, + hashAlg, + padded->size - hLen - 1, &padded->buffer[hLen + 1], 0); + // Recover the seed into seedMask pAssert(hLen <= sizeof(seedMask)); pp = &padded->buffer[1]; pm = seedMask; for(i = hLen; i > 0; i--) *pm++ ^= *pp++; + // Use the seed to generate the data mask CryptMGF_KDF(padded->size - hLen - 1, mask, hashAlg, hLen, seedMask, 0); + // Use the mask generated from seed to recover the padded data pp = &padded->buffer[hLen + 1]; pm = mask; for(i = (padded->size - hLen - 1); i > 0; i--) *pm++ ^= *pp++; + // Make sure that the recovered data has the hash of the label // Put trial value in the seed mask if((CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer, @@ -386,6 +490,7 @@ OaepDecode( FAIL(FATAL_ERROR_INTERNAL); if(memcmp(seedMask, mask, hLen) != 0) ERROR_RETURN(TPM_RC_VALUE); + // find the start of the data pm = &mask[hLen]; for(i = (UINT32)padded->size - (2 * hLen) - 1; i > 0; i--) @@ -396,6 +501,7 @@ OaepDecode( // If we ran out of data or didn't end with 0x01, then return an error if(i == 0 || pm[-1] != 0x01) ERROR_RETURN(TPM_RC_VALUE); + // pm should be pointing at the first part of the data // and i is one greater than the number of bytes to move i--; @@ -409,7 +515,8 @@ OaepDecode( dataOut->size = 0; return retVal; } -/* 10.2.17.4.7 PKCS1v1_5Encode() */ + +/* 10.2.17.4.11 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 */ @@ -425,11 +532,13 @@ RSAES_PKCS1v1_5Encode( if(message->size > padded->size - 11) return TPM_RC_VALUE; // move the message to the end of the buffer - memcpy(&padded->buffer[padded->size - message->size], message->buffer, + memcpy(&padded->buffer[padded->size - message->size], + message->buffer, message->size); // Set the first byte to 0x00 and the second to 0x02 padded->buffer[0] = 0; padded->buffer[1] = 2; + // Fill with random bytes DRBG_Generate(rand, &padded->buffer[2], (UINT16)ps); if(g_inFailureMode) @@ -437,6 +546,7 @@ RSAES_PKCS1v1_5Encode( // Set the delimiter for the random field to 0 padded->buffer[2 + ps] = 0; + // Now, the only messy part. Make sure that all the 'ps' bytes are non-zero // In this implementation, use the value of the current index for(ps++; ps > 1; ps--) @@ -448,7 +558,7 @@ RSAES_PKCS1v1_5Encode( } return TPM_RC_SUCCESS; } -/* 10.2.17.4.8 RSAES_Decode() */ +/* 10.2.17.4.12 RSAES_Decode() */ /* This function performs the decoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 */ /* Error Returns Meaning */ /* TPM_RC_FAIL decoding error or results would no fit into provided buffer */ @@ -470,6 +580,7 @@ RSAES_Decode( break; } pSize++; + // Make sure that pSize has not gone over the end and that there are at least 8 // bytes of pad data. fail = (pSize > coded->size) | fail; @@ -486,10 +597,8 @@ RSAES_Decode( /* This function computes the salt size used in PSS. It is broken out so that the X509 code can get the same value that is used by the encoding function in this module. */ INT16 -CryptRsaPssSaltSize( - INT16 hashSize, - INT16 outSize -) +CryptRsaPssSaltSize(INT16 hashSize, + INT16 outSize) { INT16 saltSize; // @@ -505,7 +614,7 @@ CryptRsaPssSaltSize( } #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added -/* 10.2.17.4.9 PssEncode() */ +/* 10.2.17.4.14 PssEncode() */ /* This function creates an encoded block of data that is the size of modulus. The function uses the maximum salt size that will fit in the encoded block. */ /* Returns TPM_RC_SUCCESS or goes into failure mode. */ @@ -524,8 +633,10 @@ PssEncode( BYTE *pOut; UINT16 mLen; HASH_STATE hashState; + // These are fatal errors indicating bad TPM firmware pAssert(out != NULL && hLen > 0 && digest != NULL); + // Get the size of the mask mLen = (UINT16)(out->size - hLen - 1); @@ -536,6 +647,7 @@ PssEncode( // Set the first 8 bytes to zero pOut = out->buffer; memset(pOut, 0, 8); + // Get set the salt DRBG_Generate(rand, salt, saltSize); if(g_inFailureMode) @@ -547,24 +659,31 @@ PssEncode( CryptDigestUpdate2B(&hashState, digest); CryptDigestUpdate(&hashState, saltSize, salt); CryptHashEnd(&hashState, hLen, &pOut[out->size - hLen - 1]); + // Create a mask if(CryptMGF_KDF(mLen, pOut, hashAlg, hLen, &pOut[mLen], 0) != mLen) FAIL(FATAL_ERROR_INTERNAL); + // Since this implementation uses key sizes that are all even multiples of // 8, just need to make sure that the most significant bit is CLEAR *pOut &= 0x7f; + // Before we mess up the pOut value, set the last byte to 0xbc pOut[out->size - 1] = 0xbc; + // XOR a byte of 0x01 at the position just before where the salt will be XOR'ed pOut = &pOut[mLen - saltSize - 1]; *pOut++ ^= 0x01; + // XOR the salt data into the buffer for(; saltSize > 0; saltSize--) *pOut++ ^= *ps++; + // and we are done return TPM_RC_SUCCESS; } -/* 10.2.17.4.10 PssDecode() */ + +/* 10.2.17.4.15 PssDecode() */ /* This function checks that the PSS encoded block was built from the provided digest. If the check is successful, TPM_RC_SUCCESS is returned. Any other value indicates an error. */ /* This implementation of PSS decoding is intended for the reference TPM implementation and is not @@ -594,19 +713,25 @@ PssDecode( // These errors are indicative of failures due to programmer error pAssert(dIn != NULL && eIn != NULL); pe = eIn->buffer; + // check the hash scheme if(hLen == 0) ERROR_RETURN(TPM_RC_SCHEME); + // most significant bit must be zero fail = pe[0] & 0x80; + // last byte must be 0xbc fail |= pe[eIn->size - 1] ^ 0xbc; + // Use the hLen bytes at the end of the buffer to generate a mask // Doesn't start at the end which is a flag byte mLen = eIn->size - hLen - 1; CryptMGF_KDF(mLen, mask, hashAlg, hLen, &pe[mLen], 0); + // Clear the MSO of the mask to make it consistent with the encoding. mask[0] &= 0x7F; + pAssert(mLen <= sizeof(mask)); // XOR the data into the mask to recover the salt. This sequence // advances eIn so that it will end up pointing to the seed data @@ -640,20 +765,26 @@ PssDecode( // i contains the salt size and pm points to the salt. Going to use the input // hash and the seed to recreate the hash in the lower portion of eIn. CryptHashStart(&hashState, hashAlg); + // add the pad of 8 zeros CryptDigestUpdate(&hashState, 8, pad); + // add the provided digest value CryptDigestUpdate(&hashState, dIn->size, dIn->buffer); + // and the salt CryptDigestUpdate(&hashState, i, pm); + // get the result fail |= (CryptHashEnd(&hashState, hLen, mask) != hLen); + // Compare all bytes for(pm = mask; hLen > 0; hLen--) // don't use fail = because that could skip the increment and compare // operations after the first failure and that gives away timing // information. fail |= *pm++ ^ *pe++; + retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS; Exit: return retVal; @@ -694,13 +825,13 @@ MakeDerTag( buffer += oidSize; *buffer++ = 0x05; // Add a NULL *buffer++ = 0x00; - + *buffer++ = 0x04; *buffer++ = (BYTE)(info->digestSize); return oidSize + 8; Error: return 0; - + } /* 10.2.17.4.17 RSASSA_Encode() */ @@ -723,22 +854,22 @@ RSASSA_Encode( BYTE *eOut; INT32 fillSize; TPM_RC retVal = TPM_RC_SUCCESS; - + // Can't use this scheme if the algorithm doesn't have a DER string defined. if(derSize == 0) ERROR_RETURN(TPM_RC_SCHEME); - + // If the digest size of 'hashAl' doesn't match the input digest size, then // the DER will misidentify the digest so return an error if(CryptHashGetDigestSize(hashAlg) != hIn->size) ERROR_RETURN(TPM_RC_VALUE); fillSize = pOut->size - derSize - hIn->size - 3; eOut = pOut->buffer; - + // Make sure that this combination will fit in the provided space if(fillSize < 8) ERROR_RETURN(TPM_RC_SIZE); - + // Start filling *eOut++ = 0; // initial byte of zero *eOut++ = 1; // byte of 0x01 @@ -776,21 +907,21 @@ RSASSA_Decode( TPM_RC retVal; BYTE *digest; UINT16 digestSize; - + pAssert(hIn != NULL && eIn != NULL); pe = eIn->buffer; - + // Can't use this scheme if the algorithm doesn't have a DER string // defined or if the provided hash isn't the right size if(derSize == 0 || (unsigned)hashSize != hIn->size) ERROR_RETURN(TPM_RC_SCHEME); - + // Make sure that this combination will fit in the provided space // Since no data movement takes place, can just walk though this // and accept nearly random values. This can only be called from // CryptValidateSignature() so eInSize is known to be in range. fillSize = eIn->size - derSize - hashSize - 3; - + // Start checking (fail will become non-zero if any of the bytes do not have // the expected value. fail = *pe++; // initial byte of zero @@ -810,7 +941,7 @@ RSASSA_Decode( } #endif // libtpms added -/* 10.2.17.4.13 CryptRsaSelectScheme() */ +/* 10.2.17.5.1 CryptRsaSelectScheme() */ /* This function is used by TPM2_RSA_Decrypt() and TPM2_RSA_Encrypt(). It sets up the rules to select a scheme between input and object default. This function assume the RSA object is loaded. If a default scheme is defined in object, the default scheme should be chosen, otherwise, @@ -856,7 +987,7 @@ CryptRsaSelectScheme( // two different, incompatible schemes specified will return NULL return retVal; } -/* 10.2.17.4.14 CryptRsaLoadPrivateExponent() */ +/* 10.2.17.5.2 CryptRsaLoadPrivateExponent() */ /* Error Returns Meaning */ /* TPM_RC_BINDING public and private parts of rsaKey are not matched */ TPM_RC @@ -891,7 +1022,8 @@ CryptRsaLoadPrivateExponent( return retVal; } #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added -/* 10.2.17.4.15 CryptRsaEncrypt() */ + +/* 10.2.17.5.3 CryptRsaEncrypt() */ /* This is the entry point for encryption using RSA. Encryption is use of the public exponent. The padding parameter determines what padding will be used. */ /* The cOutSize parameter must be at least as large as the size of the key. */ @@ -970,7 +1102,7 @@ CryptRsaEncrypt( Exit: return retVal; } -/* 10.2.17.4.16 CryptRsaDecrypt() */ +/* 10.2.17.5.4 CryptRsaDecrypt() */ /* This is the entry point for decryption using RSA. Decryption is use of the private exponent. The padType parameter determines what padding was used. */ /* Error Returns Meaning */ @@ -1021,7 +1153,7 @@ CryptRsaDecrypt( Exit: return retVal; } -/* 10.2.17.4.17 CryptRsaSign() */ +/* 10.2.17.5.5 CryptRsaSign() */ /* This function is used to generate an RSA signature of the type indicated in scheme. */ /* Error Returns Meaning */ /* TPM_RC_SCHEME scheme or hashAlg are not supported */ @@ -1066,7 +1198,7 @@ CryptRsaSign( } return retVal; } -/* 10.2.17.4.18 CryptRsaValidateSignature() */ +/* 10.2.17.5.6 CryptRsaValidateSignature() */ /* This function is used to validate an RSA signature. If the signature is valid TPM_RC_SUCCESS is returned. If the signature is not valid, TPM_RC_SIGNATURE is returned. Other return codes indicate either parameter problems or fatal errors. */ @@ -1126,7 +1258,7 @@ int GetCachedRsaKey(OBJECT *key, RAND_STATE *rand); #else #define GET_CACHED_KEY(key, rand) #endif -/* 10.2.17.4.19 CryptRsaGenerateKey() */ +/* 10.2.17.5.7 CryptRsaGenerateKey() */ /* Generate an RSA key from a provided seed */ /* Error Returns Meaning */ /* TPM_RC_CANCELED operation was canceled */ @@ -1153,7 +1285,6 @@ CryptRsaGenerateKey( // pAssert(publicArea == &rsaKey->publicArea && sensitive == &rsaKey->sensitive); // libtpms added: consistency check - // Need to make sure that the caller did not specify an exponent that is // not supported e = publicArea->parameters.rsaDetail.exponent; @@ -1175,12 +1306,15 @@ CryptRsaGenerateKey( || (keySizeInBits > MAX_RSA_KEY_BITS) // this might be redundant, but... || (keySizeInBits == 0)) ERROR_RETURN(TPM_RC_VALUE); + // Set the prime size for instrumentation purposes INSTRUMENT_SET(PrimeIndex, PRIME_INDEX(keySizeInBits / 2)); + #if SIMULATION && USE_RSA_KEY_CACHE if(GET_CACHED_KEY(publicArea, sensitive, rand)) return TPM_RC_SUCCESS; #endif + // Make sure that key generation has been tested TEST(TPM_ALG_NULL); #if USE_OPENSSL_FUNCTIONS_RSA // libtpms added begin @@ -1189,6 +1323,7 @@ CryptRsaGenerateKey( #endif // libtpms added end // Need to initialize the privateExponent structure RsaInitializeExponent(&rsaKey->privateExponent); + // The prime is computed in P. When a new prime is found, Q is checked to // see if it is zero. If so, P is copied to Q and a new P is found. // When both P and Q are non-zero, the modulus and @@ -1208,6 +1343,7 @@ CryptRsaGenerateKey( goto Exit; } INSTRUMENT_INC(PrimeCounts[PrimeIndex]); + // If this is the second prime, make sure that it differs from the // first prime by at least 2^100 if(BnEqualZero(bnQ)) @@ -1224,6 +1360,7 @@ CryptRsaGenerateKey( BnSub(bnD, bnP, bnQ); if(BnMsb(bnD) < 100) continue; + //Form the public modulus and set the unique value BnMult(bnN, bnP, bnQ); BnTo2B(bnN, &publicArea->unique.rsa.b, @@ -1235,6 +1372,7 @@ CryptRsaGenerateKey( if(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0) || ((sensitive->sensitive.rsa.t.buffer[0] & 0x80) == 0)) FAIL(FATAL_ERROR_INTERNAL); + // Make sure that we can form the private exponent values if(ComputePrivateExponent(bnP, bnQ, bnPubExp, &rsaKey->privateExponent) != TRUE) { @@ -1252,6 +1390,7 @@ CryptRsaGenerateKey( BN_RSA(temp1); BN_RSA(temp2); BnGenerateRandomInRange(temp1, bnN, rand); + // Encrypt with public exponent... BnModExp(temp2, temp1, bnPubExp, bnN); // ... then decrypt with private exponent diff --git a/src/tpm2/crypto/openssl/TpmToOsslMath.h b/src/tpm2/crypto/openssl/TpmToOsslMath.h index 47333c73..56c6611b 100644 --- a/src/tpm2/crypto/openssl/TpmToOsslMath.h +++ b/src/tpm2/crypto/openssl/TpmToOsslMath.h @@ -3,7 +3,6 @@ /* TPM to OpenSSL BigNum Shim Layer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ -/* $Id: TpmToOsslMath.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ @@ -55,7 +54,7 @@ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ -/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* (c) Copyright IBM Corp. and others, 2016 - 2023 */ /* */ /********************************************************************************/ @@ -74,15 +73,20 @@ #define SYMMETRIC_ALIGNMENT RADIX_BYTES #if 0 // libtpms added -#if OPENSSL_VERSION_NUMBER >= 0x10200000L -// Check the bignum_st definition in crypto/bn/bn_lcl.h and either update the -// version check or provide the new definition for this version. +/* + * As of release 3.0.0, OPENSSL_VERSION_NUMBER is a combination of the + * major (M), minor (NN) and patch (PP) version into a single integer 0xMNN00PP0L + */ +#if OPENSSL_VERSION_NUMBER > 0x30100ff0L +// Check the bignum_st definition in crypto/bn/bn_lcl.h or crypto/bn/bn_local.h and either update +// the version check or provide the new definition for this version. +// Currently safe for all 3.1.x # error Untested OpenSSL version #elif OPENSSL_VERSION_NUMBER >= 0x10100000L // from crypto/bn/bn_lcl.h struct bignum_st { BN_ULONG *d; - int top; + int top; int dmax; int neg; diff --git a/src/tpm2/crypto/openssl/TpmToOsslSym.h b/src/tpm2/crypto/openssl/TpmToOsslSym.h index 3419b459..276ebddd 100644 --- a/src/tpm2/crypto/openssl/TpmToOsslSym.h +++ b/src/tpm2/crypto/openssl/TpmToOsslSym.h @@ -3,7 +3,7 @@ /* Splice the OpenSSL() library into the TPM code. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ -/* $Id: TpmToOsslSym.h 1619 2020-05-19 16:51:47Z kgoldman $ */ +/* $Id: TpmToOsslSym.h 1619M 2021-01-19 21:39:42Z (local) $ */ /* */ /* 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 - 2020 */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/