mirror of
https://github.com/stefanberger/libtpms
synced 2026-08-09 23:38:23 +00:00
tpm2: EcSM2: Enforce that the random bnK has no leading zeros
Make sure that the value of bnK is not short so that the subsequent BnEccModMult() runs in constant time. We take the same approach as with the modifications to BnEccGenerateKeyPair() where we request bnK to have all bytes set (no leading zeros that will be cut away) in case the order of the curve is as byte boundary. In the other cases we add the order to bnK, which creates bnK1, which we then use for BnEccModMult's scalar parameter. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> Suggested-by: Charanjit Jutla <csjutla@us.ibm.com> Reviewed-by: Charanjit Jutla <csjutla@us.ibm.com> Tested-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
parent
5c224b8d98
commit
089485035f
@ -552,3 +552,81 @@ BnGenerateRandomInRange(
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// libtpms added begin
|
||||
|
||||
// This version of BnSizeInBits skips any leading zero bytes in bigConst
|
||||
// and thus calculates the bits that OpenSSL will work with after truncating
|
||||
// the leading zeros
|
||||
static LIB_EXPORT unsigned
|
||||
BnSizeInBitsSkipLeadingZeros(
|
||||
bigConst n
|
||||
)
|
||||
{
|
||||
int firstByte;
|
||||
unsigned bitSize = BnSizeInBits(n);
|
||||
crypt_uword_t i;
|
||||
|
||||
if (bitSize <= 8)
|
||||
return bitSize;
|
||||
|
||||
// search for the first limb that is non-zero
|
||||
for (i = 0; i < n->size; i++) {
|
||||
if (n->d[i] != 0)
|
||||
break;
|
||||
}
|
||||
if (i >= n->size)
|
||||
return 0; // should never happen
|
||||
|
||||
// get the first byte in this limb that is non-zero
|
||||
firstByte = (RADIX_BITS - 1 - Msb(n->d[i])) >> 3;
|
||||
|
||||
return bitSize - i * sizeof(n->d[0]) - (firstByte << 3);
|
||||
}
|
||||
|
||||
|
||||
/* This is a version of BnGenerateRandomInRange that ensures that the upper most
|
||||
byte is non-zero, so that the number will not be shortened and subsequent operations
|
||||
will not have a timing-sidechannel
|
||||
*/
|
||||
LIB_EXPORT BOOL
|
||||
BnGenerateRandomInRangeAllBytes(
|
||||
bigNum dest,
|
||||
bigConst limit,
|
||||
RAND_STATE *rand
|
||||
)
|
||||
{
|
||||
BOOL OK;
|
||||
int repeats = 0;
|
||||
int maxRepeats;
|
||||
unsigned requestedBits;
|
||||
unsigned requestedBytes;
|
||||
unsigned numBytes;
|
||||
|
||||
if (rand)
|
||||
return BnGenerateRandomInRange(dest, limit, rand);
|
||||
|
||||
// a 'limit' like 'BN_P638_n' has leading zeros and we only need 73 bytes not 80
|
||||
requestedBits = BnSizeInBitsSkipLeadingZeros(limit);
|
||||
requestedBytes = BITS_TO_BYTES(requestedBits);
|
||||
maxRepeats = 8;
|
||||
if (requestedBits & 7)
|
||||
maxRepeats += (9 - (requestedBits & 7));
|
||||
|
||||
while (true) {
|
||||
OK = BnGenerateRandomInRange(dest, limit, rand);
|
||||
if (!OK)
|
||||
break;
|
||||
if (repeats < maxRepeats) {
|
||||
numBytes = BITS_TO_BYTES(BnSizeInBitsSkipLeadingZeros(dest));
|
||||
if (numBytes < requestedBytes) {
|
||||
repeats++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
// libtpms added end
|
||||
|
||||
@ -151,6 +151,13 @@ BnGenerateRandomInRange(
|
||||
bigConst limit,
|
||||
RAND_STATE *rand
|
||||
);
|
||||
|
||||
// libtpms added begin
|
||||
LIB_EXPORT BOOL
|
||||
BnGenerateRandomInRangeAllBytes(
|
||||
bigNum dest,
|
||||
bigConst limit,
|
||||
RAND_STATE *rand
|
||||
);
|
||||
// libtpms added end
|
||||
|
||||
#endif
|
||||
|
||||
@ -472,6 +472,12 @@ BnSignEcSm2(
|
||||
POINT(Q1);
|
||||
bigConst order = (E != NULL)
|
||||
? CurveGetOrder(AccessCurveData(E)) : NULL;
|
||||
// libtpms added begin
|
||||
UINT32 orderBits = BnSizeInBits(order);
|
||||
BOOL atByteBoundary = (orderBits & 7) == 0;
|
||||
ECC_NUM(bnK1);
|
||||
// libtpms added end
|
||||
|
||||
//
|
||||
#ifdef _SM2_SIGN_DEBUG
|
||||
BnFromHex(bnE, "B524F552CD82B8B028476E005C377FB1"
|
||||
@ -484,16 +490,36 @@ BnSignEcSm2(
|
||||
loop:
|
||||
{
|
||||
// Get a random number 0 < k < n
|
||||
BnGenerateRandomInRange(bnK, order, rand);
|
||||
// libtpms modified begin
|
||||
//
|
||||
// We take a dual approach here. One for curves whose order is not at
|
||||
// the byte boundary, e.g. NIST P521, we get a random number bnK and add
|
||||
// the order to that number to have bnK1. This will not spill over into
|
||||
// a new byte and we can then use bnK1 to do the do the BnEccModMult
|
||||
// with a constant number of bytes. For curves whose order is at the
|
||||
// byte boundary we require that the random number bnK comes back with
|
||||
// a requested number of bytes.
|
||||
if (!atByteBoundary) {
|
||||
BnGenerateRandomInRange(bnK, order, rand);
|
||||
BnAdd(bnK1, bnK, order);
|
||||
#ifdef _SM2_SIGN_DEBUG
|
||||
BnFromHex(bnK, "6CB28D99385C175C94F94E934817663F"
|
||||
"C176D925DD72B727260DBAAE1FB2F96F");
|
||||
BnFromHex(bnK1, "6CB28D99385C175C94F94E934817663F"
|
||||
"C176D925DD72B727260DBAAE1FB2F96F");
|
||||
#endif
|
||||
// A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according
|
||||
// to details specified in 4.2.7 in Part 1 of this document, transform the
|
||||
// data type of x1 into an integer;
|
||||
if(!BnEccModMult(Q1, NULL, bnK, E))
|
||||
goto loop;
|
||||
// A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according
|
||||
// to details specified in 4.2.7 in Part 1 of this document, transform the
|
||||
// data type of x1 into an integer;
|
||||
if(!BnEccModMult(Q1, NULL, bnK1, E))
|
||||
goto loop;
|
||||
} else {
|
||||
BnGenerateRandomInRangeAllBytes(bnK, order, rand);
|
||||
#ifdef _SM2_SIGN_DEBUG
|
||||
BnFromHex(bnK, "6CB28D99385C175C94F94E934817663F"
|
||||
"C176D925DD72B727260DBAAE1FB2F96F");
|
||||
#endif
|
||||
if(!BnEccModMult(Q1, NULL, bnK, E))
|
||||
goto loop;
|
||||
} // libtpms modified end
|
||||
// A5: Figure out r = (e + x1) mod n,
|
||||
BnAdd(bnR, bnE, Q1->x);
|
||||
BnMod(bnR, order);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user