Skip to content

Commit 1d7e34b

Browse files
Merged PR 11848961: Add SymCryptRsakeySetValueFromPrivateExponent
## Description: + Adds implementation of SymCryptRsakeySetValueFromPrivateExponent for OpenSSL interop + Adds various testing for this, including adding success/failure testing for RSA keypair import + Removes fatal PCTs from bad import + Bumps to SymCrypt v103.6.0 ## Admin Checklist: - [X] You have updated documentation in symcrypt.h to reflect any changes in behavior - [X] You have updated CHANGELOG.md to reflect any changes in behavior - [X] You have updated symcryptunittest to exercise any new functionality - [X] If you have introduced any symbols in symcrypt.h you have updated production and test dynamic export symbols (exports.ver / exports.def / symcrypt.src) and tested the updated dynamic modules with symcryptunittest - [X] If you have introduced functionality that varies based on CPU features, you have manually tested with and without relevant features - [X] If you have made significant changes to a particular algorithm, you have checked that performance numbers reported by symcryptunittest are in line with expectations - [X] If you have added new algorithms/modes, you have updated the status indicator text for the associated modules if necessary Related work items: #51975833
1 parent 24d5b53 commit 1d7e34b

29 files changed

+8315
-6404
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33
New changes will be listed here as they are developed. The version number is determined
44
prior to the creation of a new release, based on the changes contained in that release.
55

6+
# Version 103.6.0
7+
68
- Add LMS implementation
79
- Add AES-KW(P) implementation
810
- Add SHA224, SHA512/224, SHA512/256, and SHA3-224
11+
- Add SymCryptRsakeySetValueFromPrivateExponent
12+
- Fixed a regression in v103.5.0 which erroneously caused a fastfail in FIPS self-test when importing an invalid keypair
913

1014
# Version 103.5.1
1115

inc/symcrypt.h

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7223,11 +7223,12 @@ SymCryptRsakeyAllocate(
72237223
//
72247224
// Allocate and create a new RSAKEY object sized according to the parameters.
72257225
// If the SYMCRYPT_RSAKEY object will only be used for a public key, the
7226-
// SYMCRYPT_RSA_PARAMS structure may set nPrimes = 0.
7226+
// SYMCRYPT_RSA_PARAMS structure may set nPrimes = 0. Use of
7227+
// SymCryptRsakeySetValueFromPrivateExponent requires nPrimes = 2.
72277228
//
72287229
// This call does not initialize the key. It should be
72297230
// followed by a call to SymCryptRsakeyGenerate or
7230-
// SymCryptRsakeySetValue.
7231+
// SymCryptRsakeySetValue*.
72317232
//
72327233
// No flags are specified for this function.
72337234
//
@@ -7251,11 +7252,12 @@ SymCryptRsakeyCreate(
72517252
//
72527253
// Create an RSAKEY object from a buffer, but does not initialize it.
72537254
// If the SYMCRYPT_RSAKEY object will only be used for a public key, the
7254-
// SYMCRYPT_RSA_PARAMS structure may set nPrimes = 0.
7255+
// SYMCRYPT_RSA_PARAMS structure may set nPrimes = 0. Use of
7256+
// SymCryptRsakeySetValueFromPrivateExponent requires nPrimes = 2.
72557257
//
72567258
// This call does not initialize the key. It should be
72577259
// followed by a call to SymCryptRsakeyGenerate or
7258-
// SymCryptRsakeySetValue.
7260+
// SymCryptRsakeySetValue*.
72597261
//
72607262

72617263
VOID
@@ -7620,12 +7622,12 @@ SymCryptRsakeySetValue(
76207622
SIZE_T cbModulus,
76217623
_In_reads_( nPubExp ) PCUINT64 pu64PubExp,
76227624
UINT32 nPubExp,
7623-
_In_reads_( nPrimes ) PCBYTE * ppPrimes,
7624-
_In_reads_( nPrimes ) SIZE_T * pcbPrimes,
7625+
_In_reads_opt_( nPrimes ) PCBYTE * ppPrimes,
7626+
_In_reads_opt_( nPrimes ) SIZE_T * pcbPrimes,
76257627
UINT32 nPrimes,
76267628
SYMCRYPT_NUMBER_FORMAT numFormat,
76277629
UINT32 flags,
7628-
_Out_ PSYMCRYPT_RSAKEY pkRsakey );
7630+
_Inout_ PSYMCRYPT_RSAKEY pkRsakey );
76297631
//
76307632
// Import key material to an RSAKEY object. The arguments are the following:
76317633
// - pbModulus is a pointer to a byte buffer of cbModulus bytes. It cannot be NULL.
@@ -7664,6 +7666,54 @@ SymCryptRsakeySetValue(
76647666
// into a possibly slightly larger buffer.
76657667
//
76667668

7669+
SYMCRYPT_ERROR
7670+
SYMCRYPT_CALL
7671+
SymCryptRsakeySetValueFromPrivateExponent(
7672+
_In_reads_bytes_( cbModulus ) PCBYTE pbModulus,
7673+
SIZE_T cbModulus,
7674+
UINT64 u64PubExp,
7675+
_In_reads_bytes_( cbPrivateExponent ) PCBYTE pbPrivateExponent,
7676+
SIZE_T cbPrivateExponent,
7677+
SYMCRYPT_NUMBER_FORMAT numFormat,
7678+
UINT32 flags,
7679+
_Inout_ PSYMCRYPT_RSAKEY pkRsakey );
7680+
//
7681+
// Import private key to an RSAKEY object using a private exponent. This is not generally
7682+
// recommended - where possible it is more efficient to import a private key using primes
7683+
// with SymCryptRsakeySetValue.
7684+
//
7685+
// The arguments are the following:
7686+
// - pbModulus is a pointer to a byte buffer of cbModulus bytes. It cannot be NULL.
7687+
// - u64PubExp is a UINT64 public exponent value.
7688+
// - pbPrivateExponent is a pointer to a byte buffer of cbPrivateExponent bytes. It
7689+
// cannot be NULL.
7690+
// - numFormat specifies the number format for all inputs
7691+
//
7692+
// Allowed flags:
7693+
//
7694+
// - SYMCRYPT_FLAG_KEY_NO_FIPS
7695+
// Opt-out of performing validation required for FIPS
7696+
//
7697+
// - SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION
7698+
// Opt-out of performing almost all validation - must be specified with SYMCRYPT_FLAG_KEY_NO_FIPS
7699+
//
7700+
// - At least one of the flags indicating what the Rsakey is to be used for must be specified:
7701+
// SYMCRYPT_FLAG_RSAKEY_SIGN
7702+
// SYMCRYPT_FLAG_RSAKEY_ENCRYPT
7703+
//
7704+
// Described in more detail in the "Flags for asymmetric key generation and import" section above
7705+
//
7706+
// Remarks:
7707+
//
7708+
// Modulus and Private exponent are stored in the same format specified by numFormat.
7709+
//
7710+
// Internally this attempts to recover a pair of primes (p1, p2) that factorize Modulus.
7711+
// This procedure has following assumptions:
7712+
// Modulus (n) is the product of two prime factors, p1 and p2
7713+
// e*d == 1 modulo LCM(p1-1, p2-1)
7714+
// e*d != 1 modulo 2^64
7715+
// If any of these assumptions are not met, then the method may fail.
7716+
//
76677717

76687718
SYMCRYPT_ERROR
76697719
SYMCRYPT_CALL
@@ -7699,16 +7749,16 @@ SymCryptRsakeyGetValue(
76997749
SYMCRYPT_ERROR
77007750
SYMCRYPT_CALL
77017751
SymCryptRsakeyGetCrtValue(
7702-
_In_ PCSYMCRYPT_RSAKEY pkRsakey,
7703-
_Out_writes_(nCrtExponents) PBYTE * ppCrtExponents,
7704-
_In_reads_(nCrtExponents) SIZE_T * pcbCrtExponents,
7705-
UINT32 nCrtExponents,
7706-
_Out_writes_bytes_(cbCrtCoefficient) PBYTE pbCrtCoefficient,
7707-
SIZE_T cbCrtCoefficient,
7708-
_Out_writes_bytes_(cbPrivateExponent) PBYTE pbPrivateExponent,
7709-
SIZE_T cbPrivateExponent,
7710-
SYMCRYPT_NUMBER_FORMAT numFormat,
7711-
UINT32 flags);
7752+
_In_ PCSYMCRYPT_RSAKEY pkRsakey,
7753+
_Out_writes_opt_(nCrtExponents) PBYTE * ppCrtExponents,
7754+
_In_reads_(nCrtExponents) SIZE_T * pcbCrtExponents,
7755+
UINT32 nCrtExponents,
7756+
_Out_writes_bytes_opt_(cbCrtCoefficient) PBYTE pbCrtCoefficient,
7757+
SIZE_T cbCrtCoefficient,
7758+
_Out_writes_bytes_opt_(cbPrivateExponent) PBYTE pbPrivateExponent,
7759+
SIZE_T cbPrivateExponent,
7760+
SYMCRYPT_NUMBER_FORMAT numFormat,
7761+
UINT32 flags);
77127762
//
77137763
// Export Crt key material from an RSAKEY object. The arguments are the following:
77147764
// ppCrtExponents is an array of nCrtExponent pointers that point to byte buffers

inc/symcrypt_low_level.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1182,7 +1182,7 @@ SymCryptIntExtendedGcd(
11821182
//
11831183
// The last two modular inverse values are not true modular inverses unless GCD( Src1, Src2 ) = 1.
11841184
//
1185-
// Any of the ouput pointers can be NULL and then that result is not returned.
1185+
// Any of the output pointers can be NULL and then that result is not returned.
11861186
// Requirements:
11871187
// - Src1 > 0
11881188
// - Src2 > 0 and Src2 odd

lib/dlkey.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ SymCryptDlkeyGenerate(
486486
SYMCRYPT_SELFTEST_ALGORITHM_DSA );
487487

488488
// Run PCT eagerly as the key can only be used for DSA - there is no value in deferring
489-
SYMCRYPT_RUN_KEY_PCT(
489+
SYMCRYPT_RUN_KEY_GEN_PCT(
490490
SymCryptDsaPct,
491491
pkDlkey,
492492
SYMCRYPT_PCT_DSA );
@@ -800,10 +800,15 @@ SymCryptDlkeySetValue(
800800

801801
if( pkDlkey->fHasPrivateKey )
802802
{
803-
SYMCRYPT_RUN_KEY_PCT(
803+
SYMCRYPT_RUN_KEY_IMPORT_PCT(
804+
scError,
804805
SymCryptDsaPct,
805806
pkDlkey,
806807
SYMCRYPT_PCT_DSA );
808+
if( scError != SYMCRYPT_NO_ERROR )
809+
{
810+
goto cleanup;
811+
}
807812
}
808813
}
809814

lib/ec_dsa.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,17 +411,24 @@ SymCryptEcDsaSign(
411411
_Out_writes_bytes_( cbSignature ) PBYTE pbSignature,
412412
SIZE_T cbSignature )
413413
{
414+
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
415+
414416
// We must have a private key to perform PCT or signature
415417
if( !pKey->hasPrivateKey || !(pKey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) )
416418
{
417419
return SYMCRYPT_INVALID_ARGUMENT;
418420
}
419421

420-
// If the key was generated and a PCT has not yet been performed - perform PCT before first use
421-
SYMCRYPT_RUN_KEY_PCT(
422+
// If the key has not yet had a PCT performed - perform PCT before first use
423+
SYMCRYPT_RUN_KEY_IMPORT_PCT(
424+
scError,
422425
SymCryptEcDsaPct,
423426
pKey,
424427
SYMCRYPT_PCT_ECDSA );
428+
if( scError != SYMCRYPT_NO_ERROR )
429+
{
430+
return scError;
431+
}
425432

426433
return SymCryptEcDsaSignEx( pKey, pbHashValue, cbHashValue, NULL, format, flags, pbSignature, cbSignature );
427434
}

lib/eckey.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,10 +652,15 @@ SymCryptEckeyGetValue(
652652
if ( ((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) != 0) &&
653653
((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0) )
654654
{
655-
SYMCRYPT_RUN_KEY_PCT(
655+
SYMCRYPT_RUN_KEY_IMPORT_PCT(
656+
scError,
656657
SymCryptEcDsaPct,
657658
pEckey,
658659
SYMCRYPT_PCT_ECDSA );
660+
if ( scError != SYMCRYPT_NO_ERROR )
661+
{
662+
goto cleanup;
663+
}
659664
}
660665

661666
// Copy the key into the temporary integer

lib/fips_selftest.c

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,15 +1308,19 @@ SymCryptEcDhSecretAgreementSelftest(void)
13081308
SymCryptEcurveFree( pCurve );
13091309
}
13101310

1311-
VOID
1311+
SYMCRYPT_ERROR
13121312
SYMCRYPT_CALL
13131313
SymCryptDsaPct( PCSYMCRYPT_DLKEY pkDlkey )
13141314
{
13151315
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
13161316

13171317
SIZE_T cbSignature = 2 * SYMCRYPT_BYTES_FROM_BITS(pkDlkey->nBitsPriv);
13181318
PBYTE pbSignature = SymCryptCallbackAlloc( cbSignature );
1319-
SYMCRYPT_FIPS_ASSERT( pbSignature != NULL );
1319+
if( pbSignature == NULL )
1320+
{
1321+
scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1322+
goto cleanup;
1323+
}
13201324

13211325
scError = SymCryptDsaSign(
13221326
pkDlkey,
@@ -1326,7 +1330,10 @@ SymCryptDsaPct( PCSYMCRYPT_DLKEY pkDlkey )
13261330
0,
13271331
pbSignature,
13281332
cbSignature );
1329-
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
1333+
if( scError != SYMCRYPT_NO_ERROR )
1334+
{
1335+
goto cleanup;
1336+
}
13301337

13311338
SymCryptInjectError( pbSignature, cbSignature );
13321339

@@ -1338,10 +1345,19 @@ SymCryptDsaPct( PCSYMCRYPT_DLKEY pkDlkey )
13381345
cbSignature,
13391346
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
13401347
0 );
1341-
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
1348+
if( scError != SYMCRYPT_NO_ERROR )
1349+
{
1350+
goto cleanup;
1351+
}
13421352

1343-
SymCryptWipe( pbSignature, cbSignature );
1344-
SymCryptCallbackFree( pbSignature );
1353+
cleanup:
1354+
if( pbSignature != NULL )
1355+
{
1356+
SymCryptWipe( pbSignature, cbSignature );
1357+
SymCryptCallbackFree( pbSignature );
1358+
}
1359+
1360+
return scError;
13451361
}
13461362

13471363
VOID
@@ -1411,15 +1427,19 @@ SymCryptDsaSelftest(void)
14111427
SymCryptDlgroupFree( pDlgroup );
14121428
}
14131429

1414-
VOID
1430+
SYMCRYPT_ERROR
14151431
SYMCRYPT_CALL
14161432
SymCryptEcDsaPct( PCSYMCRYPT_ECKEY pkEckey )
14171433
{
14181434
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
14191435

14201436
SIZE_T cbSignature = 2 * SymCryptEckeySizeofPrivateKey(pkEckey);
14211437
PBYTE pbSignature = SymCryptCallbackAlloc( cbSignature );
1422-
SYMCRYPT_FIPS_ASSERT( pbSignature != NULL );
1438+
if( pbSignature == NULL )
1439+
{
1440+
scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1441+
goto cleanup;
1442+
}
14231443

14241444
// Use SymCryptEcDsaSignEx to avoid infinite recursion in the PCT
14251445
scError = SymCryptEcDsaSignEx(
@@ -1431,7 +1451,10 @@ SymCryptEcDsaPct( PCSYMCRYPT_ECKEY pkEckey )
14311451
0,
14321452
pbSignature,
14331453
cbSignature );
1434-
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
1454+
if( scError != SYMCRYPT_NO_ERROR )
1455+
{
1456+
goto cleanup;
1457+
}
14351458

14361459
SymCryptInjectError( pbSignature, cbSignature );
14371460

@@ -1443,10 +1466,19 @@ SymCryptEcDsaPct( PCSYMCRYPT_ECKEY pkEckey )
14431466
cbSignature,
14441467
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
14451468
0 );
1446-
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
1469+
if( scError != SYMCRYPT_NO_ERROR )
1470+
{
1471+
goto cleanup;
1472+
}
14471473

1448-
SymCryptWipe( pbSignature, cbSignature );
1449-
SymCryptCallbackFree( pbSignature );
1474+
cleanup:
1475+
if( pbSignature != NULL )
1476+
{
1477+
SymCryptWipe( pbSignature, cbSignature );
1478+
SymCryptCallbackFree( pbSignature );
1479+
}
1480+
1481+
return scError;
14501482
}
14511483

14521484
VOID
@@ -1520,15 +1552,19 @@ SymCryptEcDsaSelftest(void)
15201552
SymCryptEcurveFree( pCurve );
15211553
}
15221554

1523-
VOID
1555+
SYMCRYPT_ERROR
15241556
SYMCRYPT_CALL
15251557
SymCryptRsaSignVerifyPct( PCSYMCRYPT_RSAKEY pkRsakey )
15261558
{
15271559
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
15281560

15291561
SIZE_T cbSignature = SYMCRYPT_BYTES_FROM_BITS(pkRsakey->nBitsOfModulus);
15301562
PBYTE pbSignature = SymCryptCallbackAlloc( cbSignature );
1531-
SYMCRYPT_FIPS_ASSERT( pbSignature != NULL );
1563+
if( pbSignature == NULL )
1564+
{
1565+
scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1566+
goto cleanup;
1567+
}
15321568

15331569
scError = SymCryptRsaPkcs1Sign(
15341570
pkRsakey,
@@ -1541,7 +1577,10 @@ SymCryptRsaSignVerifyPct( PCSYMCRYPT_RSAKEY pkRsakey )
15411577
pbSignature,
15421578
cbSignature,
15431579
&cbSignature );
1544-
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
1580+
if( scError != SYMCRYPT_NO_ERROR )
1581+
{
1582+
goto cleanup;
1583+
}
15451584

15461585
SymCryptInjectError( pbSignature, cbSignature );
15471586

@@ -1555,10 +1594,19 @@ SymCryptRsaSignVerifyPct( PCSYMCRYPT_RSAKEY pkRsakey )
15551594
SymCryptSha256OidList,
15561595
SYMCRYPT_SHA256_OID_COUNT,
15571596
0 );
1558-
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
1597+
if( scError != SYMCRYPT_NO_ERROR )
1598+
{
1599+
goto cleanup;
1600+
}
1601+
1602+
cleanup:
1603+
if( pbSignature != NULL )
1604+
{
1605+
SymCryptWipe( pbSignature, cbSignature );
1606+
SymCryptCallbackFree( pbSignature );
1607+
}
15591608

1560-
SymCryptWipe( pbSignature, cbSignature );
1561-
SymCryptCallbackFree( pbSignature );
1609+
return scError;
15621610
}
15631611

15641612
VOID

0 commit comments

Comments
 (0)