Skip to content

Commit

Permalink
Merged PR 11848961: Add SymCryptRsakeySetValueFromPrivateExponent
Browse files Browse the repository at this point in the history
## 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
  • Loading branch information
samuel-lee-msft committed Nov 23, 2024
1 parent 24d5b53 commit 1d7e34b
Show file tree
Hide file tree
Showing 29 changed files with 8,315 additions and 6,404 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
New changes will be listed here as they are developed. The version number is determined
prior to the creation of a new release, based on the changes contained in that release.

# Version 103.6.0

- Add LMS implementation
- Add AES-KW(P) implementation
- Add SHA224, SHA512/224, SHA512/256, and SHA3-224
- Add SymCryptRsakeySetValueFromPrivateExponent
- Fixed a regression in v103.5.0 which erroneously caused a fastfail in FIPS self-test when importing an invalid keypair

# Version 103.5.1

Expand Down
84 changes: 67 additions & 17 deletions inc/symcrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -7223,11 +7223,12 @@ SymCryptRsakeyAllocate(
//
// Allocate and create a new RSAKEY object sized according to the parameters.
// If the SYMCRYPT_RSAKEY object will only be used for a public key, the
// SYMCRYPT_RSA_PARAMS structure may set nPrimes = 0.
// SYMCRYPT_RSA_PARAMS structure may set nPrimes = 0. Use of
// SymCryptRsakeySetValueFromPrivateExponent requires nPrimes = 2.
//
// This call does not initialize the key. It should be
// followed by a call to SymCryptRsakeyGenerate or
// SymCryptRsakeySetValue.
// SymCryptRsakeySetValue*.
//
// No flags are specified for this function.
//
Expand All @@ -7251,11 +7252,12 @@ SymCryptRsakeyCreate(
//
// Create an RSAKEY object from a buffer, but does not initialize it.
// If the SYMCRYPT_RSAKEY object will only be used for a public key, the
// SYMCRYPT_RSA_PARAMS structure may set nPrimes = 0.
// SYMCRYPT_RSA_PARAMS structure may set nPrimes = 0. Use of
// SymCryptRsakeySetValueFromPrivateExponent requires nPrimes = 2.
//
// This call does not initialize the key. It should be
// followed by a call to SymCryptRsakeyGenerate or
// SymCryptRsakeySetValue.
// SymCryptRsakeySetValue*.
//

VOID
Expand Down Expand Up @@ -7620,12 +7622,12 @@ SymCryptRsakeySetValue(
SIZE_T cbModulus,
_In_reads_( nPubExp ) PCUINT64 pu64PubExp,
UINT32 nPubExp,
_In_reads_( nPrimes ) PCBYTE * ppPrimes,
_In_reads_( nPrimes ) SIZE_T * pcbPrimes,
_In_reads_opt_( nPrimes ) PCBYTE * ppPrimes,
_In_reads_opt_( nPrimes ) SIZE_T * pcbPrimes,
UINT32 nPrimes,
SYMCRYPT_NUMBER_FORMAT numFormat,
UINT32 flags,
_Out_ PSYMCRYPT_RSAKEY pkRsakey );
_Inout_ PSYMCRYPT_RSAKEY pkRsakey );
//
// Import key material to an RSAKEY object. The arguments are the following:
// - pbModulus is a pointer to a byte buffer of cbModulus bytes. It cannot be NULL.
Expand Down Expand Up @@ -7664,6 +7666,54 @@ SymCryptRsakeySetValue(
// into a possibly slightly larger buffer.
//

SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptRsakeySetValueFromPrivateExponent(
_In_reads_bytes_( cbModulus ) PCBYTE pbModulus,
SIZE_T cbModulus,
UINT64 u64PubExp,
_In_reads_bytes_( cbPrivateExponent ) PCBYTE pbPrivateExponent,
SIZE_T cbPrivateExponent,
SYMCRYPT_NUMBER_FORMAT numFormat,
UINT32 flags,
_Inout_ PSYMCRYPT_RSAKEY pkRsakey );
//
// Import private key to an RSAKEY object using a private exponent. This is not generally
// recommended - where possible it is more efficient to import a private key using primes
// with SymCryptRsakeySetValue.
//
// The arguments are the following:
// - pbModulus is a pointer to a byte buffer of cbModulus bytes. It cannot be NULL.
// - u64PubExp is a UINT64 public exponent value.
// - pbPrivateExponent is a pointer to a byte buffer of cbPrivateExponent bytes. It
// cannot be NULL.
// - numFormat specifies the number format for all inputs
//
// Allowed flags:
//
// - SYMCRYPT_FLAG_KEY_NO_FIPS
// Opt-out of performing validation required for FIPS
//
// - SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION
// Opt-out of performing almost all validation - must be specified with SYMCRYPT_FLAG_KEY_NO_FIPS
//
// - At least one of the flags indicating what the Rsakey is to be used for must be specified:
// SYMCRYPT_FLAG_RSAKEY_SIGN
// SYMCRYPT_FLAG_RSAKEY_ENCRYPT
//
// Described in more detail in the "Flags for asymmetric key generation and import" section above
//
// Remarks:
//
// Modulus and Private exponent are stored in the same format specified by numFormat.
//
// Internally this attempts to recover a pair of primes (p1, p2) that factorize Modulus.
// This procedure has following assumptions:
// Modulus (n) is the product of two prime factors, p1 and p2
// e*d == 1 modulo LCM(p1-1, p2-1)
// e*d != 1 modulo 2^64
// If any of these assumptions are not met, then the method may fail.
//

SYMCRYPT_ERROR
SYMCRYPT_CALL
Expand Down Expand Up @@ -7699,16 +7749,16 @@ SymCryptRsakeyGetValue(
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptRsakeyGetCrtValue(
_In_ PCSYMCRYPT_RSAKEY pkRsakey,
_Out_writes_(nCrtExponents) PBYTE * ppCrtExponents,
_In_reads_(nCrtExponents) SIZE_T * pcbCrtExponents,
UINT32 nCrtExponents,
_Out_writes_bytes_(cbCrtCoefficient) PBYTE pbCrtCoefficient,
SIZE_T cbCrtCoefficient,
_Out_writes_bytes_(cbPrivateExponent) PBYTE pbPrivateExponent,
SIZE_T cbPrivateExponent,
SYMCRYPT_NUMBER_FORMAT numFormat,
UINT32 flags);
_In_ PCSYMCRYPT_RSAKEY pkRsakey,
_Out_writes_opt_(nCrtExponents) PBYTE * ppCrtExponents,
_In_reads_(nCrtExponents) SIZE_T * pcbCrtExponents,
UINT32 nCrtExponents,
_Out_writes_bytes_opt_(cbCrtCoefficient) PBYTE pbCrtCoefficient,
SIZE_T cbCrtCoefficient,
_Out_writes_bytes_opt_(cbPrivateExponent) PBYTE pbPrivateExponent,
SIZE_T cbPrivateExponent,
SYMCRYPT_NUMBER_FORMAT numFormat,
UINT32 flags);
//
// Export Crt key material from an RSAKEY object. The arguments are the following:
// ppCrtExponents is an array of nCrtExponent pointers that point to byte buffers
Expand Down
2 changes: 1 addition & 1 deletion inc/symcrypt_low_level.h
Original file line number Diff line number Diff line change
Expand Up @@ -1182,7 +1182,7 @@ SymCryptIntExtendedGcd(
//
// The last two modular inverse values are not true modular inverses unless GCD( Src1, Src2 ) = 1.
//
// Any of the ouput pointers can be NULL and then that result is not returned.
// Any of the output pointers can be NULL and then that result is not returned.
// Requirements:
// - Src1 > 0
// - Src2 > 0 and Src2 odd
Expand Down
9 changes: 7 additions & 2 deletions lib/dlkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ SymCryptDlkeyGenerate(
SYMCRYPT_SELFTEST_ALGORITHM_DSA );

// Run PCT eagerly as the key can only be used for DSA - there is no value in deferring
SYMCRYPT_RUN_KEY_PCT(
SYMCRYPT_RUN_KEY_GEN_PCT(
SymCryptDsaPct,
pkDlkey,
SYMCRYPT_PCT_DSA );
Expand Down Expand Up @@ -800,10 +800,15 @@ SymCryptDlkeySetValue(

if( pkDlkey->fHasPrivateKey )
{
SYMCRYPT_RUN_KEY_PCT(
SYMCRYPT_RUN_KEY_IMPORT_PCT(
scError,
SymCryptDsaPct,
pkDlkey,
SYMCRYPT_PCT_DSA );
if( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}
}
}

Expand Down
11 changes: 9 additions & 2 deletions lib/ec_dsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,17 +411,24 @@ SymCryptEcDsaSign(
_Out_writes_bytes_( cbSignature ) PBYTE pbSignature,
SIZE_T cbSignature )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;

// We must have a private key to perform PCT or signature
if( !pKey->hasPrivateKey || !(pKey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) )
{
return SYMCRYPT_INVALID_ARGUMENT;
}

// If the key was generated and a PCT has not yet been performed - perform PCT before first use
SYMCRYPT_RUN_KEY_PCT(
// If the key has not yet had a PCT performed - perform PCT before first use
SYMCRYPT_RUN_KEY_IMPORT_PCT(
scError,
SymCryptEcDsaPct,
pKey,
SYMCRYPT_PCT_ECDSA );
if( scError != SYMCRYPT_NO_ERROR )
{
return scError;
}

return SymCryptEcDsaSignEx( pKey, pbHashValue, cbHashValue, NULL, format, flags, pbSignature, cbSignature );
}
Expand Down
7 changes: 6 additions & 1 deletion lib/eckey.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,10 +652,15 @@ SymCryptEckeyGetValue(
if ( ((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) != 0) &&
((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0) )
{
SYMCRYPT_RUN_KEY_PCT(
SYMCRYPT_RUN_KEY_IMPORT_PCT(
scError,
SymCryptEcDsaPct,
pEckey,
SYMCRYPT_PCT_ECDSA );
if ( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}
}

// Copy the key into the temporary integer
Expand Down
84 changes: 66 additions & 18 deletions lib/fips_selftest.c
Original file line number Diff line number Diff line change
Expand Up @@ -1308,15 +1308,19 @@ SymCryptEcDhSecretAgreementSelftest(void)
SymCryptEcurveFree( pCurve );
}

VOID
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptDsaPct( PCSYMCRYPT_DLKEY pkDlkey )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;

SIZE_T cbSignature = 2 * SYMCRYPT_BYTES_FROM_BITS(pkDlkey->nBitsPriv);
PBYTE pbSignature = SymCryptCallbackAlloc( cbSignature );
SYMCRYPT_FIPS_ASSERT( pbSignature != NULL );
if( pbSignature == NULL )
{
scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
goto cleanup;
}

scError = SymCryptDsaSign(
pkDlkey,
Expand All @@ -1326,7 +1330,10 @@ SymCryptDsaPct( PCSYMCRYPT_DLKEY pkDlkey )
0,
pbSignature,
cbSignature );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
if( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}

SymCryptInjectError( pbSignature, cbSignature );

Expand All @@ -1338,10 +1345,19 @@ SymCryptDsaPct( PCSYMCRYPT_DLKEY pkDlkey )
cbSignature,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0 );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
if( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}

SymCryptWipe( pbSignature, cbSignature );
SymCryptCallbackFree( pbSignature );
cleanup:
if( pbSignature != NULL )
{
SymCryptWipe( pbSignature, cbSignature );
SymCryptCallbackFree( pbSignature );
}

return scError;
}

VOID
Expand Down Expand Up @@ -1411,15 +1427,19 @@ SymCryptDsaSelftest(void)
SymCryptDlgroupFree( pDlgroup );
}

VOID
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptEcDsaPct( PCSYMCRYPT_ECKEY pkEckey )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;

SIZE_T cbSignature = 2 * SymCryptEckeySizeofPrivateKey(pkEckey);
PBYTE pbSignature = SymCryptCallbackAlloc( cbSignature );
SYMCRYPT_FIPS_ASSERT( pbSignature != NULL );
if( pbSignature == NULL )
{
scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
goto cleanup;
}

// Use SymCryptEcDsaSignEx to avoid infinite recursion in the PCT
scError = SymCryptEcDsaSignEx(
Expand All @@ -1431,7 +1451,10 @@ SymCryptEcDsaPct( PCSYMCRYPT_ECKEY pkEckey )
0,
pbSignature,
cbSignature );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
if( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}

SymCryptInjectError( pbSignature, cbSignature );

Expand All @@ -1443,10 +1466,19 @@ SymCryptEcDsaPct( PCSYMCRYPT_ECKEY pkEckey )
cbSignature,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0 );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
if( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}

SymCryptWipe( pbSignature, cbSignature );
SymCryptCallbackFree( pbSignature );
cleanup:
if( pbSignature != NULL )
{
SymCryptWipe( pbSignature, cbSignature );
SymCryptCallbackFree( pbSignature );
}

return scError;
}

VOID
Expand Down Expand Up @@ -1520,15 +1552,19 @@ SymCryptEcDsaSelftest(void)
SymCryptEcurveFree( pCurve );
}

VOID
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptRsaSignVerifyPct( PCSYMCRYPT_RSAKEY pkRsakey )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;

SIZE_T cbSignature = SYMCRYPT_BYTES_FROM_BITS(pkRsakey->nBitsOfModulus);
PBYTE pbSignature = SymCryptCallbackAlloc( cbSignature );
SYMCRYPT_FIPS_ASSERT( pbSignature != NULL );
if( pbSignature == NULL )
{
scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
goto cleanup;
}

scError = SymCryptRsaPkcs1Sign(
pkRsakey,
Expand All @@ -1541,7 +1577,10 @@ SymCryptRsaSignVerifyPct( PCSYMCRYPT_RSAKEY pkRsakey )
pbSignature,
cbSignature,
&cbSignature );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
if( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}

SymCryptInjectError( pbSignature, cbSignature );

Expand All @@ -1555,10 +1594,19 @@ SymCryptRsaSignVerifyPct( PCSYMCRYPT_RSAKEY pkRsakey )
SymCryptSha256OidList,
SYMCRYPT_SHA256_OID_COUNT,
0 );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
if( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}

cleanup:
if( pbSignature != NULL )
{
SymCryptWipe( pbSignature, cbSignature );
SymCryptCallbackFree( pbSignature );
}

SymCryptWipe( pbSignature, cbSignature );
SymCryptCallbackFree( pbSignature );
return scError;
}

VOID
Expand Down
Loading

0 comments on commit 1d7e34b

Please sign in to comment.