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 <stefanb@linux.ibm.com>
This commit is contained in:
Stefan Berger 2023-08-28 12:14:38 -04:00 committed by Stefan Berger
parent c9a0650e52
commit 36d1e03368
2 changed files with 59 additions and 27 deletions

View File

@ -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

View File

@ -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)