Skip to content

Commit 3b4cad7

Browse files
committed
Merged PR 11324214: FIPS 140-3 CASTs for RSA, DSA, ECDSA
This change adds additional Cryptographic Algorithm Self-Tests (CASTs) for RSA, DSA and ECDSA. as required by FIPS 140-3. Specifically, it adds explicit Known Answer Tests (KATs), as the Pairwise Consistency Tests (PCTs) that we were using previously are no longer considered sufficient for CASTs. Also adds pairwise consistency tests on key import for RSA and DSA, per recent changes in the FIPS 140-3 implementation guidance. ECDSA PCTs continue to be run prior to signing or key export, as a performance optimization. ECDH and DH do not have explicit PCTs, but they include the required checks specified in SP 800-56A rev 3. Related work items: #53481333
1 parent 6173477 commit 3b4cad7

File tree

11 files changed

+324
-140
lines changed

11 files changed

+324
-140
lines changed

doc/breaking_changes.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,9 @@ This is a potentially ABI-breaking change on Windows x86.
2727
This is for consistency with the Semantic Versioning specification, as well as various tooling.
2828

2929
### extern variables defined in SymCrypt headers will be removed and replaced by equivalent getter functions
30-
This simplifies how we define dynamic module exports in a cross-platform way.
30+
This simplifies how we define dynamic module exports in a cross-platform way.
31+
32+
### Self-test functions and definitions will no longer be exposed/exported
33+
Various functions and definitions related to FIPS self-tests are exposed to callers in
34+
symcrypt_internal.h, and exported from the shared object libraries/DLLs. These functions are only
35+
intended to be used internally for FIPS compliance, so they will be removed from external visibility.

inc/symcrypt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7367,7 +7367,7 @@ SymCryptDlkeyExtendKeyUsage(
73677367
// Enable an existing key which has been generated or imported to be used in specified algorithms.
73687368
// Some callers may not know at key generation or import time what algorithms a key will be used for
73697369
// and this API allows the key to be extended for use in additional algorithms. Use of this API may
7370-
// not be compliant with FIPS 140-3
7370+
// not be compliant with FIPS 140-3.
73717371
//
73727372
// - flags must be some bitwise OR of the following flags:
73737373
// SYMCRYPT_FLAG_DLKEY_DSA

inc/symcrypt_internal.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2417,7 +2417,7 @@ typedef SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_RSAKEY {
24172417
UINT32 fAlgorithmInfo; // Tracks which algorithms the key can be used in
24182418
// Also tracks which per-key selftests have been performed on this key
24192419
// A bitwise OR of SYMCRYPT_FLAG_KEY_*, SYMCRYPT_FLAG_RSAKEY_*, and
2420-
// SYMCRYPT_SELFTEST_KEY_* values
2420+
// SYMCRYPT_PCT_* values
24212421

24222422
UINT32 cbTotalSize; // Total size of the rsa key
24232423
BOOLEAN hasPrivateKey; // Set to true if there is private key information set
@@ -2571,7 +2571,7 @@ typedef SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_DLKEY {
25712571
UINT32 fAlgorithmInfo; // Tracks which algorithms the key can be used in
25722572
// Also tracks which per-key selftests have been performed on this key
25732573
// A bitwise OR of SYMCRYPT_FLAG_KEY_*, SYMCRYPT_FLAG_DLKEY_*, and
2574-
// SYMCRYPT_SELFTEST_KEY_* values
2574+
// SYMCRYPT_PCT_* values
25752575

25762576
BOOLEAN fHasPrivateKey; // Set to true if there is a private key set
25772577
BOOLEAN fPrivateModQ; // Set to true if the private key is at most Q-1, otherwise it is at most P-2
@@ -2760,7 +2760,7 @@ typedef SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_ECKEY {
27602760
UINT32 fAlgorithmInfo; // Tracks which algorithms the key can be used in
27612761
// Also tracks which per-key selftests have been performed on this key
27622762
// A bitwise OR of SYMCRYPT_FLAG_KEY_*, SYMCRYPT_FLAG_ECKEY_*, and
2763-
// SYMCRYPT_SELFTEST_KEY_* values
2763+
// SYMCRYPT_PCT_* values
27642764
BOOLEAN hasPrivateKey; // Set to true if there is a private key set
27652765
PCSYMCRYPT_ECURVE pCurve; // Handle to the curve which created the key
27662766

@@ -3130,18 +3130,25 @@ SymCryptFipsGetSelftestsPerformed(void);
31303130
// defer running expensive tests until we know they are required (e.g. if we generate an Eckey which
31313131
// may be used in ECDH or ECDSA, and only use it for ECDH, the ECDSA PCT is deferred until we first
31323132
// attempt to use the key in ECDSA, or export the private key).
3133+
//
3134+
// For clarity, SYMCRYPT_PCT_* should be used instead of SYMCRYPT_SELFTEST_KEY_* going forward.
3135+
// The latter is retained for compatibility with existing code, but may be removed in a future
3136+
// breaking change.
31333137

31343138
// Dlkey selftest flags
31353139
// DSA Pairwise Consistency Test to be run generated keys
31363140
#define SYMCRYPT_SELFTEST_KEY_DSA (0x1)
3141+
#define SYMCRYPT_PCT_DSA SYMCRYPT_SELFTEST_KEY_DSA
31373142

31383143
// Eckey selftest flags
31393144
// ECDSA Pairwise Consistency Test to be run generated keys
31403145
#define SYMCRYPT_SELFTEST_KEY_ECDSA (0x1)
3146+
#define SYMCRYPT_PCT_ECDSA SYMCRYPT_SELFTEST_KEY_ECDSA
31413147

31423148
// Rsakey selftest flags
31433149
// RSA Pairwise Consistency Test to be run generated keys
31443150
#define SYMCRYPT_SELFTEST_KEY_RSA_SIGN (0x1)
3151+
#define SYMCRYPT_PCT_RSA_SIGN SYMCRYPT_SELFTEST_KEY_RSA_SIGN
31453152

31463153
UINT32
31473154
SYMCRYPT_CALL

lib/dlkey.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -480,12 +480,16 @@ SymCryptDlkeyGenerate(
480480
{
481481
if( ( flags & SYMCRYPT_FLAG_DLKEY_DSA ) != 0 )
482482
{
483+
// Ensure DSA algorithm selftest is run before first use of DSA algorithm
484+
SYMCRYPT_RUN_SELFTEST_ONCE(
485+
SymCryptDsaSelftest,
486+
SYMCRYPT_SELFTEST_ALGORITHM_DSA );
487+
483488
// Run PCT eagerly as the key can only be used for DSA - there is no value in deferring
484-
SYMCRYPT_RUN_KEYGEN_PCT(
485-
SymCryptDsaSignVerifyTest,
489+
SYMCRYPT_RUN_KEY_PCT(
490+
SymCryptDsaPct,
486491
pkDlkey,
487-
SYMCRYPT_SELFTEST_ALGORITHM_DSA,
488-
SYMCRYPT_SELFTEST_KEY_DSA );
492+
SYMCRYPT_PCT_DSA );
489493
}
490494

491495
if( ( flags & SYMCRYPT_FLAG_DLKEY_DH ) != 0 )
@@ -796,8 +800,10 @@ SymCryptDlkeySetValue(
796800

797801
if( pkDlkey->fHasPrivateKey )
798802
{
799-
// We do not need to run a DSA PCT on import, indicate that the test has been run
800-
pkDlkey->fAlgorithmInfo |= SYMCRYPT_SELFTEST_KEY_DSA;
803+
SYMCRYPT_RUN_KEY_PCT(
804+
SymCryptDsaPct,
805+
pkDlkey,
806+
SYMCRYPT_PCT_DSA );
801807
}
802808
}
803809

lib/ec_dsa.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -418,11 +418,10 @@ SymCryptEcDsaSign(
418418
}
419419

420420
// If the key was generated and a PCT has not yet been performed - perform PCT before first use
421-
SYMCRYPT_RUN_KEYGEN_PCT(
422-
SymCryptEcDsaSignVerifyTest,
421+
SYMCRYPT_RUN_KEY_PCT(
422+
SymCryptEcDsaPct,
423423
pKey,
424-
SYMCRYPT_SELFTEST_ALGORITHM_ECDSA,
425-
SYMCRYPT_SELFTEST_KEY_ECDSA );
424+
SYMCRYPT_PCT_ECDSA );
426425

427426
return SymCryptEcDsaSignEx( pKey, pbHashValue, cbHashValue, NULL, format, flags, pbSignature, cbSignature );
428427
}

lib/eckey.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -547,11 +547,8 @@ SymCryptEckeySetValue(
547547
SymCryptEcDsaSelftest,
548548
SYMCRYPT_SELFTEST_ALGORITHM_ECDSA );
549549

550-
if( pEckey->hasPrivateKey )
551-
{
552-
// We do not need to run an ECDSA PCT on import, indicate that the test has been run
553-
pEckey->fAlgorithmInfo |= SYMCRYPT_SELFTEST_KEY_ECDSA;
554-
}
550+
// ECDSA PCT is deferred until the key is used or exported - see SymCryptEcDsaSign and
551+
// SymCryptEckeyGetValue
555552
}
556553

557554
if ( ( flags & SYMCRYPT_FLAG_ECKEY_ECDH ) != 0 )
@@ -658,11 +655,10 @@ SymCryptEckeyGetValue(
658655
if ( ((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) != 0) &&
659656
((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0) )
660657
{
661-
SYMCRYPT_RUN_KEYGEN_PCT(
662-
SymCryptEcDsaSignVerifyTest,
658+
SYMCRYPT_RUN_KEY_PCT(
659+
SymCryptEcDsaPct,
663660
pEckey,
664-
SYMCRYPT_SELFTEST_ALGORITHM_ECDSA,
665-
SYMCRYPT_SELFTEST_KEY_ECDSA );
661+
SYMCRYPT_PCT_ECDSA );
666662
}
667663

668664
// Copy the key into the temporary integer

0 commit comments

Comments
 (0)