From 36d1e033688c79efe2374e43667ee5451ebf6f16 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Mon, 28 Aug 2023 12:14:38 -0400 Subject: [PATCH] tpm2: Use new privateExponent also for dP, dQ, and qInv Also use the new privatExponent for dP, dQ and qInv. There are two functions that need to be adapted: - ComputePrivateExponent: producer of these parameters - RsaPrivateKeyOp : consumer of these parameters ComputePrivateExponent is converted to store the results into Z->dP, Z->dQ, and Z->qInv. Therefore, remove the old privateExponent parameter *pExp, that was previously used to store them, from the signature of this function and pull out the initialization of pExp and preservation of Q to be done before calling this function. This is done in the 2 calling functions. After returning from the function copy the values of Z->dP, Z->dQ, and Z->qInv to the old privateExponent where the results had been stored previously and where we need to have them. This change results in a sequence like this for the 2 callers: RsaInitializeExponentOld(&rsaKey->privateExponent); BnCopy((bigNum)&rsaKey->privateExponent.Q, Z->Q); // preserve Q VERIFY(ComputePrivateExponent(bnE, Z)); RsaSetExponentOld(&rsaKey->privateExponent, Z); // duplicate dP, dQ, qInv The values for dP, dQ, ad qInv are consumed by RsaPrivateKeyOp. Therefore, adjust this functions signature by removing the old privateExponent parameter *pExp from it and make sure that callers initialize Z->dP, Z->dQ, and Z->qInv before calling this functions. There are two call-sites where the one in RSADP looks like this: RsaSetExponentFromOld(Z, &key->privateExponent); // copy Q, dP, dQ, qInv to Z VERIFY(RsaPrivateKeyOp(bnM, Z)); The call site in CryptRsaGenerateKey has called ComputePrivateExponent before, therefore it already holds the values in Z. Signed-off-by: Stefan Berger --- src/tpm2/crypto/CryptRsa.h | 33 ++++++++++++++++--- src/tpm2/crypto/openssl/CryptRsa.c | 53 +++++++++++++++++------------- 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/src/tpm2/crypto/CryptRsa.h b/src/tpm2/crypto/CryptRsa.h index 325eb899..e893f2ac 100644 --- a/src/tpm2/crypto/CryptRsa.h +++ b/src/tpm2/crypto/CryptRsa.h @@ -83,9 +83,9 @@ typedef struct privateExponent { bigNum P; bigNum Q; - bigNum dP_unused; - bigNum dQ_unused; - bigNum qInv_unused; + bigNum dP; + bigNum dQ; + bigNum qInv; bn_prime_t entries[5]; } privateExponent; @@ -119,5 +119,30 @@ RsaInitializeExponentOld( BN_INIT(pExp->qInv); } // libtpms added end -#endif // _CRYPT_RSA_H +#include "BnMemory_fp.h" +static inline void +RsaSetExponentOld( + privateExponent_t *pExp, // OUT + privateExponent *Z // IN + ) +{ + // pExp->Q must be set elsewhere + BnCopy((bigNum)&pExp->dP, Z->dP); + BnCopy((bigNum)&pExp->dQ, Z->dQ); + BnCopy((bigNum)&pExp->qInv, Z->qInv); +} + +static inline void +RsaSetExponentFromOld( + privateExponent *Z, // OUT + privateExponent_t *pExp // IN + ) +{ + BnCopy(Z->Q, (bigNum)&pExp->Q); + BnCopy(Z->dP, (bigNum)&pExp->dP); + BnCopy(Z->dQ, (bigNum)&pExp->dQ); + BnCopy(Z->qInv, (bigNum)&pExp->qInv); +} + +#endif // _CRYPT_RSA_H \ No newline at end of file diff --git a/src/tpm2/crypto/openssl/CryptRsa.c b/src/tpm2/crypto/openssl/CryptRsa.c index e395c60d..ad67bfe3 100644 --- a/src/tpm2/crypto/openssl/CryptRsa.c +++ b/src/tpm2/crypto/openssl/CryptRsa.c @@ -193,9 +193,8 @@ UnpackExponent( static BOOL ComputePrivateExponent( bigNum pubExp, // IN: the public exponent - privateExponent *Z, // IN/OUT: on input, has primes P and Q. On - // output, has P, Q but NOT dP, dQ, and pInv - privateExponent_t *pExp // OUT: has Q, dP, dQ and pInv + privateExponent *Z // IN/OUT: on input, has primes P and Q. On + // output, has P, Q, dP, dQ, and pInv ) { BOOL pOK; @@ -203,20 +202,17 @@ ComputePrivateExponent( BN_PRIME(pT); // // make p the larger value so that m2 is always less than p - RsaInitializeExponentOld(pExp); - BnCopy((bigNum)&pExp->Q, Z->Q); - MakePgreaterThanQ(Z); //dP = (1/e) mod (p-1) pOK = BnSubWord(pT, Z->P, 1); - pOK = pOK && BnModInverse((bigNum)&pExp->dP, pubExp, pT); + pOK = pOK && BnModInverse(Z->dP, pubExp, pT); //dQ = (1/e) mod (q-1) qOK = BnSubWord(pT, Z->Q, 1); - qOK = qOK && BnModInverse((bigNum)&pExp->dQ, pubExp, pT); + qOK = qOK && BnModInverse(Z->dQ, pubExp, pT); // qInv = (1/q) mod p if(pOK && qOK) - pOK = qOK = BnModInverse((bigNum)&pExp->qInv, Z->Q, Z->P); + pOK = qOK = BnModInverse(Z->qInv, Z->Q, Z->P); if(!pOK) BnSetWord(Z->P, 0); if(!qOK) @@ -233,8 +229,7 @@ ComputePrivateExponent( static BOOL RsaPrivateKeyOp( bigNum inOut, // IN/OUT: number to be exponentiated - privateExponent *Z, - privateExponent_t *pExp + privateExponent *Z ) { BN_RSA(M1); @@ -244,14 +239,14 @@ RsaPrivateKeyOp( // MakePgreaterThanQ(Z); // m1 = cdP mod p - VERIFY(BnModExp(M1, inOut, (bigNum)&pExp->dP, Z->P)); + VERIFY(BnModExp(M1, inOut, Z->dP, Z->P)); // m2 = cdQ mod q - VERIFY(BnModExp(M2, inOut, (bigNum)&pExp->dQ, Z->Q)); + VERIFY(BnModExp(M2, inOut, Z->dQ, Z->Q)); // h = qInv * (m1 - m2) mod p = qInv * (m1 + P - m2) mod P because Q < P // so m2 < P VERIFY(BnSub(H, Z->P, M2)); VERIFY(BnAdd(H, H, M1)); - VERIFY(BnModMult(H, H, (bigNum)&pExp->qInv, Z->P)); + VERIFY(BnModMult(H, H, Z->qInv, Z->P)); // m = m2 + h * q VERIFY(BnMult(M, H, Z->Q)); VERIFY(BnAdd(inOut, M2, M)); @@ -318,15 +313,15 @@ RSADP( // During self-test, this might not be the case so load it up if it hasn't // already done // been done - if(!key->attributes.privateExp) + if(!key->attributes.privateExp) // libtpms changed begin: use older verions { if(CryptRsaLoadPrivateExponent(key) != TPM_RC_SUCCESS) return TPM_RC_BINDING; } VERIFY(BnFrom2B(Z->P, &key->sensitive.sensitive.rsa.b) != NULL); - BnCopy(Z->Q, (bigNum)&key->privateExponent.Q); - VERIFY(RsaPrivateKeyOp(bnM, Z, &key->privateExponent)); + RsaSetExponentFromOld(Z, &key->privateExponent); // libtpms changed end + VERIFY(RsaPrivateKeyOp(bnM, Z)); VERIFY(BnTo2B(bnM, inOut, inOut->size)); return TPM_RC_SUCCESS; Error: @@ -1006,15 +1001,17 @@ CryptRsaLoadPrivateExponent( // Convert first prime to 2B VERIFY(BnFrom2B(Z->P, &sensitive->sensitive.rsa.b) != NULL); - // Make sure that the bigNum used for the exponent is properly initialized - RsaInitializeExponentOld(&rsaKey->privateExponent); // Find the second prime by division. This uses 'bQ' rather than Z->Q // because the division could make the quotient larger than a prime during // some intermediate step. VERIFY(BnDiv(Z->Q, bnQr, bnN, Z->P)); VERIFY(BnEqualZero(bnQr)); // Compute the private exponent and return it if found - VERIFY(ComputePrivateExponent(bnE, Z, &rsaKey->privateExponent)); + RsaInitializeExponentOld(&rsaKey->privateExponent); // libtpms added + BnCopy((bigNum)&rsaKey->privateExponent.Q, Z->Q); // libtpms added: preserve Q + VERIFY(ComputePrivateExponent(bnE, Z)); + RsaSetExponentOld(&rsaKey->privateExponent, Z); // libtpms added: preserve dP, dQ, qInv + } rsaKey->attributes.privateExp = TRUE; return TPM_RC_SUCCESS; @@ -1370,11 +1367,13 @@ CryptRsaGenerateKey( (NUMBYTES)BITS_TO_BYTES(keySizeInBits) / 2); // Make sure everything came out right. The MSb of the values must be one if(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0) - || ((sensitive->sensitive.rsa.t.buffer[0] & 0x80) == 0)) + || (publicArea->unique.rsa.t.size + != (NUMBYTES)BITS_TO_BYTES(keySizeInBits))) FAIL(FATAL_ERROR_INTERNAL); + BnCopy((bigNum)&rsaKey->privateExponent.Q, Z->Q); // libtpms added: preserve Q // Make sure that we can form the private exponent values - if(ComputePrivateExponent(bnPubExp, Z, &rsaKey->privateExponent) != TRUE) + if(ComputePrivateExponent(bnPubExp, Z) != TRUE) { // If ComputePrivateExponent could not find an inverse for // Q, then copy P and recompute P. This might @@ -1383,6 +1382,13 @@ CryptRsaGenerateKey( BnCopy(Z->Q, Z->P); continue; } + RsaSetExponentOld(&rsaKey->privateExponent, Z); // libtpms added: preserve dP, dQ, qInv + + // Make sure everything came out right. The MSb of the values must be one + if(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0) + || ((sensitive->sensitive.rsa.t.buffer[0] & 0x80) == 0)) + FAIL(FATAL_ERROR_INTERNAL); + retVal = TPM_RC_SUCCESS; // Do a trial encryption decryption if this is a signing key if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) @@ -1394,7 +1400,8 @@ CryptRsaGenerateKey( // Encrypt with public exponent... BnModExp(temp2, temp1, bnPubExp, bnN); // ... then decrypt with private exponent - RsaPrivateKeyOp(temp2, Z, &rsaKey->privateExponent); + RsaPrivateKeyOp(temp2, Z); + // If the starting and ending values are not the same, // start over )-; if(BnUnsignedCmp(temp2, temp1) != 0)