Merged PR 7349481: Avoid Unnecessary Pairwise Conditional Tests on (EC)DH key generation

+ Avoid Unnecessary Pairwise Conditional Tests on (EC)DH key generation
+ Enable deferred testing of PCTs for all asymmetric key generation
  + Introduce a new UINT32 field in the (Dl|Ec|Rsa)key structures to track what algorithms the key may be used for, and which key PCTs have been run
+ For ECDSA, perform PCT before first use of private key in an sign
  operation
+ For RSA and DSA, just perform the PCT unconditionally at key generation time
+ Remove the (EC)DH PCT functions entirely. They are not necessary for
  FIPS and no calling application should be using them as they were very
  recently introduced.
+ Fix corner case bug with DH and explicitly set private key lengths not having the correct validation.

Related work items: #37791870, #39478648
This commit is contained in:
Samuel Lee 2022-05-25 19:51:34 +00:00
Родитель 31e06ae046
Коммит 317e785816
27 изменённых файлов: 1029 добавлений и 942 удалений

Просмотреть файл

@ -1,3 +1,9 @@
# Version 102.0
- Breaking change to Asymmetric key generation and import handling, sanitizing flags required for FIPS
- Trim symbols exposed in SymCrypt module to those specified in symcrypt.h
- Introduce logic enabling FIPS per-key tests to be deferred to before first use, rather than at generation time
# Version 101.3
- Fix for OpenEnclave binary to workaround clang bug

Просмотреть файл

@ -370,7 +370,7 @@ SymCryptStoreMsbFirstUint64(
SIZE_T cbDst );
//
// Functions to retreive the bitsize/bytesize of UINT32/UINT64 values
// Functions to retrieve the bitsize/bytesize of UINT32/UINT64 values
// Note: the bitsize/bytesize of the value 0 is defined as 0.
// Some data formats don't allow empty encodings, so the caller
// should ensure they handle the 0-case properly.
@ -5123,86 +5123,41 @@ SymCryptEckeyCopy(
//=====================================================
// On-demand self-test flags
// Flags for asymmetric key generation and import
// These flags can be passed in at key generation or import time to indicate that the
// corresponding pairwise consistency test should be run. Running these tests is required
// to be compliant with FIPS 140-3, but because they are computationally expensive, we do not
// run them at module start-up. It is the caller's responsibility to pass in the appropriate flag
// at key generation or import time.
//
// Why are these flags algorithm specific? Because SymCrypt does not distinguish between ECC keys
// used for ECDSA vs. ECC keys used for ECDH, or DL keys used for DSA vs. DL keys used for DH, the
// caller must use the appropriate flag to indicate what the key will be used for and therefore
// which selftest needs to be run.
//
// Note that per FIPS requirements, testing each imported key is not required, but the appropriate
// algorithm test must be run once before an algorithm can be used. Therefore, the key import
// test will be run at most one time per algorithm. SymCrypt handles this internally. For key
// generation, however, each generated key must be tested, so the key generation test will be run
// once per key generated.
#define SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA (0x100)
#define SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH (0x200)
// These flags are introduced primarily for FIPS purposes. For FIPS 140-3 rather than expose to the
// caller the specifics of what tests will be run with various algorithms, we are sanitizing flags
// provided on asymmetric key generation and import to enable the caller to indicate their intent,
// and for SymCrypt to perform the required testing.
// Below we define the flags that can be passed and when a caller should set them.
// The specifics of what tests will be run are likely to change over time, as FIPS requirements and
// our understanding of how best to implement them, change over time. Callers should not rely on
// specific behavior.
#define SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA (0x100)
#define SYMCRYPT_FLAG_DLKEY_SELFTEST_DH (0x200)
#define SYMCRYPT_FLAG_RSAKEY_SELFTEST (0x100)
// Validation required by FIPS is enabled by default. This flag enables a caller to opt out of this
// validation.
#define SYMCRYPT_FLAG_KEY_NO_FIPS (0x100)
//=====================================================
// Generic key validation flags
// Currently only apply to DH, DSA, ECDH, and ECDSA.
// When opting out of FIPS, SymCrypt may still perform some sanity checks on key import
// In very performance sensitive situations where a caller strongly trusts the values it is passing
// to SymCrypt and does not care about FIPS (or can statically prove properties about the imported
// keys), a caller may specify SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION in addition to
// SYMCRYPT_FLAG_KEY_NO_FIPS to skip costly checks
#define SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION (0x200)
// SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION: When set in a SetValue call, minimize costly validation.
// Only to be used in very performance sensitive situations where the caller strongly trusts the values
// it is passing to SymCrypt
// Cannot be specified with SYMCRYPT_FLAG_KEY_RANGE_VALIDATION or SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION
#define SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION (0x10)
// Callers must specify what algorithm(s) a given asymmetric key will be used for.
// This information will be tracked by SymCrypt, and attempting to use the key in an algorithm it
// was not generated or imported for will result in failure.
// If no algorithm is specified then the key generation or import function will fail.
#define SYMCRYPT_FLAG_DLKEY_DSA (0x1000)
#define SYMCRYPT_FLAG_DLKEY_DH (0x2000)
// Maintain old ECC specific flag for backwards compatibility
#define SYMCRYPT_FLAG_ECC_NO_VALIDATION SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION
// SYMCRYPT_FLAG_KEY_RANGE_VALIDATION: When set in a SetValue call, ensure that:
// Generated or imported Private key:
// For DH/DSA:
// Check private key is in the range: [1, q-1]
// If Dlgroup is a named safe-prime group, nBitsPriv is specified either using a default
// value or using SymCryptDlkeySetPrivateKeyLength, such that 2s <= nBitsPriv <= nBitsOfQ.
// In this case, we enforce that the private key is in the reduced range [1, min(2^nBitsPriv, q)-1]
// (s is the maximum security strength for a named safe-prime group as specified in SP800-56arev3)
// If q is not known, this will cause SYMCRYPT_INVALID_ARGUMENT
// For ECDH/ECDSA:
// For Curves with Canonical Private key format: Private key is in range [1, GOrd-1]
// Currently only Short-Weierstrass curves use the SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL format
// For other Curves: Private key is non-zero
// Generated or imported Public key:
// For DH/DSA: Public key in range [2, p-2]
// For ECDH/ECDSA:
// Public key is nonzero, has coordinates in the underlying field
// and for non-Montgomery Curves: Public key is on the curve
// Cannot be specified with SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION or SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION
#define SYMCRYPT_FLAG_KEY_RANGE_VALIDATION (0x20)
// SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION: When set in a SetValue, Generate, or SetRandom call, ensure that:
// Range validation ensured as for SYMCRYPT_FLAG_KEY_RANGE_VALIDATION
// In the case of generation of a Private key this is done by construction
// and
// Generated or imported Public key is in a subgroup of the correct order. i.e.:
// For DH/DSA: Verify that (Public key)^Q == 1 mod P
// If Q is not known, this will cause SYMCRYPT_INVALID_ARGUMENT
// For ECDH/ECDSA: Verify that GOrd*(Public key) == O
// Cannot be specified with SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION or SYMCRYPT_FLAG_KEY_RANGE_VALIDATION
#define SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION (0x30)
// SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION: When set in a SetValue call, ensure that:
// If a Public and Private key are imported:
// Use the imported Private key to generate a Public key, and check the generated Public key is equal
// to the imported Public key
#define SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION (0x40)
// Maintain old DL specific flag for backwards compatibility
#define SYMCRYPT_FLAG_DLKEY_VERIFY SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION
#define SYMCRYPT_FLAG_ECKEY_ECDSA (0x1000)
#define SYMCRYPT_FLAG_ECKEY_ECDH (0x2000)
#define SYMCRYPT_FLAG_RSAKEY_SIGN (0x1000)
#define SYMCRYPT_FLAG_RSAKEY_ENCRYPT (0x2000)
//=====================================================
// RSA key operations
@ -5291,11 +5246,14 @@ SymCryptRsakeyGenerate(
//
// Allowed flags:
//
// - SYMCRYPT_FLAG_RSAKEY_SELFTEST
// Perform a pairwise consistency test on the generated key.
// This flag must be set for callers who require compliance with FIPS 140-3. Any failure
// in the selftest will cause a fatal error, as it indicates that the module cannot operate
// in a FIPS-compliant mode.
// - SYMCRYPT_FLAG_KEY_NO_FIPS
// Opt-out of performing validation required for 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
//
SYMCRYPT_ERROR
@ -5323,11 +5281,17 @@ SymCryptRsakeySetValue(
//
// Allowed flags:
//
// - SYMCRYPT_FLAG_RSAKEY_SELFTEST
// Perform an RSA algorithm test, if not already been done.
// This flag must be set for callers who require compliance with FIPS 140-3. Any failure
// in the selftest will cause a fatal error, as it indicates that the module cannot operate
// in a FIPS-compliant mode.
// - 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 all primes are stored in the same format specified by numFormat.
@ -5403,6 +5367,20 @@ SymCryptRsakeyGetCrtValue(
// - Currently, the only acceptable value of nCrtExponent is 2 or 0.
// pbCrtCoefficient, pbPrivateExponent can be NULL;
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptRsakeyExtendKeyUsage(
_Inout_ PSYMCRYPT_RSAKEY pkRsakey,
UINT32 flags );
//
// Enable an existing key which has been generated or imported to be used in specified algorithms.
// Some callers may not know at key generation or import time what algorithms a key will be used for
// and this API allows the key to be extended for use in additional algorithms. Use of this API may
// not be compliant with FIPS 140-3
//
// - flags must be some bitwise OR of the following flags:
// SYMCRYPT_FLAG_RSAKEY_SIGN
// SYMCRYPT_FLAG_RSAKEY_ENCRYPT
#define SYMCRYPT_DLGROUP_FIPS_LATEST (SYMCRYPT_DLGROUP_FIPS_186_3)
@ -5652,32 +5630,22 @@ SymCryptDlkeyGenerate(
_Inout_ PSYMCRYPT_DLKEY pkDlkey );
//
// Allowed flags:
// - SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION
// Described in the key validation flag definitions above. Intended use is to allow additional
// (expensive) checks required by FIPS (SP800-56arev3) to be performed for compliance.
// Provided the Dlgroup is well formed, and the prime Q is known, generated keypairs will always
// pass these checks, so it is not recommended to set this flag unless required, as it makes the
// operation slower without affecting the results.
//
// - SYMCRYPT_FLAG_DLKEY_GEN_MODP
// When set, generate a private key between 1 and P-2.
// When Q is known, this overrides the default behavior of generating a private key between 1 and Q-1,
// or 1 and min(2^nBitsPriv-1, Q-1) for named safe-prime groups
// When Q is not known, this does not affect the behavior
//
// - SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA
// Perform a DSA pairwise consistency test on the generated key. For keys which will be used with
// DSA, this flag must be set for callers who require compliance with FIPS 140-3. Any failure
// in the selftest will cause a fatal error, as it indicates that the module cannot operate
// in a FIPS-compliant mode.
// - SYMCRYPT_FLAG_KEY_NO_FIPS
// Opt-out of performing validation required for FIPS
//
// - SYMCRYPT_FLAG_DLKEY_SELFTEST_DH
// Equivalent to SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA, but for keys which will be used with DH.
// - At least one of the flags indicating what the Dlkey is to be used for must be specified:
// SYMCRYPT_FLAG_DLKEY_DSA
// SYMCRYPT_FLAG_DLKEY_DH
//
// Note:
// If SYMCRYPT_FLAG_DLKEY_GEN_MODP is specified in conjuction with
// SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION a SYMCRYPT_INVALID_ARGUMENT error will be
// returned, as Private key range validation requires the default generation behavior
// If SYMCRYPT_FLAG_DLKEY_GEN_MODP is specified then SYMCRYPT_FLAG_KEY_NO_FIPS must also be
// specified to avoid SYMCRYPT_INVALID_ARGUMENT, as FIPS requires the default generation behavior
//
SYMCRYPT_ERROR
@ -5695,21 +5663,17 @@ SymCryptDlkeySetValue(
//
// Allowed flags:
//
// - SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA
// Perform a DSA algorithm test, if not already done. For keys which will be used with
// DSA, this flag must be set for callers who require compliance with FIPS 140-3. Any failure
// in the selftest will cause a fatal error, as it indicates that the module cannot operate
// in a FIPS-compliant mode.
// - SYMCRYPT_FLAG_KEY_NO_FIPS
// Opt-out of performing validation required for FIPS
//
// - SYMCRYPT_FLAG_DLKEY_SELFTEST_DH
// Equivalent to SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA, but for keys which will be used with DH.
// - SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION
// Opt-out of performing almost all validation - must be specified with SYMCRYPT_FLAG_KEY_NO_FIPS
//
// - Optionally, at most 1 of
// SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION,
// SYMCRYPT_FLAG_KEY_RANGE_VALIDATION, and
// SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION
// - and optionally SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION
// Described in the key validation flag definitions above.
// - At least one of the flags indicating what the Dlkey is to be used for must be specified:
// SYMCRYPT_FLAG_DLKEY_DSA
// SYMCRYPT_FLAG_DLKEY_DH
//
// Described in more detail in the "Flags for asymmetric key generation and import" section above
//
SYMCRYPT_ERROR
@ -5729,6 +5693,21 @@ SymCryptDlkeyGetValue(
// allocated by the caller.
//
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptDlkeyExtendKeyUsage(
_Inout_ PSYMCRYPT_DLKEY pkDlkey,
UINT32 flags );
//
// Enable an existing key which has been generated or imported to be used in specified algorithms.
// Some callers may not know at key generation or import time what algorithms a key will be used for
// and this API allows the key to be extended for use in additional algorithms. Use of this API may
// not be compliant with FIPS 140-3
//
// - flags must be some bitwise OR of the following flags:
// SYMCRYPT_FLAG_DLKEY_DSA
// SYMCRYPT_FLAG_DLKEY_DH
//=====================================================
// Elliptic curve operations and supported curves
//
@ -5903,28 +5882,23 @@ SymCryptEckeySetValue(
//
// At least one of the public and private keys must be provided.
//
// If both are provided, then they should match. They are required to match when
// SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION is specified.
// If both are provided, then they must match.
//
// The algorithm always sets the corresponding public key
//
// Allowed flags:
//
// - SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA
// Perform an ECDSA algorithm test, if not already done. For keys which will be used with
// ECDSA, this flag must be set for callers who require compliance with FIPS 140-3. Any failure
// in the selftest will cause a fatal error, as it indicates that the module cannot operate
// in a FIPS-compliant mode.
// - SYMCRYPT_FLAG_KEY_NO_FIPS
// Opt-out of performing validation required for FIPS
//
// - SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH
// Equivalent to SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA, but for keys which will be used with ECDH.
// - SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION
// Opt-out of performing almost all validation - must be specified with SYMCRYPT_FLAG_KEY_NO_FIPS
//
// - Optionally, at most 1 of
// SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION,
// SYMCRYPT_FLAG_KEY_RANGE_VALIDATION, and
// SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION
// - and optionally SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION
// Described in the key validation flag definitions above.
// - At least one of the flags indicating what the Eckey is to be used for must be specified:
// SYMCRYPT_FLAG_ECKEY_ECDSA
// SYMCRYPT_FLAG_ECKEY_ECDH
//
// Described in more detail in the "Flags for asymmetric key generation and import" section above
//
SYMCRYPT_ERROR
@ -5944,21 +5918,14 @@ SymCryptEckeySetRandom(
//
// Allowed flags:
//
// - SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA
// Perform an ECDSA pairwise consistency test on the generated key. For keys which will be used with
// ECDSA, this flag must be set for callers who require compliance with FIPS 140-3. Any failure
// in the selftest will cause a fatal error, as it indicates that the module cannot operate
// in a FIPS-compliant mode.
// - SYMCRYPT_FLAG_KEY_NO_FIPS
// Opt-out of performing validation required for FIPS
//
// - SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH
// Equivalent to SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA, but for keys which will be used with ECDH.
//
// - SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION
// Described in the key validation flag definitions above. Intended use is to allow additional
// (expensive) checks required by FIPS (SP800-56arev3) to be performed for compliance.
// Provided the Ecurve is well formed, generated keypairs will always pass these checks, so it is
// not recommended to set this flag unless required, as it makes the operation slower without
// affecting the results.
// - At least one of the flags indicating what the Eckey is to be used for must be specified:
// SYMCRYPT_FLAG_ECKEY_ECDSA
// SYMCRYPT_FLAG_ECKEY_ECDH
// Described in more detail in the "Flags for asymmetric key generation and import" section above
//
SYMCRYPT_ERROR
@ -5979,11 +5946,10 @@ SymCryptEckeyGetValue(
// allocated by the caller.
//
// If (pbPrivateKey != NULL), then the function will return the private key in pbPrivateKey
// in the format specified by the numFormat parameter **as long as** the following two
// in the format specified by the numFormat parameter **as long as** the following three
// requirements are satisfied:
// 1. cbPrivateKey >= SymCryptEckeyGetSizeofPrivateKey( pEckey )
// 2. pEckey contains a private key part (If this fails the function returns SYMCRYPT_INVALID_BLOB)
// If (pbPrivateKey == NULL) and (cbPrivateKey != 0), then it returns SYMCRYPT_INVALID_ARGUMENT.
// If (pbPrivateKey == NULL) and (cbPrivateKey == 0), then these parameters are ignored
// and no private key is returned.
//
@ -5991,7 +5957,6 @@ SymCryptEckeyGetValue(
// in the format specified by the numFormat and the ecPointFormat parameters
// **as long as** the following requirement is satisfied:
// 1. cbPublicKey >= SymCryptEckeyGetSizeofPublicKey( pEckey, ecPointFormat )
// If (pbPublicKey == NULL) and (cbPublicKey != 0), then it returns SYMCRYPT_INVALID_ARGUMENT.
// If (pbPublicKey == NULL) and (cbPublicKey == 0), then these parameters are ignored
// and no public key is returned.
//
@ -5999,6 +5964,21 @@ SymCryptEckeyGetValue(
// - None.
//
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptEckeyExtendKeyUsage(
_Inout_ PSYMCRYPT_ECKEY pEckey,
UINT32 flags );
//
// Enable an existing key which has been generated or imported to be used in specified algorithms.
// Some callers may not know at key generation or import time what algorithms a key will be used for
// and this API allows the key to be extended for use in additional algorithms. Use of this API may
// not be compliant with FIPS 140-3
//
// - flags must be some bitwise OR of the following flags:
// SYMCRYPT_FLAG_ECKEY_ECDSA
// SYMCRYPT_FLAG_ECKEY_ECDH
/************************
* Crypto algorithm API *
************************/
@ -6343,23 +6323,15 @@ SymCryptRsaPssVerify(
// None
//
VOID
SYMCRYPT_CALL
SymCryptRsaSignVerifyTest( PCSYMCRYPT_RSAKEY pkRsakey );
//
// FIPS self-test for RSA sign/verify. If the self-test fails, SymCryptFatal will be called to
// fastfail. Rather than calling this function directly, the caller can pass
// SYMCRYPT_FLAG_RSAKEY_SELFTEST into SymCryptRsakeyGenerate/SymCryptRsakeySetValue.
//
VOID
SYMCRYPT_CALL
SymCryptRsaSelftest( );
//
// Wrapper which calls SymCryptRsaSignVerifyTest with a hard-coded key. Used to satisfy the FIPS
// test-before-use requirement in the case that no keys are generated. Rather than calling this
// function directly, the caller can pass SYMCRYPT_FLAG_RSAKEY_SELFTEST into
// SymCryptRsakeyGenerate/SymCryptRsakeySetValue.
// FIPS self-test for RSA sign/verify. This function uses a hardcoded key to perform the self-test
// without having to generate a key. If the self-test fails, SymCryptFatal will be called to
// fastfail.
// The self-test will automatically be performed before first operational use of RSA if using a key
// with FIPS validation, so most callers should never use this function.
//
@ -6408,22 +6380,15 @@ SymCryptDsaVerify(
// None
//
VOID
SYMCRYPT_CALL
SymCryptDsaSignVerifyTest( PCSYMCRYPT_DLKEY pkDlkey );
//
// FIPS self-test for DSA sign/verify. If the self-test fails, SymCryptFatal will be called to
// fastfail. Rather than calling this function directly, the caller can pass
// SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA into SymCryptDlkeyGenerate/SymCryptDlkeySetValue.
//
VOID
SYMCRYPT_CALL
SymCryptDsaSelftest( );
//
// Wrapper which calls SymCryptDsaSignVerifyTest with a hard-coded key. Used to satisfy the FIPS
// test-before-use requirement. Rather than calling this function directly, the caller can pass
// SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA into SymCryptDlkeyGenerate/SymCryptDlkeySetValue.
// FIPS self-test for DSA sign/verify. This function uses a hardcoded key to perform the self-test
// without having to generate a key. If the self-test fails, SymCryptFatal will be called to
// fastfail.
// The self-test will automatically be performed before first operational use of DSA if using a key
// with FIPS validation, so most callers should never use this function.
//
//
@ -6449,24 +6414,15 @@ SymCryptDhSecretAgreement(
// - None
//
VOID
SYMCRYPT_CALL
SymCryptDhSecretAgreementPairwiseConsistencyTest( PCSYMCRYPT_DLKEY pkKey1 );
//
// FIPS self-test for DH secret agreement. If the self-test fails, SymCryptFatal will be called to
// fastfail. Rather than calling this function directly, the caller can pass
// SYMCRYPT_FLAG_DLKEY_SELFTEST_DH into SymCryptDlkeyGenerate/SymCryptDlkeySetValue.
//
VOID
SYMCRYPT_CALL
SymCryptDhSecretAgreementSelftest();
//
// FIPS self-test for DH secret agreement. Unlike the above function, this function uses two
// hardcoded keys and a precalculated known answer to perform the selftest without having to
// generate a key. If the self-test fails, SymCryptFatal will be called to fastfail. Rather than
// calling this function directly, the caller can pass
// SYMCRYPT_FLAG_DLKEY_SELFTEST_DH into SymCryptDlkeyGenerate/SymCryptDlkeySetValue.
// FIPS self-test for DH secret agreement. This function uses two hardcoded keys and a precalculated
// known answer to perform the self-test without having to generate a key. If the self-test fails,
// SymCryptFatal will be called to fastfail.
// The self-test will automatically be performed before first operational use of DH if using keys
// with FIPS validation, so most callers should never use this function.
//
//
@ -6522,22 +6478,15 @@ SymCryptEcDsaVerify(
// SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION: If set then the hash value will
// not be truncated.
VOID
SYMCRYPT_CALL
SymCryptEcDsaSignVerifyTest( PCSYMCRYPT_ECKEY pkEckey );
//
// FIPS self-test for ECDSA sign/verify. If the self-test fails, SymCryptFatal will be called to
// fastfail. Rather than calling this function directly, the caller can pass
// SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA into SymCryptDlkeyGenerate/SymCryptDlkeySetValue.
VOID
SYMCRYPT_CALL
SymCryptEcDsaSelftest( );
//
// Wrapper which calls SymCryptEcDsaSignVerifyTest with a hard-coded key. Used to satisfy the FIPS
// test-before-use requirement. Rather than calling this function directly, the caller can pass
// SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA into SymCryptDlkeyGenerate/SymCryptDlkeySetValue.
// FIPS self-test for ECDSA sign/verify. This function uses a hardcoded key to perform the self-test
// without having to generate a key. If the self-test fails, SymCryptFatal will be called to
// fastfail.
// The self-test will automatically be performed before first operational use of ECDSA if using a
// key with FIPS validation, so most callers should never use this function.
//
//
@ -6562,24 +6511,15 @@ SymCryptEcDhSecretAgreement(
// - None
//
VOID
SYMCRYPT_CALL
SymCryptEcDhSecretAgreementPairwiseConsistencyTest( PCSYMCRYPT_ECKEY pkKey1 );
//
// FIPS self-test for ECDH secret agreement. If the self-test fails, SymCryptFatal will be called
// to fastfail. Rather than calling this function directly, the caller can pass
// SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH into SymCryptEckeySetRandom/SymCryptEckeySetValue.
//
VOID
SYMCRYPT_CALL
SymCryptEcDhSecretAgreementSelftest( );
//
// FIPS self-test for ECDH secret agreement. Unlike the above function, this function uses two
// hardcoded keys and a precalculated known answer to perform the selftest without having to
// generate a key. If the self-test fails, SymCryptFatal will be called to fastfail. Rather than
// calling this function directly, the caller can pass
// SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH into SymCryptEckeySetRandom/SymCryptEckeySetValue.
// FIPS self-test for ECDH secret agreement. This function uses two hardcoded keys and a
// precalculated known answer to perform the self-test without having to generate a key. If the
// self-test fails, SymCryptFatal will be called to fastfail.
// The self-test will automatically be performed before first operational use of ECDH if using keys
// with FIPS validation, so most callers should never use this function.
//
//

Просмотреть файл

@ -2070,6 +2070,11 @@ SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_MODELEMENT {
// the RSA modulus and each prime.
typedef SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_RSAKEY {
UINT32 fAlgorithmInfo; // Tracks which algorithms the key can be used in
// Also tracks which per-key selftests have been performed on this key
// A bitwise OR of SYMCRYPT_FLAG_KEY_*, SYMCRYPT_FLAG_RSAKEY_*, and
// SYMCRYPT_SELFTEST_KEY_* values
UINT32 cbTotalSize; // Total size of the rsa key
BOOLEAN hasPrivateKey; // Set to true if there is private key information set
@ -2219,12 +2224,17 @@ typedef const SYMCRYPT_DLGROUP * PCSYMCRYPT_DLGROUP;
// DLKEY type
//
typedef SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_DLKEY {
PCSYMCRYPT_DLGROUP pDlgroup; // Handle to the group which created the key
UINT32 fAlgorithmInfo; // Tracks which algorithms the key can be used in
// Also tracks which per-key selftests have been performed on this key
// A bitwise OR of SYMCRYPT_FLAG_KEY_*, SYMCRYPT_FLAG_DLKEY_*, and
// SYMCRYPT_SELFTEST_KEY_* values
BOOLEAN fHasPrivateKey; // Set to true if there is a private key set
BOOLEAN fPrivateModQ; // Set to true if the private key is at most Q-1, otherwise it is at most P-2
UINT32 nBitsPriv; // Number of bits used in private keys
PCSYMCRYPT_DLGROUP pDlgroup; // Handle to the group which created the key
PBYTE pbPrivate; // SYMCRYPT_ASYM_ALIGN'ed buffer that points to the memory allocated for the private key
PSYMCRYPT_MODELEMENT pePublicKey; // Public key (modelement modulo P)
@ -2380,11 +2390,15 @@ typedef SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_ECPOINT {
typedef const SYMCRYPT_ECPOINT * PCSYMCRYPT_ECPOINT;
typedef SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_ECKEY {
BOOLEAN hasPrivateKey; // Set to true if there is a private key set
PCSYMCRYPT_ECURVE pCurve; // Handle to the curve which created the key
UINT32 fAlgorithmInfo; // Tracks which algorithms the key can be used in
// Also tracks which per-key selftests have been performed on this key
// A bitwise OR of SYMCRYPT_FLAG_KEY_*, SYMCRYPT_FLAG_ECKEY_*, and
// SYMCRYPT_SELFTEST_KEY_* values
BOOLEAN hasPrivateKey; // Set to true if there is a private key set
PCSYMCRYPT_ECURVE pCurve; // Handle to the curve which created the key
PSYMCRYPT_ECPOINT poPublicKey; // Public key (ECPOINT)
PSYMCRYPT_INT piPrivateKey; // Private key
PSYMCRYPT_ECPOINT poPublicKey; // Public key (ECPOINT)
PSYMCRYPT_INT piPrivateKey; // Private key
SYMCRYPT_MAGIC_FIELD
@ -2766,17 +2780,46 @@ SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
#define SYMCRYPT_FIPS_ASSERT(x) { if(!(x)){ SymCryptFatal('FIPS'); } }
// Flags for on-demand selftests. When an on-demand selftest succeeds, the corresponding flag
// Flags for FIPS on-demand selftests. When an on-demand selftest succeeds, the corresponding flag
// will be set in g_SymCryptFipsSelftestsPerformed. Other selftests are performed automatically
// when the module is loaded, so they don't have a corresponding flag.
typedef enum {
SYMCRYPT_SELFTEST_NONE = 0x0,
SYMCRYPT_SELFTEST_STARTUP = 0x1,
SYMCRYPT_SELFTEST_DSA = 0x2,
SYMCRYPT_SELFTEST_ECDSA = 0x4,
SYMCRYPT_SELFTEST_RSA = 0x8,
SYMCRYPT_SELFTEST_DH_SECRET_AGREEMENT = 0x10,
SYMCRYPT_SELFTEST_ECDH_SECRET_AGREEMENT = 0x20
} SYMCRYPT_FIPS_SELFTEST;
typedef enum _SYMCRYPT_SELFTEST_ALGORITHM {
SYMCRYPT_SELFTEST_ALGORITHM_NONE = 0x0,
SYMCRYPT_SELFTEST_ALGORITHM_STARTUP = 0x1,
SYMCRYPT_SELFTEST_ALGORITHM_DSA = 0x2,
SYMCRYPT_SELFTEST_ALGORITHM_ECDSA = 0x4,
SYMCRYPT_SELFTEST_ALGORITHM_RSA = 0x8,
SYMCRYPT_SELFTEST_ALGORITHM_DH = 0x10,
SYMCRYPT_SELFTEST_ALGORITHM_ECDH = 0x20,
} SYMCRYPT_SELFTEST_ALGORITHM;
extern SYMCRYPT_FIPS_SELFTEST g_SymCryptFipsSelftestsPerformed;
// Takes values which are some bitwise OR combination of SYMCRYPT_SELFTEST_ALGORITHM values
// Specified as UINT32 as we will update with 32 bit atomics, and compilers may choose to make enum
// types smaller than 32 bits.
extern UINT32 g_SymCryptFipsSelftestsPerformed;
// Flags for per-key selftests.
// When an asymmetric key is generated or imported, and SYMCRYPT_FLAG_KEY_NO_FIPS is not specified,
// some selftests must be performed on the key, before its operational use in an algorithm, to
// comply with FIPS.
// The algorithms the key may be used in will be tracked in the key's fAlgorithmInfo field, as a
// bitwise OR of SYMCRYPT_FLAG_<keytype>_<algorithm> (e.g. SYMCRYPT_FLAG_DLKEY_DH).
// This field will also track which per-key selftests have been run on the key using the below flags
// We want to track which selftests have been run independently of which algorithms the key may be
// used in as in some scenarios at key generation / import time we may not know what algorithm the
// key will actually be used in. Tracking the run per-key selftests in fAlgorithmInfo allows us to
// defer running expensive tests until we know they are required (e.g. if we generate an Eckey which
// may be used in ECDH or ECDSA, and only use it for ECDH, the ECDSA PCT is deferred until we first
// attempt to use the key in ECDSA, or export the private key).
// Dlkey selftest flags
// DSA Pairwise Consistency Test to be run generated keys
#define SYMCRYPT_SELFTEST_KEY_DSA (0x1)
// Eckey selftest flags
// ECDSA Pairwise Consistency Test to be run generated keys
#define SYMCRYPT_SELFTEST_KEY_ECDSA (0x1)
// Rsakey selftest flags
// RSA Pairwise Consistency Test to be run generated keys
#define SYMCRYPT_SELFTEST_KEY_RSA_SIGN (0x1)

Просмотреть файл

@ -22,8 +22,8 @@
// The API numbering starts at 100 to avoid number conficts with the old system.
//
#define SYMCRYPT_CODE_VERSION_API 101
#define SYMCRYPT_CODE_VERSION_MINOR 3
#define SYMCRYPT_CODE_VERSION_API 102
#define SYMCRYPT_CODE_VERSION_MINOR 0
#define SYMCRYPT_CODE_VERSION_PATCH 0
#if defined(DBG)

Просмотреть файл

@ -105,6 +105,14 @@ SymCryptDhSecretAgreement(
UINT32 nBitsOfExp = 0;
// Make sure that the keys may be used in DH
if ( ((pkPrivate->fAlgorithmInfo & SYMCRYPT_FLAG_DLKEY_DH) == 0) ||
((pkPublic->fAlgorithmInfo & SYMCRYPT_FLAG_DLKEY_DH) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Make sure we only specify the correct flags and that
// there is a private key
if ( (flags != 0) || (!pkPrivate->fHasPrivateKey) )

Просмотреть файл

@ -65,6 +65,7 @@ SymCryptDlkeyCreate(
pkRes = (PSYMCRYPT_DLKEY) pbBuffer;
// DLKEY parameters
pkRes->fAlgorithmInfo = 0;
pkRes->pDlgroup = pDlgroup;
pkRes->fHasPrivateKey = FALSE;
pkRes->fPrivateModQ = FALSE; // This will be properly set during generate or setvalue
@ -116,6 +117,7 @@ SymCryptDlkeyCopy(
//
if( pkSrc != pkDst )
{
pkDst->fAlgorithmInfo = pkSrc->fAlgorithmInfo;
pkDst->fHasPrivateKey = pkSrc->fHasPrivateKey;
pkDst->fPrivateModQ = pkSrc->fPrivateModQ;
pkDst->nBitsPriv = pkSrc->nBitsPriv;
@ -197,6 +199,8 @@ SymCryptDlkeyHasPrivateKey( _In_ PCSYMCRYPT_DLKEY pkDlkey )
return pkDlkey->fHasPrivateKey;
}
#define SYMCRYPT_FLAG_DLKEY_PUBLIC_KEY_ORDER_VALIDATION (0x1)
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptDlkeyPerformPublicKeyValidation(
@ -239,7 +243,7 @@ SymCryptDlkeyPerformPublicKeyValidation(
}
// Perform validation that Public key is in a subgroup of order Q.
if ( (flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION )
if ( (flags & SYMCRYPT_FLAG_DLKEY_PUBLIC_KEY_ORDER_VALIDATION) != 0 )
{
peTmpPublicKeyExpQ = SymCryptModElementCreate( pbScratch, cbModElement, pDlgroup->pmP);
pbScratch += cbModElement;
@ -302,22 +306,24 @@ SymCryptDlkeyGenerate(
BYTE privMask;
UINT32 cntr;
// Ensure caller has specified what algorithm(s) the key will be used with
UINT32 algorithmFlags = SYMCRYPT_FLAG_DLKEY_DSA | SYMCRYPT_FLAG_DLKEY_DH;
// Make sure only allowed flags are specified
UINT32 allowedFlags = SYMCRYPT_FLAG_DLKEY_GEN_MODP |
SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION |
SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA |
SYMCRYPT_FLAG_DLKEY_SELFTEST_DH;
UINT32 allowedFlags = SYMCRYPT_FLAG_DLKEY_GEN_MODP | SYMCRYPT_FLAG_KEY_NO_FIPS | algorithmFlags;
if ( ( flags & ~allowedFlags ) != 0 )
if ( ( ( flags & ~allowedFlags ) != 0 ) ||
( ( flags & algorithmFlags ) == 0 ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// If any bits of SYMCRYPT_FLAG_KEY_VALIDATION_MASK are set, all bits of
// SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION must be set
if ( ( flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK ) != 0 &&
( flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK ) != SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION )
// Extra sanity checks when running with FIPS
// Either Dlgroup is named SafePrime group and key is for DH,
// or Dlgroup is not named SafePrime group and key is for DSA
if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
( (pDlgroup->isSafePrimeGroup && (flags & SYMCRYPT_FLAG_DLKEY_DSA)) ||
(!(pDlgroup->isSafePrimeGroup) && (flags & SYMCRYPT_FLAG_DLKEY_DH)) ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
@ -345,7 +351,7 @@ SymCryptDlkeyGenerate(
{
// We perform Private key range validation by construction
// The Private key is constructed in the range [1,min(2^nBitsPriv,Q)-1] precisely when pkDlkey->fPrivateModQ
if ( (flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION )
if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
@ -447,14 +453,13 @@ SymCryptDlkeyGenerate(
cbScratch );
// Perform range validation on generated Public key.
if ( (flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION )
if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
{
// Perform Public key validation.
// Always perform range validation
// May also perform validation that Public key is in subgroup of order Q, depending on flags
// Always perform range validation, and validation that Public key is in subgroup of order Q
scError = SymCryptDlkeyPerformPublicKeyValidation(
pkDlkey,
flags,
SYMCRYPT_FLAG_DLKEY_PUBLIC_KEY_ORDER_VALIDATION,
pbScratch,
cbScratch );
if ( scError != SYMCRYPT_NO_ERROR )
@ -466,17 +471,28 @@ SymCryptDlkeyGenerate(
// Set the fHasPrivateKey flag
pkDlkey->fHasPrivateKey = TRUE;
if( ( flags & SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA ) != 0 )
pkDlkey->fAlgorithmInfo = flags; // We want to track all of the flags in the Dlkey
if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
{
SYMCRYPT_RUN_KEYGEN_PCT( SymCryptDsaSignVerifyTest, pkDlkey, SYMCRYPT_SELFTEST_DSA );
}
if( ( flags & SYMCRYPT_FLAG_DLKEY_SELFTEST_DH ) != 0 )
{
SYMCRYPT_RUN_KEYGEN_PCT(
SymCryptDhSecretAgreementPairwiseConsistencyTest,
pkDlkey,
SYMCRYPT_SELFTEST_DH_SECRET_AGREEMENT );
if( ( flags & SYMCRYPT_FLAG_DLKEY_DSA ) != 0 )
{
// Run PCT eagerly as the key can only be used for DSA - there is no value in deferring
SYMCRYPT_RUN_KEYGEN_PCT(
SymCryptDsaSignVerifyTest,
pkDlkey,
SYMCRYPT_SELFTEST_ALGORITHM_DSA,
SYMCRYPT_SELFTEST_KEY_DSA );
}
if( ( flags & SYMCRYPT_FLAG_DLKEY_DH ) != 0 )
{
// No additional per-key tests to perform before first use.
// Just ensure we have run the algorithm selftest at least once.
SYMCRYPT_RUN_SELFTEST_ONCE(
SymCryptDhSecretAgreementSelftest,
SYMCRYPT_SELFTEST_ALGORITHM_DH );
}
}
cleanup:
@ -512,8 +528,7 @@ SymCryptDlkeySetValue(
PSYMCRYPT_MODELEMENT peTmp = NULL;
UINT32 cbModElement = SymCryptSizeofModElementFromModulus( pDlgroup->pmP );
BOOLEAN performRangeValidation = FALSE;
UINT32 fValidatePublicKeyOrder = SYMCRYPT_FLAG_DLKEY_PUBLIC_KEY_ORDER_VALIDATION;
if ( ((pbPrivateKey==NULL) && (cbPrivateKey!=0)) ||
((pbPublicKey==NULL) && (cbPublicKey!=0)) ||
@ -523,22 +538,41 @@ SymCryptDlkeySetValue(
goto cleanup;
}
// Ensure only allowed flags are specified
UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION |
SYMCRYPT_FLAG_KEY_RANGE_VALIDATION |
SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION |
SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION |
SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA |
SYMCRYPT_FLAG_DLKEY_SELFTEST_DH;
// Ensure caller has specified what algorithm(s) the key will be used with
UINT32 algorithmFlags = SYMCRYPT_FLAG_DLKEY_DSA | SYMCRYPT_FLAG_DLKEY_DH;
// Make sure only allowed flags are specified
UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS | SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION | algorithmFlags;
if ( ( flags & ~allowedFlags ) != 0 )
if ( ( ( flags & ~allowedFlags ) != 0 ) ||
( ( flags & algorithmFlags ) == 0 ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
performRangeValidation = ((flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_RANGE_VALIDATION) ||
((flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION);
// Extra sanity checks when running with FIPS
// Either Dlgroup is named SafePrime group and key is for DH,
// or Dlgroup is not named SafePrime group and key is for DSA
if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
( (pDlgroup->isSafePrimeGroup && (flags & SYMCRYPT_FLAG_DLKEY_DSA)) ||
(!(pDlgroup->isSafePrimeGroup) && (flags & SYMCRYPT_FLAG_DLKEY_DH)) ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Check that minimal validation flag only specified with no fips
if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) != 0 ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) != 0 )
{
fValidatePublicKeyOrder = 0;
}
//
// From symcrypt_internal.h we have:
@ -562,10 +596,13 @@ SymCryptDlkeySetValue(
// If the group does not have a Q assume that the imported key is modulo P as
// it wouldn't help us assume otherwise (the bitsize of the private key should be kept
// secret from SC attacks).
// If the private key has had some non-default value set for nBitsPriv then the caller
// has explicitly opted in to more stringent range checking.
//
pkDlkey->fPrivateModQ = ( (pDlgroup->fHasPrimeQ) &&
((cbPrivateKey < pDlgroup->cbPrimeQ) ||
((cbPrivateKey == pDlgroup->cbPrimeQ) && (pDlgroup->cbPrimeQ < pDlgroup->cbPrimeP))) );
((cbPrivateKey == pDlgroup->cbPrimeQ) && (pDlgroup->cbPrimeQ < pDlgroup->cbPrimeP)) ||
(pkDlkey->nBitsPriv != pDlgroup->nDefaultBitsPriv)) );
if ( pkDlkey->fPrivateModQ )
{
@ -596,17 +633,21 @@ SymCryptDlkeySetValue(
}
// Perform range validation on imported Private key.
if ( performRangeValidation )
if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
{
// Ensure that Q is specified in the Dlgroup
if ( !pDlgroup->fHasPrimeQ )
// Check if Private key is 0
if ( SymCryptIntIsEqualUint32( pkDlkey->piPrivateKey, 0 ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
}
// Check if Private key is 0
if ( SymCryptIntIsEqualUint32( pkDlkey->piPrivateKey, 0 ) )
// Continue range validation on imported Private key.
if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 )
{
// Ensure that Q is specified in the Dlgroup
if ( !pDlgroup->fHasPrimeQ )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
@ -643,14 +684,14 @@ SymCryptDlkeySetValue(
}
// Perform range validation on imported Public key.
if ( performRangeValidation )
if ( (flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION) == 0 )
{
// Perform Public key validation.
// Always perform range validation
// May also perform validation that Public key is in subgroup of order Q, depending on flags
scError = SymCryptDlkeyPerformPublicKeyValidation(
pkDlkey,
flags,
fValidatePublicKeyOrder,
pbScratch,
cbScratch );
if ( scError != SYMCRYPT_NO_ERROR )
@ -663,7 +704,7 @@ SymCryptDlkeySetValue(
// Calculating the public key if no key was provided
// or if needed for keypair regeneration validation
if ( (pbPublicKey==NULL) ||
( ( (flags & SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION) != 0 ) &&
( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
(pbPrivateKey!=NULL) && (pbPublicKey!=NULL) ) )
{
// Calculate the public key from the private key
@ -699,14 +740,14 @@ SymCryptDlkeySetValue(
goto cleanup;
}
}
else if ( performRangeValidation )
else if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
{
// Perform Public key validation on generated public key.
// Always perform range validation
// May also perform validation that Public key is in subgroup of order Q, depending on flags
scError = SymCryptDlkeyPerformPublicKeyValidation(
pkDlkey,
flags,
fValidatePublicKeyOrder,
pbScratch,
cbScratch );
if ( scError != SYMCRYPT_NO_ERROR )
@ -716,16 +757,30 @@ SymCryptDlkeySetValue(
}
}
if( ( flags & SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA ) != 0 )
pkDlkey->fAlgorithmInfo = flags; // We want to track all of the flags in the Dlkey
if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
{
SYMCRYPT_RUN_SELFTEST_ONCE( SymCryptDsaSelftest, SYMCRYPT_SELFTEST_DSA );
}
if( ( flags & SYMCRYPT_FLAG_DLKEY_SELFTEST_DH ) != 0 )
{
SYMCRYPT_RUN_SELFTEST_ONCE(
SymCryptDhSecretAgreementSelftest,
SYMCRYPT_SELFTEST_DH_SECRET_AGREEMENT );
if( ( flags & SYMCRYPT_FLAG_DLKEY_DSA ) != 0 )
{
// Ensure DSA algorithm selftest is run before first use of DSA algorithm
SYMCRYPT_RUN_SELFTEST_ONCE(
SymCryptDsaSelftest,
SYMCRYPT_SELFTEST_ALGORITHM_DSA );
if( pkDlkey->fHasPrivateKey )
{
// We do not need to run a DSA PCT on import, indicate that the test has been run
pkDlkey->fAlgorithmInfo |= SYMCRYPT_SELFTEST_KEY_DSA;
}
}
if( ( flags & SYMCRYPT_FLAG_DLKEY_DH ) != 0 )
{
SYMCRYPT_RUN_SELFTEST_ONCE(
SymCryptDhSecretAgreementSelftest,
SYMCRYPT_SELFTEST_ALGORITHM_DH );
}
}
cleanup:
@ -813,3 +868,27 @@ cleanup:
}
return scError;
}
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptDlkeyExtendKeyUsage(
_Inout_ PSYMCRYPT_DLKEY pkDlkey,
UINT32 flags )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
// Ensure caller has specified what algorithm(s) the key will be used with
UINT32 algorithmFlags = SYMCRYPT_FLAG_DLKEY_DSA | SYMCRYPT_FLAG_DLKEY_DH;
if ( ( ( flags & ~algorithmFlags ) != 0 ) ||
( ( flags & algorithmFlags ) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
pkDlkey->fAlgorithmInfo |= flags;
cleanup:
return scError;
}

Просмотреть файл

@ -102,6 +102,13 @@ SymCryptDsaSignEx(
UNREFERENCED_PARAMETER( flags );
// Make sure that the key may be used in DSA
if ( ((pKey->fAlgorithmInfo & SYMCRYPT_FLAG_DLKEY_DSA) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Make sure that the group and the key have all the
// information for dsa, i.e. prime q and private key
// modulo q, and we are not using a named DH safe-prime
@ -422,6 +429,13 @@ SymCryptDsaVerify(
UNREFERENCED_PARAMETER( flags );
// Make sure that the key may be used in DSA
if ( ((pKey->fAlgorithmInfo & SYMCRYPT_FLAG_DLKEY_DSA) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Make sure that the group has a prime q, and we are not using a named DH safe-prime group
if (!pDlgroup->fHasPrimeQ || pDlgroup->isSafePrimeGroup)
{

Просмотреть файл

@ -32,6 +32,14 @@ SymCryptEcDhSecretAgreement(
UINT32 cbQ = 0;
UINT32 cbX = 0;
// Make sure that the keys may be used in ECDH
if ( ((pkPrivate->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDH) == 0) ||
((pkPublic->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDH) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Make sure we only specify the correct flags
if (flags != 0)
{

Просмотреть файл

@ -180,6 +180,13 @@ SymCryptEcDsaSignEx(
UINT32 cbRs = 0;
UINT32 cbX = 0;
// Make sure that the key may be used in ECDSA
if ( ((pKey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Make sure that only the correct flags are set
if ( (flags & ~SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION) != 0 )
{
@ -389,6 +396,13 @@ SymCryptEcDsaSign(
_Out_writes_bytes_( cbSignature ) PBYTE pbSignature,
SIZE_T cbSignature )
{
// If the key was generated and a PCT has not yet been performed - perform PCT before first use
SYMCRYPT_RUN_KEYGEN_PCT(
SymCryptEcDsaSignVerifyTest,
pKey,
SYMCRYPT_SELFTEST_ALGORITHM_ECDSA,
SYMCRYPT_SELFTEST_KEY_ECDSA );
return SymCryptEcDsaSignEx( pKey, pbHashValue, cbHashValue, NULL, format, flags, pbSignature, cbSignature );
}
@ -436,6 +450,13 @@ SymCryptEcDsaVerify(
UINT32 cbRs = 0;
UINT32 cbX = 0;
// Make sure that the key may be used in ECDSA
if ( ((pKey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Make sure that only the correct flags are set
if ( (flags & ~SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION) != 0 )
{

Просмотреть файл

@ -79,6 +79,7 @@ SymCryptEckeyCreate(
pkObj = (PSYMCRYPT_ECKEY) pbBuffer;
pkObj->fAlgorithmInfo = 0;
pkObj->hasPrivateKey = FALSE;
pkObj->pCurve = pCurve;
@ -118,6 +119,9 @@ SymCryptEckeyCopy(
//
if( pkSrc != pkDst )
{
// Copy the fAlgorithmInfo flags
pkDst->fAlgorithmInfo = pkSrc->fAlgorithmInfo;
// Copy the hasPrivateKey flag
pkDst->hasPrivateKey = pkSrc->hasPrivateKey;
@ -160,6 +164,8 @@ SymCryptEckeyHasPrivateKey( _In_ PCSYMCRYPT_ECKEY pkEckey )
return pkEckey->hasPrivateKey;
}
#define SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION (0x1)
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptEckeyPerformPublicKeyValidation(
@ -200,7 +206,7 @@ SymCryptEckeyPerformPublicKeyValidation(
}
// Perform validation that Public key is in a subgroup of order GOrd.
if ( (flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION )
if ( (flags & SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION) != 0 )
{
if ( SymCryptIntIsEqualUint32( pCurve->H, 1 ) )
{
@ -273,27 +279,35 @@ SymCryptEckeySetValue(
UINT32 privateKeyDigits = SymCryptEcurveDigitsofScalarMultiplier(pCurve);
BOOLEAN performRangeValidation = FALSE;
UINT32 fValidatePublicKeyOrder = SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION;
SYMCRYPT_ASSERT( (cbPrivateKey==0) || (cbPrivateKey == SymCryptEcurveSizeofScalarMultiplier( pEckey->pCurve )) );
SYMCRYPT_ASSERT( (cbPublicKey==0) || (cbPublicKey == SymCryptEckeySizeofPublicKey( pEckey, ecPointFormat)) );
// Ensure only allowed flags are specified
UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION |
SYMCRYPT_FLAG_KEY_RANGE_VALIDATION |
SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION |
SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION |
SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA |
SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH;
// Ensure caller has specified what algorithm(s) the key will be used with
UINT32 algorithmFlags = SYMCRYPT_FLAG_ECKEY_ECDSA | SYMCRYPT_FLAG_ECKEY_ECDH;
// Make sure only allowed flags are specified
UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS | SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION | algorithmFlags;
if ( ( flags & ~allowedFlags ) != 0 )
if ( ( ( flags & ~allowedFlags ) != 0 ) ||
( ( flags & algorithmFlags ) == 0 ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
performRangeValidation = ((flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_RANGE_VALIDATION) ||
((flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION);
// Check that minimal validation flag only specified with no fips
if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) != 0 ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) != 0 )
{
fValidatePublicKeyOrder = 0;
}
if ( ( ( cbPrivateKey == 0 ) && ( cbPublicKey == 0 ) ) ||
( ( cbPrivateKey != 0 ) && ( cbPrivateKey != SymCryptEcurveSizeofScalarMultiplier( pEckey->pCurve ) ) ) ||
@ -344,11 +358,10 @@ SymCryptEckeySetValue(
}
// Validation steps
if ( !((flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION) )
if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
{
// Perform range validation on imported Private key if it is in canonical format
if ( performRangeValidation &&
(pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL) )
if ( pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL )
{
// Check if Private key is greater than or equal to GOrd
if ( !SymCryptIntIsLessThan( piTmpInteger, SymCryptIntFromModulus( pCurve->GOrd ) ) )
@ -415,7 +428,7 @@ SymCryptEckeySetValue(
pbScratchInternal,
cbScratchInternal );
if ( !((flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION) )
if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
{
// Check if Private key is 0 after dividing it by the subgroup order
// Other part of range validation
@ -450,11 +463,11 @@ SymCryptEckeySetValue(
}
// Perform Public key validation on imported Public key.
if ( !((flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION) )
if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
{
scError = SymCryptEckeyPerformPublicKeyValidation(
pEckey,
flags,
fValidatePublicKeyOrder,
pbScratch,
cbScratch );
if ( scError != SYMCRYPT_NO_ERROR )
@ -467,7 +480,7 @@ SymCryptEckeySetValue(
// Calculating the public key if no key was provided
// or if needed for keypair regeneration validation
if ( (pbPublicKey==NULL) ||
( ( (flags & SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION) != 0 ) &&
( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
(pbPrivateKey!=NULL) && (pbPublicKey!=NULL) ) )
{
// Calculate the public key from the private key
@ -510,12 +523,12 @@ SymCryptEckeySetValue(
goto cleanup;
}
}
else if ( !((flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION) )
else if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
{
// Perform Public key validation on generated Public key.
scError = SymCryptEckeyPerformPublicKeyValidation(
pEckey,
flags,
fValidatePublicKeyOrder,
pbScratch,
cbScratch );
if ( scError != SYMCRYPT_NO_ERROR )
@ -525,16 +538,30 @@ SymCryptEckeySetValue(
}
}
if ( ( flags & SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA ) != 0 )
{
SYMCRYPT_RUN_SELFTEST_ONCE( SymCryptEcDsaSelftest, SYMCRYPT_SELFTEST_ECDSA );
}
pEckey->fAlgorithmInfo = flags; // We want to track all of the flags in the Eckey
if ( ( flags & SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH ) != 0 )
if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 )
{
SYMCRYPT_RUN_SELFTEST_ONCE(
SymCryptEcDhSecretAgreementSelftest,
SYMCRYPT_SELFTEST_ECDH_SECRET_AGREEMENT);
if ( ( flags & SYMCRYPT_FLAG_ECKEY_ECDSA ) != 0 )
{
// Ensure ECDSA algorithm selftest is run before first use of ECDSA algorithm
SYMCRYPT_RUN_SELFTEST_ONCE(
SymCryptEcDsaSelftest,
SYMCRYPT_SELFTEST_ALGORITHM_ECDSA );
if( pEckey->hasPrivateKey )
{
// We do not need to run an ECDSA PCT on import, indicate that the test has been run
pEckey->fAlgorithmInfo |= SYMCRYPT_SELFTEST_KEY_ECDSA;
}
}
if ( ( flags & SYMCRYPT_FLAG_ECKEY_ECDH ) != 0 )
{
SYMCRYPT_RUN_SELFTEST_ONCE(
SymCryptEcDhSecretAgreementSelftest,
SYMCRYPT_SELFTEST_ALGORITHM_ECDH );
}
}
cleanup:
@ -628,6 +655,18 @@ SymCryptEckeyGetValue(
goto cleanup;
}
// If this keypair may be used in ECDSA, and does not have the no FIPS flag, run the PCT if
// it has not already been run
if ( ((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) != 0) &&
((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0) )
{
SYMCRYPT_RUN_KEYGEN_PCT(
SymCryptEcDsaSignVerifyTest,
pEckey,
SYMCRYPT_SELFTEST_ALGORITHM_ECDSA,
SYMCRYPT_SELFTEST_KEY_ECDSA );
}
// Copy the key into the temporary integer
SymCryptIntCopy( pEckey->piPrivateKey, piTmpInteger );
@ -711,20 +750,13 @@ SymCryptEckeySetRandom(
UINT32 highBitRestrictionPosition = pCurve->HighBitRestrictionPosition;
// Ensure only allowed flags are specified
UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION |
SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA |
SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH;
if ( ( flags & ~allowedFlags ) != 0)
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Ensure caller has specified what algorithm(s) the key will be used with
UINT32 algorithmFlags = SYMCRYPT_FLAG_ECKEY_ECDSA | SYMCRYPT_FLAG_ECKEY_ECDH;
// Make sure only allowed flags are specified
UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS | algorithmFlags;
// If any bits of SYMCRYPT_FLAG_KEY_VALIDATION_MASK are set, all bits of
// SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION must be set
if ( ( flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK ) != 0 &&
( flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK ) != SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION )
if ( ( ( flags & ~allowedFlags ) != 0 ) ||
( ( flags & algorithmFlags ) == 0 ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
@ -855,14 +887,13 @@ SymCryptEckeySetRandom(
}
// Perform range and public key order validation on generated Public key.
if ( (flags & SYMCRYPT_FLAG_KEY_VALIDATION_MASK) == SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION )
if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
{
// Perform Public key validation.
// Always perform range validation
// May also perform validation that Public key is in subgroup of order GOrd, depending on flags
// Always perform range validation and validation that Public key is in subgroup of order GOrd
scError = SymCryptEckeyPerformPublicKeyValidation(
pEckey,
flags,
SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION,
pbScratch,
cbScratch );
if ( scError != SYMCRYPT_NO_ERROR )
@ -871,21 +902,25 @@ SymCryptEckeySetRandom(
}
}
if( ( flags & SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA ) != 0 )
{
SYMCRYPT_RUN_KEYGEN_PCT( SymCryptEcDsaSignVerifyTest, pEckey, SYMCRYPT_SELFTEST_ECDSA );
}
if( ( flags & SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH ) != 0 )
{
SYMCRYPT_RUN_KEYGEN_PCT(
SymCryptEcDhSecretAgreementPairwiseConsistencyTest,
pEckey,
SYMCRYPT_SELFTEST_ECDH_SECRET_AGREEMENT );
}
pEckey->hasPrivateKey = TRUE;
pEckey->fAlgorithmInfo = flags; // We want to track all of the flags in the Eckey
if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
{
// We defer the ECDSA PCT to before first use of the Eckey in EcDsaSign, or first time
// private key is exported - whichever comes first.
if( ( flags & SYMCRYPT_FLAG_ECKEY_ECDH ) != 0 )
{
// No additional per-key tests to perform before first use.
// Just ensure we have run the algorithm selftest at least once.
SYMCRYPT_RUN_SELFTEST_ONCE(
SymCryptEcDhSecretAgreementSelftest,
SYMCRYPT_SELFTEST_ALGORITHM_ECDH );
}
}
cleanup:
if ( pbScratch != NULL )
@ -896,3 +931,27 @@ cleanup:
return scError;
}
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptEckeyExtendKeyUsage(
_Inout_ PSYMCRYPT_ECKEY pEckey,
UINT32 flags )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
// Ensure caller has specified what algorithm(s) the key will be used with
UINT32 algorithmFlags = SYMCRYPT_FLAG_ECKEY_ECDSA | SYMCRYPT_FLAG_ECKEY_ECDH;
if ( ( ( flags & ~algorithmFlags ) != 0 ) ||
( ( flags & algorithmFlags ) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
pEckey->fAlgorithmInfo |= flags;
cleanup:
return scError;
}

Просмотреть файл

@ -6,7 +6,8 @@
#include "precomp.h"
SYMCRYPT_FIPS_SELFTEST g_SymCryptFipsSelftestsPerformed = SYMCRYPT_SELFTEST_NONE;
// Takes values which are some bitwise OR combination of SYMCRYPT_SELFTEST_ALGORITHM values
UINT32 g_SymCryptFipsSelftestsPerformed = SYMCRYPT_SELFTEST_ALGORITHM_NONE;
//
// Convenience structs for selftest data
@ -479,101 +480,6 @@ const BYTE rgbSha256Hash[] =
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
};
VOID
SYMCRYPT_CALL
SymCryptDhSecretAgreementPairwiseConsistencyTest( PCSYMCRYPT_DLKEY pkKey1 )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
PSYMCRYPT_DLGROUP pKnownDlgroup = NULL;
PSYMCRYPT_DLKEY pkKey2 = NULL;
PBYTE pbSecret1 = NULL;
PBYTE pbSecret2 = NULL;
ULONG cbSecret = SymCryptDlkeySizeofPublicKey( pkKey1 );
pbSecret1 = SymCryptCallbackAlloc( cbSecret );
SYMCRYPT_FIPS_ASSERT( pbSecret1 != NULL );
pbSecret2 = SymCryptCallbackAlloc( cbSecret );
SYMCRYPT_FIPS_ASSERT( pbSecret2 != NULL );
pKnownDlgroup = SymCryptDlgroupAllocate(
SymCryptDlgroupDhSafePrimeParamsModp2048->nBitsOfP,
0 );
SYMCRYPT_FIPS_ASSERT( pKnownDlgroup != NULL );
scError = SymCryptDlgroupSetValue(
SymCryptDlgroupDhSafePrimeParamsModp2048->pcbPrimeP,
SymCryptDlgroupDhSafePrimeParamsModp2048->nBitsOfP / 8,
NULL, // pbPrimeQ
0, // cbPrimeQ
(PBYTE) &dhGenerator,
sizeof(dhGenerator),
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
NULL, // pHashAlgorithm
NULL, // pbSeed
0, // cbSeed
0, // genCounter
SYMCRYPT_DLGROUP_FIPS_NONE,
pKnownDlgroup);
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
if( SymCryptDlgroupIsSame( pKnownDlgroup, pkKey1->pDlgroup ) )
{
pkKey2 = SymCryptDlkeyAllocate( pKnownDlgroup );
SYMCRYPT_FIPS_ASSERT( pkKey2 != NULL );
scError = SymCryptDlkeySetValue(
dhKey2.private,
sizeof(dhKey2.private),
dhKey2.public,
sizeof(dhKey2.public),
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0, // flags
pkKey2 );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
}
else
{
pkKey2 = SymCryptDlkeyAllocate( pkKey1->pDlgroup );
SYMCRYPT_FIPS_ASSERT( pkKey2 != NULL );
scError = SymCryptDlkeyGenerate(0, pkKey2 );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
}
// Calculate secret using private key 1 and public key 2
scError = SymCryptDhSecretAgreement(
pkKey1,
pkKey2,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0, // flags
pbSecret1,
cbSecret );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
// Calculate secret using private key 2 and public key 1
scError = SymCryptDhSecretAgreement(
pkKey2,
pkKey1,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0, // flags
pbSecret2,
cbSecret );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
SYMCRYPT_FIPS_ASSERT( memcmp( pbSecret1, pbSecret2, cbSecret ) == 0 );
SymCryptWipe( pbSecret2, cbSecret );
SymCryptWipe( pbSecret1, cbSecret );
// No need to check for NULL values as allocation errors in this function are fatal
SymCryptCallbackFree( pbSecret2 );
SymCryptCallbackFree( pbSecret1 );
SymCryptDlkeyFree( pkKey2 );
SymCryptDlgroupFree( pKnownDlgroup );
}
VOID
SYMCRYPT_CALL
@ -617,7 +523,7 @@ SymCryptDhSecretAgreementSelftest()
dhKey1.public,
sizeof(dhKey1.public),
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0, // flags
SYMCRYPT_FLAG_DLKEY_DH | SYMCRYPT_FLAG_KEY_NO_FIPS, // flags
pkKey1 );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
@ -630,7 +536,7 @@ SymCryptDhSecretAgreementSelftest()
dhKey2.public,
sizeof(dhKey2.public),
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0, // flags
SYMCRYPT_FLAG_DLKEY_DH | SYMCRYPT_FLAG_KEY_NO_FIPS, // flags
pkKey2 );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
@ -653,200 +559,6 @@ SymCryptDhSecretAgreementSelftest()
SymCryptDlgroupFree( pDlgroup );
}
// For performance we always generate a known-good key for performing PCTs.
// To avoid excessive overhead, for short-weierstrass curves we generate the key,
// private = GOrd - 1, public = -G. This is guaranteed to fulfill the validity requirements:
// a) private key is in range [1, GOrd -1]
// b) public key is non-zero, and is on the curve
// c) public key has order GOrd
// d) private key * G == (GOrd - 1) * G == (GOrd * G) - (1 * G) == 0 - G == -G == public key
VOID
SYMCRYPT_CALL
SymCryptDeriveEcDhTestKeyFromShortWeierstrassCurve(
PCSYMCRYPT_ECURVE pCurve,
_Out_ PSYMCRYPT_ECKEY* pkKey )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
PSYMCRYPT_ECPOINT poNegativeG = NULL;
PSYMCRYPT_INT piGOrdMinus1 = NULL;
SIZE_T cbGOrdMinus1 = 0;
PBYTE pbGOrdMinus1 = NULL;
SIZE_T cbNegativeG = 0;
PBYTE pbNegativeG = NULL;
*pkKey = SymCryptEckeyAllocate( pCurve );
SYMCRYPT_FIPS_ASSERT( *pkKey != NULL );
SIZE_T cbScratch = SYMCRYPT_MAX(
SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ),
SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) );
PBYTE pbScratch = SymCryptCallbackAlloc( cbScratch );
SYMCRYPT_FIPS_ASSERT( pbScratch != NULL );
poNegativeG = SymCryptEcpointAllocate( pCurve );
SYMCRYPT_FIPS_ASSERT( poNegativeG != NULL );
piGOrdMinus1 = SymCryptIntAllocate( pCurve->GOrdDigits );
SYMCRYPT_FIPS_ASSERT( piGOrdMinus1 != NULL );
// Get our public key, (GOrd - 1)
{
SymCryptIntSubUint32(
SymCryptIntFromModulus( pCurve->GOrd ),
1,
piGOrdMinus1 );
cbGOrdMinus1 = SYMCRYPT_BYTES_FROM_BITS( SymCryptIntBitsizeOfValue( piGOrdMinus1 ) );
pbGOrdMinus1 = SymCryptCallbackAlloc( cbGOrdMinus1 );
SYMCRYPT_FIPS_ASSERT( pbGOrdMinus1 != NULL );
scError = SymCryptIntGetValue(
piGOrdMinus1,
pbGOrdMinus1,
cbGOrdMinus1,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
}
// Get our private key, -G, by negating the curve parameter G
{
SymCryptEcpointCopy( pCurve, pCurve->G, poNegativeG );
SymCryptEcpointNegate( pCurve, poNegativeG, 0xffffffff, pbScratch, cbScratch );
cbNegativeG = 2 * SymCryptEcurveSizeofFieldElement( pCurve );
pbNegativeG = SymCryptCallbackAlloc( cbNegativeG );
scError = SymCryptEcpointGetValue(
pCurve,
poNegativeG,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_ECPOINT_FORMAT_XY,
pbNegativeG,
cbNegativeG,
SYMCRYPT_FLAG_DATA_PUBLIC,
pbScratch,
cbScratch );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
}
scError = SymCryptEckeySetValue(
pbGOrdMinus1,
cbGOrdMinus1,
pbNegativeG,
cbNegativeG,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_ECPOINT_FORMAT_XY,
0, // flags
*pkKey );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
// No need to test for NULL because all errors are fatal
SymCryptWipe( pbNegativeG, cbNegativeG );
SymCryptCallbackFree( pbNegativeG );
SymCryptWipe( pbGOrdMinus1, cbGOrdMinus1 );
SymCryptCallbackFree( pbGOrdMinus1 );
SymCryptIntFree( piGOrdMinus1 );
SymCryptEcpointFree( pCurve, poNegativeG );
SymCryptWipe( pbScratch, cbScratch );
SymCryptCallbackFree( pbScratch );
}
VOID
SYMCRYPT_CALL
SymCryptEcDhSecretAgreementPairwiseConsistencyTest( PCSYMCRYPT_ECKEY pkKey1 )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
PSYMCRYPT_ECURVE pKnownCurve = NULL;
PSYMCRYPT_ECKEY pkKey2 = NULL;
PBYTE pbSecret1 = NULL;
PBYTE pbSecret2 = NULL;
ULONG cbSecret = SymCryptEcurveSizeofFieldElement( pkKey1->pCurve );
pbSecret1 = SymCryptCallbackAlloc( cbSecret );
SYMCRYPT_FIPS_ASSERT( pbSecret1 != NULL );
pbSecret2 = SymCryptCallbackAlloc( cbSecret );
SYMCRYPT_FIPS_ASSERT( pbSecret2 != NULL );
pKnownCurve = SymCryptEcurveAllocate( SymCryptEcurveParamsNistP256, 0 );
SYMCRYPT_FIPS_ASSERT( pKnownCurve != NULL );
if( SymCryptEcurveIsSame( pKnownCurve, pkKey1->pCurve ) )
{
// If this key uses the same curve as our hard-coded key, we can just import that
pkKey2 = SymCryptEckeyAllocate( pKnownCurve );
SYMCRYPT_FIPS_ASSERT( pkKey2 != NULL );
scError = SymCryptEckeySetValue(
eckey2.d,
sizeof(eckey2.d),
eckey2.Qxy,
sizeof(eckey2.Qxy),
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_ECPOINT_FORMAT_XY,
0, // flags
pkKey2);
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
}
else if( pkKey1->pCurve->type == SYMCRYPT_ECURVE_TYPE_SHORT_WEIERSTRASS &&
SymCryptIntIsEqualUint32(pkKey1->pCurve->H, 1) )
{
// For short Weierstrass curves with cofactor == 1, we can do efficient derivation
// of a test key from the curve parameters
SymCryptDeriveEcDhTestKeyFromShortWeierstrassCurve( pkKey1->pCurve, &pkKey2 );
}
else
{
// Otherwise, we have to generate a key
pkKey2 = SymCryptEckeyAllocate( pkKey1->pCurve );
SYMCRYPT_FIPS_ASSERT( pkKey2 != NULL );
scError = SymCryptEckeySetRandom(
SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION,
pkKey2 );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
}
// Calculate secret using private key 1 and public key 2
scError = SymCryptEcDhSecretAgreement(
pkKey1,
pkKey2,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
pbSecret1,
cbSecret);
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
// Calculate secret using private key 2 and public key 1
scError = SymCryptEcDhSecretAgreement(
pkKey2,
pkKey1,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
pbSecret2,
cbSecret);
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
SYMCRYPT_FIPS_ASSERT( memcmp( pbSecret1, pbSecret2, cbSecret ) == 0);
SymCryptWipe( pbSecret2, cbSecret );
SymCryptWipe( pbSecret1, cbSecret );
// No need to check for NULL values as allocation errors in this function are fatal
SymCryptCallbackFree( pbSecret2 );
SymCryptCallbackFree( pbSecret1 );
SymCryptEckeyFree( pkKey2 );
SymCryptEcurveFree( pKnownCurve );
}
VOID
SYMCRYPT_CALL
SymCryptEcDhSecretAgreementSelftest( )
@ -872,7 +584,7 @@ SymCryptEcDhSecretAgreementSelftest( )
sizeof(eckey1.Qxy),
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_ECPOINT_FORMAT_XY,
0, // flags
SYMCRYPT_FLAG_ECKEY_ECDH | SYMCRYPT_FLAG_KEY_NO_FIPS, // flags
pkKey1);
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
@ -886,7 +598,7 @@ SymCryptEcDhSecretAgreementSelftest( )
sizeof(eckey2.Qxy),
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_ECPOINT_FORMAT_XY,
0, // flags
SYMCRYPT_FLAG_ECKEY_ECDH | SYMCRYPT_FLAG_KEY_NO_FIPS, // flags
pkKey2);
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
@ -980,7 +692,7 @@ SymCryptDsaSelftest( )
dsaKey.public,
sizeof(dsaKey.public),
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0, // flags
SYMCRYPT_FLAG_DLKEY_DSA | SYMCRYPT_FLAG_KEY_NO_FIPS, // flags
pkDlkey );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
@ -1000,10 +712,12 @@ SymCryptEcDsaSignVerifyTest( PCSYMCRYPT_ECKEY pkEckey )
PBYTE pbSignature = SymCryptCallbackAlloc( cbSignature );
SYMCRYPT_FIPS_ASSERT( pbSignature != NULL );
scError = SymCryptEcDsaSign(
// Use SymCryptEcDsaSignEx to avoid infinite recursion in the PCT
scError = SymCryptEcDsaSignEx(
pkEckey,
rgbSha256Hash,
sizeof(rgbSha256Hash),
NULL,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
pbSignature,
@ -1046,7 +760,7 @@ SymCryptEcDsaSelftest( )
sizeof(eckey1.Qxy),
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_ECPOINT_FORMAT_XY,
0, // flags
SYMCRYPT_FLAG_ECKEY_ECDSA | SYMCRYPT_FLAG_KEY_NO_FIPS, // flags
pkEckey);
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
@ -1124,7 +838,7 @@ SymCryptRsaSelftest( )
cbPrimes,
sizeof(cbPrimes) / sizeof(cbPrimes[0]),
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_KEY_NO_FIPS,
pkRsakey );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );

Просмотреть файл

@ -521,6 +521,13 @@ SymCryptRsaRawEncrypt(
PBYTE pbScratch = NULL;
UINT32 cbScratch = 0;
// Make sure that the key may be used in Encrypt/Decrypt
if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
cbScratch = SymCryptRsaCoreEncScratchSpace( pkRsakey );
pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch );
@ -564,6 +571,13 @@ SymCryptRsaRawDecrypt(
PBYTE pbScratch = NULL;
UINT32 cbScratch = 0;
// Make sure that the key may be used in Encrypt/Decrypt
if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Make sure that the key has a private key
if (!pkRsakey->hasPrivateKey)
{
@ -634,6 +648,13 @@ SymCryptRsaPkcs1Encrypt(
UNREFERENCED_PARAMETER( flags );
// Make sure that the key may be used in Encrypt/Decrypt
if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
*pcbDst = cbTmp;
// Check if only *pcbDst is needed
@ -720,6 +741,13 @@ SymCryptRsaPkcs1Decrypt(
SIZE_T cbModulus = SymCryptRsakeySizeofModulus(pkRsakey);
SIZE_T cbTmp = SymCryptRoundUpPow2Sizet( cbModulus ); // tmp buffer needs to be a power of 2
// Make sure that the key may be used in Encrypt/Decrypt
if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Make sure that the key has a private key
if (!pkRsakey->hasPrivateKey)
{
@ -825,6 +853,13 @@ SymCryptRsaOaepEncrypt(
UNREFERENCED_PARAMETER( flags );
// Make sure that the key may be used in Encrypt/Decrypt
if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
*pcbDst = cbTmp;
// Check if only *pcbDst is needed
@ -923,6 +958,13 @@ SymCryptRsaOaepDecrypt(
UNREFERENCED_PARAMETER( flags );
// Make sure that the key may be used in Encrypt/Decrypt
if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
if (cbSrc > cbTmp)
{
scError = SYMCRYPT_INVALID_ARGUMENT;
@ -1054,6 +1096,13 @@ SymCryptRsaPkcs1Sign(
pbOID = pHashOIDs ? pHashOIDs->pbOID : NULL;
cbOID = pHashOIDs ? pHashOIDs->cbOID : 0;
// Make sure that the key may be used in Sign/Verify
if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_SIGN) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Make sure that the key has a private key
if (!pkRsakey->hasPrivateKey)
{
@ -1166,6 +1215,13 @@ SymCryptRsaPkcs1Verify(
PBYTE pbTmp = NULL;
SIZE_T cbTmp = SymCryptRsakeySizeofModulus(pkRsakey);
// Make sure that the key may be used in Sign/Verify
if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_SIGN) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
if (cbSignature > cbTmp)
{
scError = SYMCRYPT_INVALID_ARGUMENT;
@ -1258,6 +1314,13 @@ SymCryptRsaPssSign(
PBYTE pbTmp = NULL;
SIZE_T cbTmp = SymCryptRsakeySizeofModulus(pkRsakey);
// Make sure that the key may be used in Sign/Verify
if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_SIGN) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
if (cbHashValue > cbTmp)
{
scError = SYMCRYPT_INVALID_ARGUMENT;
@ -1386,6 +1449,13 @@ SymCryptRsaPssVerify(
PBYTE pbTmp = NULL;
SIZE_T cbTmp = SymCryptRsakeySizeofModulus(pkRsakey);
// Make sure that the key may be used in Sign/Verify
if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_SIGN) == 0 )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
if (cbHashValue > cbTmp)
{
scError = SYMCRYPT_INVALID_ARGUMENT;

Просмотреть файл

@ -209,6 +209,7 @@ SymCryptRsakeyCopy(
//
if( pkSrc != pkDst )
{
pkDst->fAlgorithmInfo = pkSrc->fAlgorithmInfo;
pkDst->cbTotalSize = pkSrc->cbTotalSize;
pkDst->hasPrivateKey = pkSrc->hasPrivateKey;
pkDst->nSetBitsOfModulus = pkSrc->nSetBitsOfModulus;
@ -521,10 +522,13 @@ SymCryptRsakeyGenerate(
const UINT64 defaultExponent = RSA_DEFAULT_PUBLIC_EXPONENT;
// Ensure caller has specified what algorithm(s) the key will be used with
UINT32 algorithmFlags = SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT;
// Ensure only allowed flags are specified
UINT32 allowedFlags = SYMCRYPT_FLAG_RSAKEY_SELFTEST;
UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS | algorithmFlags;
if ( ( flags & ~allowedFlags ) != 0 )
if ( ( ( flags & ~allowedFlags ) != 0 ) ||
( ( flags & algorithmFlags ) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
@ -702,16 +706,30 @@ SymCryptRsakeyGenerate(
// Calculate the rest of the fields
scError = SymCryptRsakeyCalculatePrivateFields( pkRsakey, pdTmp, piPhi, piAcc, pbFnScratch, cbFnScratch );
if (scError != SYMCRYPT_NO_ERROR )
if ( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}
pkRsakey->hasPrivateKey = TRUE;
if ( ( flags & SYMCRYPT_FLAG_RSAKEY_SELFTEST ) != 0 )
pkRsakey->fAlgorithmInfo = flags; // We want to track all of the flags in the Rsakey
if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 )
{
SYMCRYPT_RUN_KEYGEN_PCT( SymCryptRsaSignVerifyTest, pkRsakey, SYMCRYPT_SELFTEST_RSA );
// Ensure RSA algorithm selftest is run before first use of RSA algorithm
// Per FIPS 140-3 IG, this selftest cannot be a PCT
SYMCRYPT_RUN_SELFTEST_ONCE(
SymCryptRsaSelftest,
SYMCRYPT_SELFTEST_ALGORITHM_RSA);
// Run SignVerify PCT on generated keypair
// Our current understanding is that this PCT is sufficient for both RSA_SIGN and RSA_ENCRYPT
SYMCRYPT_RUN_KEYGEN_PCT(
SymCryptRsaSignVerifyTest,
pkRsakey,
0, /* Do not set any algorithm selftest as run with this PCT */
SYMCRYPT_SELFTEST_KEY_RSA_SIGN );
}
cleanup:
@ -760,15 +778,25 @@ SymCryptRsakeySetValue(
PBYTE pbFnScratch = NULL;
UINT32 cbFnScratch = 0;
// Ensure caller has specified what algorithm(s) the key will be used with
UINT32 algorithmFlags = SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT;
// Ensure only allowed flags are specified
UINT32 allowedFlags = SYMCRYPT_FLAG_RSAKEY_SELFTEST;
UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS | SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION | algorithmFlags;
if ( ( flags & ~allowedFlags ) != 0 )
if ( ( ( flags & ~allowedFlags ) != 0 ) ||
( ( flags & algorithmFlags ) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Check that minimal validation flag only specified with no fips
if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) != 0 ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
// Check if the arguments are correct
if ( (pbModulus==NULL) || (cbModulus==0) || // Modulus is needed
@ -928,9 +956,20 @@ SymCryptRsakeySetValue(
pkRsakey->hasPrivateKey = TRUE;
}
if ( ( flags & SYMCRYPT_FLAG_RSAKEY_SELFTEST ) != 0 )
pkRsakey->fAlgorithmInfo = flags; // We want to track all of the flags in the Rsakey
if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 )
{
SYMCRYPT_RUN_SELFTEST_ONCE( SymCryptRsaSelftest, SYMCRYPT_SELFTEST_RSA );
// Ensure RSA algorithm selftest is run before first use of RSA algorithm
SYMCRYPT_RUN_SELFTEST_ONCE(
SymCryptRsaSelftest,
SYMCRYPT_SELFTEST_ALGORITHM_RSA);
if( pkRsakey->hasPrivateKey )
{
// We do not need to run an RSA PCT on import, indicate that the test has been run
pkRsakey->fAlgorithmInfo |= SYMCRYPT_SELFTEST_KEY_RSA_SIGN;
}
}
cleanup:
@ -1108,3 +1147,27 @@ cleanup:
return scError;
}
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptRsakeyExtendKeyUsage(
_Inout_ PSYMCRYPT_RSAKEY pkRsakey,
UINT32 flags )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
// Ensure caller has specified what algorithm(s) the key will be used with
UINT32 algorithmFlags = SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT;
if ( ( ( flags & ~algorithmFlags ) != 0 ) ||
( ( flags & algorithmFlags ) == 0) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
pkRsakey->fAlgorithmInfo |= flags;
cleanup:
return scError;
}

Просмотреть файл

@ -3003,34 +3003,251 @@ SYMCRYPT_CALL
SymCryptFdefMontgomeryReduceMulx1024(
_In_ PCSYMCRYPT_MODULUS pmMod,
_Inout_ PUINT32 pSrc,
_Out_ PUINT32 pDst );
_Out_ PUINT32 pDst);
// Helper macro for checking for specific key validation flag using bits 4 and 5 in a flags variable
// Must be updated if SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION, SYMCRYPT_FLAG_KEY_RANGE_VALIDATION, or
// SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION are updated.
#define SYMCRYPT_FLAG_KEY_VALIDATION_MASK SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION
// Macro for executing a module selftest and setting the corresponding flag
#define SYMCRYPT_RUN_SELFTEST_ONCE(SelftestFunction, SelftestFlag) \
if( ( g_SymCryptFipsSelftestsPerformed & SelftestFlag ) == 0 ) \
//=====================================================
// Current state of FIPS tests for asymmetric keys
//=====================================================
// --------------------------------------------------------------------
// Key type | |
// & | Alg | Description
// Operation| |
// --------------------------------------------------------------------
// Dlkey | DH | Requires use of named safe-prime group (otherwise we cannot perform private
// Generate | | key range check, or public key order validation).
// | |
// | | From SP800-56Ar3:
// | | Check private key is in the range [1, min(2^nBitsPriv, q)-1]
// | | nBitsPriv is specified either using a default value or using
// | | SymCryptDlkeySetPrivateKeyLength, such that 2s <= nBitsPriv <= nBitsOfQ.
// | | (s is the maximum security strength for a named safe-prime group as
// | | specified in SP800 - 56arev3)
// | | Check public key is in the range [2, p-2]
// | | Check that (Public key)^q == 1 mod p
// | |
// | | FIPS 140-3 does not require a further PCT before first use of the key.
// |-----------------------------------------------------------
// | DSA | Requires use of a Dlgroup which has q, but is not a named safe-prime group.
// | |
// | | FIPS 186-4 and SP800-89 do not require DSA keypair owners to perform
// | | validation of keypairs they generate.
// | |
// | | FIPS 140-3 requires that a module generating a Dlkey keypair for use in DSA
// | | must perform a PCT on the keypair before first operational use in DSA.
// | | As the Dlgroups supported by FIPS are distinct for DH and DSA, we can perform
// | | this PCT on key generation without fear of adverse performance.
// --------------------------------------------------------------------
// Dlkey | DH | Requires use of named safe-prime group (otherwise we cannot perform private
// SetValue | | key range check, or public key order validation).
// | |
// | | From SP800-56Ar3:
// | | If importing a private key:
// | | Check private key is in the range [1, min(2^nBitsPriv, q)-1]
// | | nBitsPriv is specified either using a default value or using
// | | SymCryptDlkeySetPrivateKeyLength, such that 2s <= nBitsPriv <= nBitsOfQ.
// | | (s is the maximum security strength for a named safe-prime group as
// | | specified in SP800-56Arev3)
// | |
// | | If importing a public key:
// | | Check public key is in the range [2, p-2]
// | | Check that (Public key)^q == 1 mod p
// | |
// | | If importing both a private and public key, as above and also:
// | | Use the imported Private key to generate a Public key, and check the
// | | generated Public key is equal to the imported Public key.
// |-----------------------------------------------------------
// | DSA | Requires use of a Dlgroup which is not a named safe-prime group.
// | |
// | | FIPS 184-4 refers to SP800-89:
// | | If importing a public key:
// | | Check public key is in the range [2, p-2]
// | | Check that (Public key)^q == 1 mod p
// | | If importing a private and public key:
// | | Use the imported Private key to generate a Public key, and check the
// | | generated Public key is equal to the imported Public key.
// --------------------------------------------------------------------
// Eckey | ECDH | Requires use of a NIST prime Elliptic Curve (P224, P256, P384, or P521)
// SetRandom| |
// | | From SP800-56Ar3:
// | | Check private key is in range [1, GOrd-1]
// | | Check public key is nonzero, has coordinates in the underlying field, and is a
// | | point on the curve
// | | Check that GOrd*(Public key) == O
// | |
// | | FIPS 140-3 does not require a further PCT before first use of the key
// |----------------------------------------------------------
// | ECDSA | Requires use of a NIST prime Elliptic Curve (P224, P256, P384, or P521)
// | |
// | | FIPS 186-4 and SP800-89 do not require ECDSA keypair owners to perform
// | | validation of keypairs they generate.
// | |
// | | FIPS 140-3 requires that a module generating an Eckey keypair for use in ECDSA
// | | must perform a PCT on the keypair before first operational use in ECDSA.
// | | As the Elliptic curves used in ECDH and ECDSA are the same, an Eckey may be
// | | used for both ECDH and ECDSA. We defer the ECDSA PCT from the EckeySetRandom
// | | call to the first use of EcDsaSign, or the first export of the keypair.
// --------------------------------------------------------------------
// Eckey | ECDH | Requires use of a NIST prime Elliptic Curve (P224, P256, P384, or P521)
// SetValue | |
// | | From SP800-56Ar3:
// | | If importing a private key:
// | | Check private key is in range [1, GOrd-1]
// | |
// | | If importing a public key:
// | | Check public key is nonzero, has coordinates in the underlying field, and is
// | | a point on the curve
// | | Check that GOrd*(Public key) == O
// | |
// | | If importing a private and public key:
// | | Use the imported Private key to generate a Public key, and check the
// | | generated Public key is equal to the imported Public key.
// |----------------------------------------------------------
// | ECDSA | Requires use of a NIST prime Elliptic Curve (P224, P256, P384, or P521)
// | |
// | | FIPS 184-4 refers to SP800-89:
// | | If importing a public key:
// | | SP800-89 refers to ANS X9.62. Assume same tests required as SP800-56Ar3:
// | | Check public key is nonzero, has coordinates in the underlying field, and is
// | | a point on the curve
// | | Check that GOrd*(Public key) == O
// | |
// | | If importing a private and public key:
// | | Use the imported Private key to generate a Public key, and check the
// | | generated Public key is equal to the imported Public key.
// --------------------------------------------------------------------
// Rsakey | RSA | From FIPS 186-4 (SIGN) and SP800-56Br2 (ENCRYPT for key transport):
// Generate |ENCRYPT| Ensure p and q are in open range (2 ^ ((nBits - 1) / 2), 2 ^ (nBits / 2))
// | and | Ensure |p-q| > 2^((nBits/2)-100)
// | RSA | Ensure e is coprime with (p-1) and (q-1)
// | SIGN | Ensure d is in range [2 ^ (nBits/2) + 1, LCM(p-1,q-1) - 1]
// | | Ensure that d*e == 1 mod LCM(p-1,q-1)
// | |
// | | FIPS 140-3 requires that a module generating an Rsakey keypair for use in an
// | | RSA algorithm must perform a PCT on the keypair before first operational use.
// | |
// | | For ENCRYPT, SP800-56Br2 specifies the PCT to perform as part of key
// | | generation is:
// | | Check (m^e)^d == m mod n for some m in range [2, n-2]
// | |
// | | For SIGN, FIPS 186-4 refers to SP800-89, which does not clearly specify a
// | | PCT, but does specify that for an owner to have assurance of Private Key
// | | Possession they can sign a message with the private key and validate it with
// | | the public key to check they correspond to each other. Notably, this
// | | internally will verify (m^d)^e == m mod n for some m (along with testing
// | | additional padding logic)
// | |
// | | FIPS 140-2 explicitly says that only one PCT is required if a keypair may be
// | | used in either algorithm, with the module able to choose the PCT.
// | | FIPS 140-3 does not say anything specific about only requiring one PCT, but
// | | given that mathematically (m^e)^d == (m^ed) == (m^d)^e mod n, our
// | | current understanding is that the SIGN PCT works in lieu of the ENCRYPT PCT
// | |
// | | NOTE: FIPS 140-3 explicitly says that an RSA PCT cannot be used in lieu of an
// | | RSA algorithm selftest (CAST)
// --------------------------------------------------------------------
// Rsakey | RSA | If importing a keypair (primes and modulus):
// SetValue |ENCRYPT| SP800-56Br2 specifies:
// | | Check (m^e)^d mod n == m for some m in range [2, n-2]
// | | Check n == p*q
// | | Check p and q are in open range (2 ^ ((nBits - 1) / 2), 2 ^ (nBits / 2))
// | | Check |p-q| > 2^((nBits/2)-100)
// | | Check e is coprime with (p-1) and (q-1)
// | | Check p and q are probably prime
// | | Check d is in range [2 ^ (nBits/2) + 1, LCM(p-1,q-1) - 1]
// | | Check that d*e == 1 mod LCM(p-1,q-1)
// | |
// | | If importing a public key (only modulus):
// | | SP800-56Br2, refers to SP800-89 which details the following Partial Public Key
// | | Validation:
// | | Check n is odd
// | | Check n is not a prime or a power of a prime
// | | Check n has no factors smaller than 752
// |----------------------------------------------------------
// | RSA | FIPS 186-4 refers only to SP800-89 which has weaker tests for a keypair than
// | SIGN | SP800-56Br2 (i.e. success at SP800-56Br2 tests implies success in SP800-89)
// | | The current strategy will be to always perform the stronger tests.
// --------------------------------------------------------------------
// Macro for executing a module selftest and setting the corresponding algorithm selftest flag
#define SYMCRYPT_RUN_SELFTEST_ONCE(AlgorithmSelftestFunction, AlgorithmSelftestFlag) \
if( ( g_SymCryptFipsSelftestsPerformed & AlgorithmSelftestFlag ) == 0 ) \
{ \
SelftestFunction( ); \
AlgorithmSelftestFunction( ); \
\
SYMCRYPT_ATOMIC_OR32_PRE_RELAXED( &g_SymCryptFipsSelftestsPerformed, SelftestFlag );\
SYMCRYPT_ATOMIC_OR32_PRE_RELAXED( &g_SymCryptFipsSelftestsPerformed, AlgorithmSelftestFlag ); \
}
// Macro for executing a key-generation PCT and setting the corresponding flag
// Note that key generation PCTs must be run on every key generated, so the selftest function
// is run regardless of whether the flag is already set. However, the key generation PCT satisfies
// the module test requirement, so setting the flag here prevents subsequent tests from being run
// on key import.
#define SYMCRYPT_RUN_KEYGEN_PCT(SelftestFunction, Key, SelftestFlag) \
// Macro for executing a key-generation PCT, setting the corresponding algorithm selftest flag, and
// setting the per-key selftest flag.
// Note that key generation PCTs must be run on every key generated, so the KeySelftestFunction
// function is run regardless of whether the algorithm selftest flag is already set. Normally the
// per-key PCT satisfies the algorithm test requirement, so setting the AlgorithmSelftestFlag here
// prevents subsequent algorithm selftests from being run on key import. If the PCT does not satisfy
// an algorithm test requirment, the caller can specify 0, and no flag will be set.
#define SYMCRYPT_RUN_KEYGEN_PCT(KeySelftestFunction, Key, AlgorithmSelftestFlag, KeySelftestFlag) \
if( ( Key->fAlgorithmInfo & (KeySelftestFlag | SYMCRYPT_FLAG_KEY_NO_FIPS) ) == 0 ) \
{ \
SelftestFunction( Key ); \
KeySelftestFunction( Key ); \
\
SYMCRYPT_ATOMIC_OR32_PRE_RELAXED( &g_SymCryptFipsSelftestsPerformed, SelftestFlag );\
if( ( g_SymCryptFipsSelftestsPerformed & AlgorithmSelftestFlag ) != AlgorithmSelftestFlag ) \
{ \
SYMCRYPT_ATOMIC_OR32_PRE_RELAXED(&g_SymCryptFipsSelftestsPerformed, AlgorithmSelftestFlag); \
} \
\
SYMCRYPT_ATOMIC_OR32_PRE_RELAXED(&Key->fAlgorithmInfo, KeySelftestFlag); \
}
// Macro to check flag used in fAlgorithmInfo is non-zero and a power of 2
#define CHECK_ALGORITHM_INFO_FLAG_POW2( flag ) \
C_ASSERT( (flag != 0) && ((flag & (flag-1)) == 0) );
// Macro to check flags used together in fAlgorithmInfo are distinct
#define CHECK_ALGORITHM_INFO_FLAGS_DISTINCT( flag0, flag1, flag2, flag3, flag4 ) \
C_ASSERT( (flag0 < flag1) && (flag1 < flag2) && (flag2 < flag3) && (flag3 < flag4) );
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_SELFTEST_KEY_DSA);
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_SELFTEST_KEY_ECDSA);
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_SELFTEST_KEY_RSA_SIGN);
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_FLAG_KEY_NO_FIPS);
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION);
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_FLAG_DLKEY_DSA);
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_FLAG_DLKEY_DH);
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_FLAG_ECKEY_ECDSA);
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_FLAG_ECKEY_ECDH);
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_FLAG_RSAKEY_SIGN);
CHECK_ALGORITHM_INFO_FLAG_POW2(SYMCRYPT_FLAG_RSAKEY_ENCRYPT);
CHECK_ALGORITHM_INFO_FLAGS_DISTINCT(SYMCRYPT_SELFTEST_KEY_DSA, SYMCRYPT_FLAG_KEY_NO_FIPS, SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION, SYMCRYPT_FLAG_DLKEY_DSA, SYMCRYPT_FLAG_DLKEY_DH);
CHECK_ALGORITHM_INFO_FLAGS_DISTINCT(SYMCRYPT_SELFTEST_KEY_ECDSA, SYMCRYPT_FLAG_KEY_NO_FIPS, SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION, SYMCRYPT_FLAG_ECKEY_ECDSA, SYMCRYPT_FLAG_ECKEY_ECDH);
CHECK_ALGORITHM_INFO_FLAGS_DISTINCT(SYMCRYPT_SELFTEST_KEY_RSA_SIGN, SYMCRYPT_FLAG_KEY_NO_FIPS, SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION, SYMCRYPT_FLAG_RSAKEY_SIGN, SYMCRYPT_FLAG_RSAKEY_ENCRYPT);
VOID
SYMCRYPT_CALL
SymCryptRsaSignVerifyTest( PCSYMCRYPT_RSAKEY pkRsakey );
//
// FIPS PCT for RSA sign/verify. If the self-test fails, SymCryptFatal will be called to fastfail.
//
VOID
SYMCRYPT_CALL
SymCryptDsaSignVerifyTest( PCSYMCRYPT_DLKEY pkDlkey );
//
// FIPS PCT for DSA sign/verify. If the self-test fails, SymCryptFatal will be called to fastfail.
//
VOID
SYMCRYPT_CALL
SymCryptEcDsaSignVerifyTest( PCSYMCRYPT_ECKEY pkEckey );
//
// FIPS PCT for ECDSA sign/verify. If the self-test fails, SymCryptFatal will be called to fastfail.
//
typedef struct _SYMCRYPT_DLGROUP_DH_SAFEPRIME_PARAMS {
SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE eDhSafePrimeType;

Просмотреть файл

@ -30,7 +30,6 @@ VERSION_101.0 {
SymCryptAesExpandKeyEncryptOnly;
SymCryptAesKeyCopy;
SymCryptAesSelftest;
SymCryptBuildString;
SymCryptCbcDecrypt;
SymCryptCbcEncrypt;
SymCryptCbcMac;
@ -52,10 +51,6 @@ VERSION_101.0 {
SymCryptChaCha20Poly1305Selftest;
SymCryptChaCha20Selftest;
SymCryptChaCha20SetOffset;
SymCryptCpuFeaturesNeverPresent;
SymCryptCreateTrialDivisionContext;
SymCryptCrtGenerateInverses;
SymCryptCrtSolve;
SymCryptCtrMsb64;
SymCryptDesBlockCipher;
SymCryptDesDecrypt;
@ -69,14 +64,6 @@ VERSION_101.0 {
SymCryptDesxSelftest;
SymCryptDhSecretAgreement;
SymCryptDhSecretAgreementSelftest;
SymCryptDigitsFromBits;
SymCryptDivisorAllocate;
SymCryptDivisorCopy;
SymCryptDivisorCreate;
SymCryptDivisorDigitsizeOfObject;
SymCryptDivisorFree;
SymCryptDivisorFromModulus;
SymCryptDivisorWipe;
SymCryptDlgroupAllocate;
SymCryptDlgroupCopy;
SymCryptDlgroupCreate;
@ -108,7 +95,6 @@ VERSION_101.0 {
SymCryptEcDhSecretAgreementSelftest;
SymCryptEcDsaSelftest;
SymCryptEcDsaSign;
SymCryptEcDsaSignEx;
SymCryptEcDsaVerify;
SymCryptEcbDecrypt;
SymCryptEcbEncrypt;
@ -123,34 +109,10 @@ VERSION_101.0 {
SymCryptEckeySizeofPrivateKey;
SymCryptEckeySizeofPublicKey;
SymCryptEckeyWipe;
SymCryptEcpointAdd;
SymCryptEcpointAddDiffNonZero;
SymCryptEcpointAllocate;
SymCryptEcpointCopy;
SymCryptEcpointCreate;
SymCryptEcpointDouble;
SymCryptEcpointFree;
SymCryptEcpointGetValue;
SymCryptEcpointIsEqual;
SymCryptEcpointIsZero;
SymCryptEcpointMaskedCopy;
SymCryptEcpointMultiScalarMul;
SymCryptEcpointNegate;
SymCryptEcpointOnCurve;
SymCryptEcpointRetrieveHandle;
SymCryptEcpointScalarMul;
SymCryptEcpointSetDistinguishedPoint;
SymCryptEcpointSetRandom;
SymCryptEcpointSetValue;
SymCryptEcpointSetZero;
SymCryptEcpointWipe;
SymCryptEcurveAllocate;
SymCryptEcurveBitsizeofFieldModulus;
SymCryptEcurveBitsizeofGroupOrder;
SymCryptEcurveDigitsofFieldElement;
SymCryptEcurveDigitsofScalarMultiplier;
SymCryptEcurveFree;
SymCryptEcurveGroupOrder;
SymCryptEcurveHighBitRestrictionNumOfBits;
SymCryptEcurveHighBitRestrictionPosition;
SymCryptEcurveHighBitRestrictionValue;
@ -167,7 +129,6 @@ VERSION_101.0 {
SymCryptEcurvePrivateKeyDefaultFormat;
SymCryptEcurveSizeofFieldElement;
SymCryptEcurveSizeofScalarMultiplier;
SymCryptFreeTrialDivisionContext;
SymCryptGcmAuthPart;
SymCryptGcmDecrypt;
SymCryptGcmDecryptFinal;
@ -239,55 +200,6 @@ VERSION_101.0 {
SymCryptHmacSha512Result;
SymCryptHmacSha512Selftest;
SymCryptHmacSha512StateCopy;
SymCryptIntAddMixedSize;
SymCryptIntAddSameSize;
SymCryptIntAddUint32;
SymCryptIntAllocate;
SymCryptIntBitsizeOfObject;
SymCryptIntBitsizeOfValue;
SymCryptIntConditionalCopy;
SymCryptIntConditionalSwap;
SymCryptIntCopy;
SymCryptIntCopyMixedSize;
SymCryptIntCreate;
SymCryptIntDigitsizeOfObject;
SymCryptIntDivMod;
SymCryptIntDivPow2;
SymCryptIntExtendedGcd;
SymCryptIntFindSmallDivisor;
SymCryptIntFree;
SymCryptIntFromDivisor;
SymCryptIntFromModulus;
SymCryptIntGenerateRandomPrime;
SymCryptIntGetBit;
SymCryptIntGetBits;
SymCryptIntGetValue;
SymCryptIntGetValueLsbits32;
SymCryptIntGetValueLsbits64;
SymCryptIntIsEqual;
SymCryptIntIsEqualUint32;
SymCryptIntIsLessThan;
SymCryptIntMaskedCopy;
SymCryptIntMillerRabinPrimalityTest;
SymCryptIntModPow2;
SymCryptIntMulMixedSize;
SymCryptIntMulPow2;
SymCryptIntMulSameSize;
SymCryptIntMulUint32;
SymCryptIntNeg;
SymCryptIntSetBits;
SymCryptIntSetValue;
SymCryptIntSetValueUint32;
SymCryptIntSetValueUint64;
SymCryptIntShr1;
SymCryptIntSquare;
SymCryptIntSubMixedSize;
SymCryptIntSubSameSize;
SymCryptIntSubUint32;
SymCryptIntToDivisor;
SymCryptIntToModElement;
SymCryptIntToModulus;
SymCryptIntWipe;
SymCryptLoadLsbFirstUint32;
SymCryptLoadLsbFirstUint64;
SymCryptLoadMsbFirstUint32;
@ -301,11 +213,6 @@ VERSION_101.0 {
SymCryptMarvin32SeedCopy;
SymCryptMarvin32Selftest;
SymCryptMarvin32StateCopy;
SymCryptMask32EqU32;
SymCryptMask32IsNonzeroU31;
SymCryptMask32IsZeroU31;
SymCryptMask32LtU31;
SymCryptMask32NeqU31;
SymCryptMd2;
SymCryptMd2Algorithm;
SymCryptMd2Append;
@ -334,38 +241,7 @@ VERSION_101.0 {
SymCryptMd5StateCopy;
SymCryptMd5StateExport;
SymCryptMd5StateImport;
SymCryptModAdd;
SymCryptModDivPow2;
SymCryptModElementAllocate;
SymCryptModElementConditionalSwap;
SymCryptModElementCopy;
SymCryptModElementCreate;
SymCryptModElementFree;
SymCryptModElementGetValue;
SymCryptModElementIsEqual;
SymCryptModElementIsZero;
SymCryptModElementMaskedCopy;
SymCryptModElementSetValue;
SymCryptModElementSetValueNegUint32;
SymCryptModElementSetValueUint32;
SymCryptModElementToInt;
SymCryptModElementWipe;
SymCryptModExp;
SymCryptModInv;
SymCryptModMul;
SymCryptModMultiExp;
SymCryptModNeg;
SymCryptModSetRandom;
SymCryptModSquare;
SymCryptModSub;
SymCryptModuleInit;
SymCryptModulusAllocate;
SymCryptModulusBitsizeOfObject;
SymCryptModulusCopy;
SymCryptModulusCreate;
SymCryptModulusDigitsizeOfObject;
SymCryptModulusFree;
SymCryptModulusWipe;
SymCryptParallelSha256Init;
SymCryptParallelSha256Process;
SymCryptParallelSha256Selftest;
@ -413,7 +289,6 @@ VERSION_101.0 {
SymCryptRngAesReseed;
SymCryptRngAesReseedSelftest;
SymCryptRngAesUninstantiate;
SymCryptRoundUpPow2Sizet;
SymCryptRsaOaepDecrypt;
SymCryptRsaOaepEncrypt;
SymCryptRsaSelftest;
@ -439,13 +314,6 @@ VERSION_101.0 {
SymCryptRsakeySizeofPrime;
SymCryptRsakeySizeofPublicExponent;
SymCryptRsakeyWipe;
SymCryptScsCopy;
SymCryptScsRotateBuffer;
SymCryptScsTableInit;
SymCryptScsTableLoad;
SymCryptScsTableSetBuffer;
SymCryptScsTableStore;
SymCryptScsTableWipe;
SymCryptSha1;
SymCryptSha1Algorithm;
SymCryptSha1Append;
@ -486,14 +354,9 @@ VERSION_101.0 {
SymCryptSha512StateCopy;
SymCryptSha512StateExport;
SymCryptSha512StateImport;
SymCryptSizeofDivisorFromDigits;
SymCryptSizeofDlgroupFromBitsizes;
SymCryptSizeofDlkeyFromDlgroup;
SymCryptSizeofEckeyFromCurve;
SymCryptSizeofEcpointFromCurve;
SymCryptSizeofIntFromDigits;
SymCryptSizeofModElementFromModulus;
SymCryptSizeofModulusFromDigits;
SymCryptSizeofRsakeyFromParams;
SymCryptSp800_108;
SymCryptSp800_108Derive;
@ -519,7 +382,6 @@ VERSION_101.0 {
SymCryptUint32Bytesize;
SymCryptUint64Bitsize;
SymCryptUint64Bytesize;
SymCryptUint64Gcd;
SymCryptWipe;
SymCryptWipeKnownSize;
SymCryptXtsAesDecrypt;
@ -532,14 +394,17 @@ VERSION_101.0 {
VERSION_101.2
{
global:
SymCryptDhSecretAgreementPairwiseConsistencyTest;
SymCryptDsaSignVerifyTest;
SymCryptEcDhSecretAgreementPairwiseConsistencyTest;
SymCryptEcDsaSignVerifyTest;
SymCryptRsaSignVerifyTest;
SymCryptSessionDestroy;
SymCryptSessionGcmDecrypt;
SymCryptSessionGcmEncrypt;
SymCryptSessionReceiverInit;
SymCryptSessionSenderInit;
} VERSION_101.0;
} VERSION_101.0;
VERSION_102.0
{
global:
SymCryptDlkeyExtendKeyUsage;
SymCryptEckeyExtendKeyUsage;
SymCryptRsakeyExtendKeyUsage;
SymCryptRsakeyCreate;
} VERSION_101.2;

Просмотреть файл

@ -59,7 +59,7 @@ VOID __attribute__((constructor)) SymCryptModuleMain()
SymCryptPbkdf2_HmacSha1SelfTest();
g_SymCryptFipsSelftestsPerformed |= SYMCRYPT_SELFTEST_STARTUP;
g_SymCryptFipsSelftestsPerformed |= SYMCRYPT_SELFTEST_ALGORITHM_STARTUP;
}
}

Просмотреть файл

@ -42,7 +42,7 @@ main( int argc, _In_reads_( argc ) char * argv[] )
}
else
{
SYMCRYPT_FIPS_ASSERT( (g_SymCryptFipsSelftestsPerformed & SYMCRYPT_SELFTEST_STARTUP) != 0 );
SYMCRYPT_FIPS_ASSERT( (g_SymCryptFipsSelftestsPerformed & SYMCRYPT_SELFTEST_ALGORITHM_STARTUP) != 0 );
SymCryptDhSecretAgreementSelftest();
SymCryptEcDhSecretAgreementSelftest();

Просмотреть файл

@ -191,7 +191,7 @@ testRsaGenerateOneKey( UINT32 iSize, UINT32 iImpl )
pubExp |= (UINT64)1 << (nPubBits - 1);
pubExp |= 1;
scError = SymCryptRsakeyGenerate( pkSymCryptKey, &pubExp, 1, 0 );
scError = SymCryptRsakeyGenerate( pkSymCryptKey, &pubExp, 1, SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
pRes = (PBYTE) pkSymCryptKey;
@ -630,7 +630,7 @@ testRsaImportOneKey(
pcbPrimes,
2,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT,
pkSymCryptKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
@ -1013,7 +1013,7 @@ testRsaPkcs1Errors()
pKey = SymCryptRsakeyAllocate( &params, 0 );
CHECK( pKey != 0, "?" );
scError = SymCryptRsakeyGenerate( pKey, 0, 0, 0 );
scError = SymCryptRsakeyGenerate( pKey, 0, 0, SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT );
CHECK( scError == SYMCRYPT_NO_ERROR, "Error generating pkcs1 key" );
for( i=0; i<sizeof( paddedData ); i++ )

Просмотреть файл

@ -1580,7 +1580,7 @@ addRsaKeyGenPerfSymCrypt( PrintTable &table )
UINT64 start = GET_PERF_CLOCK();
PSYMCRYPT_RSAKEY pScKey = SymCryptRsakeyAllocate( &scRsaParams, 0 );
SymCryptRsakeyGenerate( pScKey, NULL, 0, 0 );
SymCryptRsakeyGenerate( pScKey, NULL, 0, SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT );
SymCryptRsakeyFree( pScKey );
UINT64 stop = GET_PERF_CLOCK();

Просмотреть файл

@ -3942,7 +3942,8 @@ SetupRsaKey( PBYTE buf1, SIZE_T keySize )
pkRsakey = SymCryptRsakeyAllocate( &rsaParams, 0 );
CHECK( pkRsakey != NULL, "?" );
scError = SymCryptRsakeyGenerate( pkRsakey, NULL, 0, 0 ); // Use default exponent
// Use default exponent
scError = SymCryptRsakeyGenerate(pkRsakey, NULL, 0, SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT);
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
g_precomputedRsaKeys[i].pkRsakey = pkRsakey;
@ -4142,7 +4143,7 @@ RsaSignImp<ImpSc, AlgRsaSignPkcs1>::setKey( PCRSAKEY_TESTBLOB pcKeyBlob )
&pcKeyBlob->u64PubExp, 1,
ppPrime, cbPrime, 2,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
SYMCRYPT_FLAG_RSAKEY_SIGN,
state.pKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
@ -4371,7 +4372,7 @@ RsaSignImp<ImpSc, AlgRsaSignPss>::setKey( PCRSAKEY_TESTBLOB pcKeyBlob )
&pcKeyBlob->u64PubExp, 1,
ppPrime, cbPrime, 2,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
SYMCRYPT_FLAG_RSAKEY_SIGN,
state.pKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
@ -4590,7 +4591,7 @@ RsaEncImp<ImpSc, AlgRsaEncRaw>::setKey( PCRSAKEY_TESTBLOB pcKeyBlob )
&pcKeyBlob->u64PubExp, 1,
ppPrime, cbPrime, 2,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
SYMCRYPT_FLAG_RSAKEY_ENCRYPT,
state.pKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
@ -4801,7 +4802,7 @@ RsaEncImp<ImpSc, AlgRsaEncPkcs1>::setKey( PCRSAKEY_TESTBLOB pcKeyBlob )
&pcKeyBlob->u64PubExp, 1,
ppPrime, cbPrime, 2,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
SYMCRYPT_FLAG_RSAKEY_ENCRYPT,
state.pKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
@ -5030,7 +5031,7 @@ RsaEncImp<ImpSc, AlgRsaEncOaep>::setKey( PCRSAKEY_TESTBLOB pcKeyBlob )
&pcKeyBlob->u64PubExp, 1,
ppPrime, cbPrime, 2,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
SYMCRYPT_FLAG_RSAKEY_ENCRYPT,
state.pKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
@ -5477,12 +5478,14 @@ SetupSymCryptDsaAndDh( PBYTE buf1, PBYTE buf2, PBYTE buf3 )
UINT32 signatureSize = 0;
PUINT32 puiSignatureSize = NULL;
UINT32 generateFlags = SYMCRYPT_FLAG_DLKEY_DH | SYMCRYPT_FLAG_DLKEY_DSA | SYMCRYPT_FLAG_KEY_NO_FIPS;
pPtrs[0] = SymCryptDlkeyCreate( buf2 + buff2Offset, dlkeysize, pDlgroup );
scError = SymCryptDlkeyGenerate( 0, pPtrs[0] );
scError = SymCryptDlkeyGenerate( generateFlags, pPtrs[0] );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
pPtrs[1] = SymCryptDlkeyCreate( buf2 + buff2Offset + dlkeysize, dlkeysize, pDlgroup );
scError = SymCryptDlkeyGenerate( 0, pPtrs[1] );
scError = SymCryptDlkeyGenerate( generateFlags, pPtrs[1] );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
signatureSize = 2*SymCryptDlkeySizeofPrivateKey( pPtrs[0] );
@ -5517,7 +5520,7 @@ SetupSymCryptDsaAndDh( PBYTE buf1, PBYTE buf2, PBYTE buf3 )
// Verify the signature to make sure everything is ok
scError = SymCryptDsaVerify(
((PSYMCRYPT_DLKEY *) buf2)[0],
buf2, // Sign the keys' buffer
buf2, // Verify the keys' buffer
SymCryptDlkeySizeofPrivateKey( ((PSYMCRYPT_DLKEY *)buf2)[0] ),
buf3 + sizeof(UINT32),
*((PUINT32) buf3),
@ -5636,11 +5639,11 @@ DlImp<ImpSc, AlgDsaVerify>::~DlImp()
//============================
PSYMCRYPT_DLKEY
dlkeyObjectFromTestBlob( PCSYMCRYPT_DLGROUP pGroup, PCDLKEY_TESTBLOB pBlob, BOOL setPrivate = TRUE )
dlkeyObjectFromTestBlob( PCSYMCRYPT_DLGROUP pGroup, PCDLKEY_TESTBLOB pBlob, UINT32 algFlags, BOOL setPrivate = TRUE )
{
PSYMCRYPT_DLKEY pRes;
SYMCRYPT_ERROR scError;
UINT32 flags = 0;
UINT32 flags = algFlags;
PCBYTE pbPrivKey = NULL;
SIZE_T cbPrivKey = 0;
PCBYTE pbPubKey = NULL;
@ -5654,32 +5657,21 @@ dlkeyObjectFromTestBlob( PCSYMCRYPT_DLGROUP pGroup, PCDLKEY_TESTBLOB pBlob, BOOL
BYTE randByte = g_rng.byte();
if(randByte & 1)
if (!pGroup->fHasPrimeQ ||
pBlob->fPrivateModP ||
((algFlags == SYMCRYPT_FLAG_DLKEY_DH) && (!pGroup->isSafePrimeGroup)) ||
((algFlags == SYMCRYPT_FLAG_DLKEY_DSA) && (pGroup->isSafePrimeGroup)) ||
(randByte & 0x1))
{
flags |= SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION;
}
// If Dlgroup has a set Q and Dlkey wasn't explicitly generated with private key mod P
if ( pGroup->fHasPrimeQ && !pBlob->fPrivateModP )
{
switch((randByte >> 1) & 3)
flags |= SYMCRYPT_FLAG_KEY_NO_FIPS;
if (randByte & 0x2)
{
case 0:
break;
case 1:
flags |= SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION;
break;
case 2:
flags |= SYMCRYPT_FLAG_KEY_RANGE_VALIDATION;
break;
case 3:
default:
flags |= SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION;
break;
flags |= SYMCRYPT_FLAG_DLKEY_DSA;
flags |= SYMCRYPT_FLAG_DLKEY_DH;
}
}
if (setPrivate || (randByte & 0x8))
if (setPrivate || (randByte & 0x4))
{
pbPrivKey = &pBlob->abPrivKey[0];
cbPrivKey = pBlob->cbPrivKey;
@ -5692,6 +5684,11 @@ dlkeyObjectFromTestBlob( PCSYMCRYPT_DLGROUP pGroup, PCDLKEY_TESTBLOB pBlob, BOOL
}
}
if (((flags & SYMCRYPT_FLAG_KEY_NO_FIPS) != 0) && (randByte & 0x8))
{
flags |= SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION;
}
if (!setPrivate)
{
pbPubKey = &pBlob->abPubKey[0];
@ -5725,12 +5722,14 @@ algImpKeyPerfFunction<ImpSc, AlgDh>( PBYTE buf1, PBYTE buf2, PBYTE buf3, SIZE_T
PSYMCRYPT_DLKEY pKey1 = SymCryptDlkeyCreate( buf2 + 64, PERF_BUFFER_SIZE/4, pGroup );
PSYMCRYPT_DLKEY pKey2 = SymCryptDlkeyCreate( buf2 + 64 + PERF_BUFFER_SIZE/4, PERF_BUFFER_SIZE/4, pGroup );
UINT32 generateFlags = SYMCRYPT_FLAG_DLKEY_DH | (pGroup->isSafePrimeGroup ? 0 : SYMCRYPT_FLAG_KEY_NO_FIPS);
CHECK( pKey1 != NULL && pKey2 != NULL, "Failed to create keys" );
scError = SymCryptDlkeyGenerate( 0, pKey1 );
scError = SymCryptDlkeyGenerate( generateFlags, pKey1 );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
scError = SymCryptDlkeyGenerate( 0, pKey2 );
scError = SymCryptDlkeyGenerate( generateFlags, pKey2 );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
((PSYMCRYPT_DLKEY *) buf2)[0] = pKey1;
@ -5758,10 +5757,12 @@ algImpDataPerfFunction< ImpSc, AlgDh>( PBYTE buf1, PBYTE buf2, PBYTE buf3, SIZE_
PSYMCRYPT_DLGROUP pGroup = *(PSYMCRYPT_DLGROUP *) buf1;
UINT32 generateFlags = SYMCRYPT_FLAG_DLKEY_DH | (pGroup->isSafePrimeGroup ? 0 : SYMCRYPT_FLAG_KEY_NO_FIPS);
PSYMCRYPT_DLKEY pKey = SymCryptDlkeyCreate( buf3, (1 << 16), pGroup );
CHECK( pKey != NULL, "?" );
scError = SymCryptDlkeyGenerate( 0, pKey );
scError = SymCryptDlkeyGenerate( generateFlags, pKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
scError = SymCryptDlkeyGetValue( pKey, NULL, 0, buf3 + (1 << 16), pGroup->cbPrimeP, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, 0 );
@ -5828,7 +5829,7 @@ DhImp<ImpSc, AlgDh>::setKey( _In_ PCDLKEY_TESTBLOB pcKeyBlob )
if( pcKeyBlob != NULL )
{
state.pGroup = dlgroupObjectFromTestBlob( pcKeyBlob->pGroup );
state.pKey = dlkeyObjectFromTestBlob( state.pGroup, pcKeyBlob );
state.pKey = dlkeyObjectFromTestBlob( state.pGroup, pcKeyBlob, SYMCRYPT_FLAG_DLKEY_DH );
CHECK( state.pGroup != NULL && state.pKey != NULL, "?" );
}
@ -5846,7 +5847,7 @@ DhImp<ImpSc, AlgDh>::sharedSecret(
PSYMCRYPT_DLKEY pKey2;
SYMCRYPT_ERROR scError;
pKey2 = dlkeyObjectFromTestBlob( state.pGroup, pcPubkey, /*setPrivate=*/ FALSE );
pKey2 = dlkeyObjectFromTestBlob( state.pGroup, pcPubkey, SYMCRYPT_FLAG_DLKEY_DH, /*setPrivate=*/ FALSE );
CHECK( pKey2 != NULL, "?")
scError = SymCryptDhSecretAgreement( state.pKey,
@ -5878,7 +5879,7 @@ algImpKeyPerfFunction<ImpSc, AlgDsa>( PBYTE buf1, PBYTE buf2, PBYTE buf3, SIZE_T
CHECK( pKey != NULL, "Failed to create key" );
scError = SymCryptDlkeyGenerate( 0, pKey );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DSA, pKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
((PSYMCRYPT_DLKEY *) buf2)[0] = pKey;
@ -5977,7 +5978,7 @@ DsaImp<ImpSc, AlgDsa>::setKey( _In_ PCDLKEY_TESTBLOB pcKeyBlob )
if( pcKeyBlob != NULL )
{
state.pGroup = dlgroupObjectFromTestBlob( pcKeyBlob->pGroup );
state.pKey = dlkeyObjectFromTestBlob( state.pGroup, pcKeyBlob );
state.pKey = dlkeyObjectFromTestBlob( state.pGroup, pcKeyBlob, SYMCRYPT_FLAG_DLKEY_DSA );
CHECK( state.pGroup != NULL && state.pKey != NULL, "?" );
}
@ -6143,7 +6144,7 @@ SetupSymCryptEcdsaAndEcdh( PBYTE buf1, PBYTE buf2, PBYTE buf3 )
PSYMCRYPT_ECKEY * pPtrs = ((PSYMCRYPT_ECKEY *) buf2);
pPtrs[0] = SymCryptEckeyCreate( buf2 + 32, eckeySize, pCurve );
scError = SymCryptEckeySetRandom( 0, pPtrs[0] );
scError = SymCryptEckeySetRandom( SYMCRYPT_FLAG_ECKEY_ECDSA | SYMCRYPT_FLAG_ECKEY_ECDH, pPtrs[0] );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
pPtrs[1] = (PSYMCRYPT_ECKEY) ((PBYTE)buf2 + 32 + eckeySize); // This will hold the hash of the message
@ -6168,19 +6169,19 @@ SetupSymCryptEcdsaAndEcdh( PBYTE buf1, PBYTE buf2, PBYTE buf3 )
SymCryptEcurveSizeofFieldElement( *(PSYMCRYPT_ECURVE *) buf1 ));
CHECK( scError == SYMCRYPT_NO_ERROR, "SymCryptEcDhSecretAgreement failed" );
// Same for ECDSA
scError = SymCryptEcDsaSign(
pPtrs[0],
(PBYTE) pPtrs[1],
SYMCRYPT_SHA512_RESULT_SIZE,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
buf3 + sizeof(UINT32),
signatureSize );
CHECK( scError == SYMCRYPT_NO_ERROR, "SymCryptEcDsaSign failed" );
if (pCurve->type != SYMCRYPT_ECURVE_TYPE_MONTGOMERY)
{
// Same for ECDSA
scError = SymCryptEcDsaSign(
pPtrs[0],
(PBYTE) pPtrs[1],
SYMCRYPT_SHA512_RESULT_SIZE,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
0,
buf3 + sizeof(UINT32),
signatureSize );
CHECK( scError == SYMCRYPT_NO_ERROR, "SymCryptEcDsaSign failed" );
// Verify the signature to make sure everything is ok
scError = SymCryptEcDsaVerify(
((PSYMCRYPT_ECKEY *) buf2)[0],

Просмотреть файл

@ -490,7 +490,7 @@ VOID testDlSimple()
pkDlkey = SymCryptDlkeyAllocate( pDlgroup );
CHECK( pkDlkey!=NULL, "?");
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_SELFTEST_DH, pkDlkey );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DSA, pkDlkey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
//printDlKey( pkDlkey );
@ -598,7 +598,7 @@ VOID testDlSimple()
//printDlGroup( pDlgroup );
// Create a new key and make sure it is mod P
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_SELFTEST_DH, pkDlkey );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DSA | SYMCRYPT_FLAG_KEY_NO_FIPS, pkDlkey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
CHECK(SymCryptDlkeySizeofPrivateKey(pkDlkey) == cbExpP, "?")
@ -696,8 +696,10 @@ VOID testDlSimple()
//printDlGroup( pDlgroup );
// Create a new key and use the mod P flag
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_GEN_MODP | SYMCRYPT_FLAG_DLKEY_SELFTEST_DH, pkDlkey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
scError = SymCryptDlkeyGenerate(
SYMCRYPT_FLAG_DLKEY_DSA | SYMCRYPT_FLAG_DLKEY_GEN_MODP | SYMCRYPT_FLAG_KEY_NO_FIPS,
pkDlkey);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
CHECK(SymCryptDlkeySizeofPrivateKey(pkDlkey) == cbExpP, "?")
@ -811,10 +813,10 @@ createKatFileSingleDh( FILE * f, PCDLGROUP_TESTBLOB pBlob )
PSYMCRYPT_DLKEY pKey1 = SymCryptDlkeyAllocate( pGroup );
PSYMCRYPT_DLKEY pKey2 = SymCryptDlkeyAllocate( pGroup );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_SELFTEST_DH, pKey1 );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DH, pKey1 );
CHECK( scError == SYMCRYPT_NO_ERROR, "Error generating DH key" );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_SELFTEST_DH, pKey2 );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DH, pKey2 );
CHECK( scError == SYMCRYPT_NO_ERROR, "Error generating DH key" );
UINT32 cbPrivKey1 = SymCryptDlkeySizeofPrivateKey( pKey1 );
@ -1009,15 +1011,11 @@ testDhtestGroups( DhImplementation * pDh, INT64 line )
}
}
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_SELFTEST_DH, pKey1 );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DH | SYMCRYPT_FLAG_KEY_NO_FIPS, pKey1 );
CHECK( scError == SYMCRYPT_NO_ERROR, "Error generating key" );
scError = SymCryptDlkeyGenerate(
SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION | SYMCRYPT_FLAG_DLKEY_SELFTEST_DH,
pKey1 );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DH | (pGroup->isSafePrimeGroup ? 0 : SYMCRYPT_FLAG_KEY_NO_FIPS), pKey1 );
CHECK( scError == SYMCRYPT_NO_ERROR, "Error generating key" );
scError = SymCryptDlkeyGenerate(
SYMCRYPT_FLAG_DLKEY_GEN_MODP | SYMCRYPT_FLAG_DLKEY_SELFTEST_DH,
pKey2 );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DH | SYMCRYPT_FLAG_KEY_NO_FIPS | SYMCRYPT_FLAG_DLKEY_GEN_MODP, pKey2 );
CHECK( scError == SYMCRYPT_NO_ERROR, "Error generating key" );
DLKEY_TESTBLOB blob1;
@ -1060,7 +1058,7 @@ testDhtestGroups( DhImplementation * pDh, INT64 line )
&blob1.abPrivKey[0], blob1.cbPrivKey,
&blob1.abPubKey[0], cbP,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION | SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION | SYMCRYPT_FLAG_DLKEY_SELFTEST_DH,
SYMCRYPT_FLAG_DLKEY_DH,
pKey1 );
CHECK4( scError == SYMCRYPT_NO_ERROR, "Error (%d) importing key - nBitsPriv %d", scError, nBitsPriv );
@ -1074,7 +1072,7 @@ testDhtestGroups( DhImplementation * pDh, INT64 line )
&blob1.abPrivKey[0], blob1.cbPrivKey,
&blob1.abPubKey[0], cbP,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION | SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION | SYMCRYPT_FLAG_DLKEY_SELFTEST_DH,
SYMCRYPT_FLAG_DLKEY_DH,
pKey1 );
CHECK5( scError == SYMCRYPT_INVALID_ARGUMENT, "Unexpected return (%d) importing key - nBitsPrivGenerated %d nBitsPriv %d", scError, nBitsPrivGenerated, nBitsPriv );
}
@ -1089,7 +1087,7 @@ testDhtestGroups( DhImplementation * pDh, INT64 line )
&blob1.abPrivKey[0], blob1.cbPrivKey,
&blob1.abPubKey[0], cbP,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION | SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION | SYMCRYPT_FLAG_DLKEY_SELFTEST_DH,
SYMCRYPT_FLAG_DLKEY_DH,
pKey1 );
CHECK5( scError == SYMCRYPT_NO_ERROR, "Error (%d) importing key - nBitsPrivGenerated %d nBitsPriv %d", scError, nBitsPrivGenerated, nBitsPriv );
}

Просмотреть файл

@ -288,9 +288,7 @@ VOID testDlSimple()
pkDlkey = SymCryptDlkeyAllocate( pDlgroup );
CHECK( pkDlkey!=NULL, "?");
scError = SymCryptDlkeyGenerate(
SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA | SYMCRYPT_FLAG_DLKEY_SELFTEST_DH,
pkDlkey );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DSA, pkDlkey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
printDlKey( pkDlkey );
@ -398,9 +396,7 @@ VOID testDlSimple()
printDlGroup( pDlgroup );
// Create a new key and make sure it is mod P
scError = SymCryptDlkeyGenerate(
SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA | SYMCRYPT_FLAG_DLKEY_SELFTEST_DH,
pkDlkey );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DSA, pkDlkey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
CHECK(SymCryptDlkeySizeofPrivateKey(pkDlkey) == cbExpP, "?")
@ -498,9 +494,7 @@ VOID testDlSimple()
printDlGroup( pDlgroup );
// Create a new key and use the mod P flag
scError = SymCryptDlkeyGenerate(
SYMCRYPT_FLAG_DLKEY_GEN_MODP | SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA | SYMCRYPT_FLAG_DLKEY_SELFTEST_DH,
pkDlkey );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_GEN_MODP | SYMCRYPT_FLAG_DLKEY_DSA, pkDlkey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
CHECK(SymCryptDlkeySizeofPrivateKey(pkDlkey) == cbExpP, "?")

Просмотреть файл

@ -25,21 +25,29 @@ template<> VOID algImpTestInteropGenerateKeyEntry< ImpSc >(PBYTE pKeyEntry)
pKE->pGroups[IMPSC_INDEX] = (PBYTE) pDlgroup;
// Dsa and first Dh keys
// Dsa keys
pkSymCryptKey = SymCryptDlkeyAllocate( pDlgroup );
CHECK( pkSymCryptKey != NULL, "?" );
scError = SymCryptDlkeyGenerate( 0, pkSymCryptKey );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DSA, pkSymCryptKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
pKE->pKeysDsa[IMPSC_INDEX] = (PBYTE) pkSymCryptKey;
// First Dh key
pkSymCryptKey = SymCryptDlkeyAllocate( pDlgroup );
CHECK( pkSymCryptKey != NULL, "?" );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DH | SYMCRYPT_FLAG_KEY_NO_FIPS, pkSymCryptKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
pKE->pKeysDhA[IMPSC_INDEX] = (PBYTE) pkSymCryptKey;
// Second Dh key
pkSymCryptKey = SymCryptDlkeyAllocate( pDlgroup );
CHECK( pkSymCryptKey != NULL, "?" );
scError = SymCryptDlkeyGenerate( 0, pkSymCryptKey );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DH | SYMCRYPT_FLAG_KEY_NO_FIPS, pkSymCryptKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
pKE->pKeysDhB[IMPSC_INDEX] = (PBYTE) pkSymCryptKey;

Просмотреть файл

@ -169,7 +169,7 @@ createKatFileSingleDsa( FILE * f, PCDLGROUP_TESTBLOB pBlob )
PSYMCRYPT_DLKEY pKey = SymCryptDlkeyAllocate( pGroup );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA, pKey );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DSA, pKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "Error generating DL key" );
UINT32 cbPrivKey = SymCryptDlkeySizeofPrivateKey( pKey );
@ -354,7 +354,7 @@ testDsatestGroups( DsaImplementation * pDsa, INT64 line )
PSYMCRYPT_DLKEY pKey = SymCryptDlkeyAllocate( pGroup );
CHECK( pKey != NULL, "Could not create keys" );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_SELFTEST_DSA, pKey );
scError = SymCryptDlkeyGenerate( SYMCRYPT_FLAG_DLKEY_DSA, pKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "Error generating key" );
DLKEY_TESTBLOB blob;

Просмотреть файл

@ -479,9 +479,7 @@ testEccArithmetic( _In_ PCSYMCRYPT_ECURVE pCurve )
do
{
scError = SymCryptEckeySetRandom(
SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION | SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA | SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH,
pkKey1 );
scError = SymCryptEckeySetRandom( SYMCRYPT_FLAG_ECKEY_ECDSA | SYMCRYPT_FLAG_ECKEY_ECDH, pkKey1 );
CHECK( scError == SYMCRYPT_NO_ERROR, "Set random key failed" );
CHECK( SymCryptEcpointOnCurve( pCurve, pkKey1->poPublicKey, pbScratch, cbScratch), "Public key not on curve");
@ -900,7 +898,7 @@ testEcdsaVerify(
cbQx + cbQy,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_ECPOINT_FORMAT_XY,
SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION | SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA,
SYMCRYPT_FLAG_ECKEY_ECDSA,
pkPublic );
CHECK3( scError == SYMCRYPT_NO_ERROR, "Public key set value failed for ECDSA record at line %lld", line );
@ -1003,7 +1001,7 @@ testEcdsaSign(
0,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_ECPOINT_FORMAT_XY,
SYMCRYPT_FLAG_KEY_RANGE_VALIDATION | SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDSA,
SYMCRYPT_FLAG_ECKEY_ECDSA,
pkPrivate );
CHECK3( scError == SYMCRYPT_NO_ERROR, "Private key set value failed for ECDSA record at line %lld", line );
@ -1080,7 +1078,7 @@ testEcdh(
PCBYTE pbOptPublicKey = NULL;
SIZE_T cbOptPublicKey = 0;
BYTE randByte = g_rng.byte();
UINT32 flags = SYMCRYPT_FLAG_ECKEY_SELFTEST_ECDH;
UINT32 flags = SYMCRYPT_FLAG_ECKEY_ECDH;
// Allocate the keys
pkPrivate = SymCryptEckeyAllocate( pCurve );
@ -1090,26 +1088,15 @@ testEcdh(
// Set the private and public key for party A
// Randomize flags and whether we provide the public key to exercise more codepaths
if (randByte & 1)
if (randByte & 0x1)
{
flags |= SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION;
flags |= SYMCRYPT_FLAG_KEY_NO_FIPS;
}
switch((randByte >> 1) & 0x3)
if (randByte & 0x2)
{
case 0:
break;
case 1:
flags |= SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION;
break;
case 2:
flags |= SYMCRYPT_FLAG_KEY_RANGE_VALIDATION;
break;
case 3:
default:
flags |= SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION;
break;
flags |= SYMCRYPT_FLAG_ECKEY_ECDSA;
}
if (randByte & 0x8)
if (randByte & 0x4)
{
memcpy(pbPublicKey, pbQxa, cbQxa);
memcpy(pbPublicKey+cbQxa, pbQya, cbQya);
@ -1145,26 +1132,18 @@ testEcdh(
// Set the public key for party B
// Randomize flags to exercise more codepaths
flags = 0;
flags = SYMCRYPT_FLAG_ECKEY_ECDH;
if (randByte & 0x10)
{
// Should do nothing as we won't provide private key, but doesn't hurt to check!
flags |= SYMCRYPT_FLAG_KEY_KEYPAIR_REGENERATION_VALIDATION;
flags |= SYMCRYPT_FLAG_KEY_NO_FIPS;
}
switch((randByte >> 5) & 0x3)
if ((randByte & 0x20) && (flags & SYMCRYPT_FLAG_KEY_NO_FIPS))
{
case 0:
break;
case 1:
flags |= SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION;
break;
case 2:
flags |= SYMCRYPT_FLAG_KEY_RANGE_VALIDATION;
break;
case 3:
default:
flags |= SYMCRYPT_FLAG_KEY_RANGE_AND_PUBLIC_KEY_ORDER_VALIDATION;
break;
flags |= SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION;
}
if (randByte & 0x40)
{
flags |= SYMCRYPT_FLAG_ECKEY_ECDSA;
}
memcpy(pbPublicKey, pbQxb, cbQxb);
memcpy(pbPublicKey+cbQxb, pbQyb, cbQyb);

Просмотреть файл

@ -226,7 +226,7 @@ testMontgomery(PSYMCRYPT_ECURVE pCurve)
do
{
scError = SymCryptEckeySetRandom( 0, pkKey1 );
scError = SymCryptEckeySetRandom( SYMCRYPT_FLAG_ECKEY_ECDH, pkKey1 );
CHECK( scError == SYMCRYPT_NO_ERROR, "Set random key failed" );
scError = SymCryptEcpointScalarMul( pCurve, pkKey1->piPrivateKey, NULL, 0, poSrc, pbScratch, cbScratch );

Просмотреть файл

@ -197,7 +197,7 @@ rsaTestKeysAddOne( UINT32 bitSize )
u64PubExp = 65537;
}
scError = SymCryptRsakeyGenerate( pKey, &u64PubExp, 1, SYMCRYPT_FLAG_RSAKEY_SELFTEST );
scError = SymCryptRsakeyGenerate( pKey, &u64PubExp, 1, SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );
PRSAKEY_TESTBLOB pBlob = &g_RsaTestKeyBlobs[ g_nRsaTestKeyBlobs++ ];
@ -324,7 +324,7 @@ rsaKeyFromTestBlob( PCRSAKEY_TESTBLOB pBlob )
&pBlob->u64PubExp, 1,
ppPrime, cbPrime, 2,
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
SYMCRYPT_FLAG_RSAKEY_SELFTEST,
SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT,
pKey );
CHECK( scError == SYMCRYPT_NO_ERROR, "?" );