зеркало из https://github.com/microsoft/SymCrypt.git
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:
Родитель
31e06ae046
Коммит
317e785816
|
@ -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
|
||||
|
|
362
inc/symcrypt.h
362
inc/symcrypt.h
|
@ -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)
|
||||
|
|
8
lib/dh.c
8
lib/dh.c
|
@ -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) )
|
||||
|
|
193
lib/dlkey.c
193
lib/dlkey.c
|
@ -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;
|
||||
}
|
||||
|
|
14
lib/dsa.c
14
lib/dsa.c
|
@ -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)
|
||||
{
|
||||
|
|
21
lib/ec_dsa.c
21
lib/ec_dsa.c
|
@ -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 )
|
||||
{
|
||||
|
|
177
lib/eckey.c
177
lib/eckey.c
|
@ -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;
|
||||
|
|
81
lib/rsakey.c
81
lib/rsakey.c
|
@ -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;
|
||||
}
|
||||
|
|
253
lib/sc_lib.h
253
lib/sc_lib.h
|
@ -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( ¶ms, 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, "?" );
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче