Merged PR 10817310: Add XMSS and XMSS^MT implementations

## Description:

Adds support for stateful hash-based signatures XMSS and XMSS^MT per RFC 8391 and NIST SP800-208.

## Admin Checklist:
- [ ] You have updated documentation in symcrypt.h to reflect any changes in behavior
- [ ] You have updated CHANGELOG.md to reflect any changes in behavior
- [ ] You have updated symcryptunittest to exercise any new functionality
- [ ] If you have introduced any symbols in symcrypt.h you have updated production and test dynamic export symbols (exports.ver / exports.def / symcrypt.src) and tested the updated dynamic modules with symcryptunittest
- [ ] If you have introduced functionality that varies based on CPU features, you have manually tested with and without relevant features
- [ ] If you have made significant changes to a particular algorithm, you have checked that performance numbers reported by symcryptunittest are in line with expectations
- [ ] If you have added new algorithms/modes, you have updated the status indicator text for the associated modules if necessary

Related work items: #52453903
This commit is contained in:
Cagdas Calik 2024-08-13 18:14:13 +00:00
Родитель f89cbf36c3
Коммит 15d0779214
29 изменённых файлов: 32891 добавлений и 9 удалений

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

@ -5,6 +5,7 @@ prior to the creation of a new release, based on the changes contained in that r
- Internal self-test changes to support FIPS 140-3 certification
- Add SSKDF implementation
- Add XMSS and XMSS^MT implementations
# Version 103.4.3

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

@ -222,6 +222,8 @@ typedef _Return_type_success_( return == SYMCRYPT_NO_ERROR ) enum {
SYMCRYPT_INCOMPATIBLE_FORMAT,
SYMCRYPT_VALUE_TOO_LARGE,
SYMCRYPT_SESSION_REPLAY_FAILURE,
SYMCRYPT_HBS_NO_OTS_KEYS_LEFT,
SYMCRYPT_HBS_PUBLIC_ROOT_MISMATCH,
} SYMCRYPT_ERROR;
// SYMCRYPT_ECURVE_TYPE needs to be completely defined before including
@ -8202,6 +8204,555 @@ SymCryptEcDhSecretAgreementSelftest(void);
// with FIPS validation, so most callers should never use this function.
//
//========================================================================
//
// Stateful Hash-based Signatures
//
// Hash-based signature schemes are digital signature schemes built out of hash
// functions. Stateful hash-based signatures are many-time signature schemes
// composed of a one-time-signature (OTS) scheme and a Merkle-tree representing
// multiple OTS with a public root value. At each signing operation, one of the
// (unused) OTS keys is used to sign the message, and the private key is updated
// so that the same OTS is not used again. Because there is a limited number of
// OTS keys determined at key generation time, signing cannot be performed after
// all OTSs are used. This is an important distinction from other digital signature
// schemes such as RSA or ECDSA.
//
// It is crucial for the security of the *stateful* hash-based signatures that the
// same private key state NOT be used more than once to sign messages, otherwise all
// security is lost.
//
//========================================================================
// XMSS API
//
// XMSS is a stateful hash-based signature scheme specified in RFC 8391. The
// multi-tree variant is named XMSS^MT.
//
// XMSS uses WOTS+ as the one-time-signature (OTS) scheme. Public key consists
// of two parts; Merkle-tree hash of OTS public keys called the Root, and a Seed value
// used in in hash computations. The private key consists of SK_XMSS which is
// used to deterministacally create OTS keys, SK_PRF which is used to generate
// the randomizer for hashing, and an integer Idx is used to select the next OTS key
// for signing.
//
typedef enum _SYMCRYPT_XMSS_ALGID
{
// Hash Fn. RFC-8391 SP800-208
SYMCRYPT_XMSS_SHA2_10_256 = 0x00000001, // SHA-256 X X
SYMCRYPT_XMSS_SHA2_16_256 = 0x00000002, // SHA-256 X X
SYMCRYPT_XMSS_SHA2_20_256 = 0x00000003, // SHA-256 X X
SYMCRYPT_XMSS_SHA2_10_512 = 0x00000004, // SHA-512 X
SYMCRYPT_XMSS_SHA2_16_512 = 0x00000005, // SHA-512 X
SYMCRYPT_XMSS_SHA2_20_512 = 0x00000006, // SHA-512 X
SYMCRYPT_XMSS_SHAKE_10_256 = 0x00000007, // SHAKE128 X
SYMCRYPT_XMSS_SHAKE_16_256 = 0x00000008, // SHAKE128 X
SYMCRYPT_XMSS_SHAKE_20_256 = 0x00000009, // SHAKE128 X
SYMCRYPT_XMSS_SHAKE_10_512 = 0x0000000A, // SHAKE256 X
SYMCRYPT_XMSS_SHAKE_16_512 = 0x0000000B, // SHAKE256 X
SYMCRYPT_XMSS_SHAKE_20_512 = 0x0000000C, // SHAKE256 X
SYMCRYPT_XMSS_SHA2_10_192 = 0x0000000D, // SHA-256 X
SYMCRYPT_XMSS_SHA2_16_192 = 0x0000000E, // SHA-256 X
SYMCRYPT_XMSS_SHA2_20_192 = 0x0000000F, // SHA-256 X
SYMCRYPT_XMSS_SHAKE256_10_256 = 0x00000010, // SHAKE256 X
SYMCRYPT_XMSS_SHAKE256_16_256 = 0x00000011, // SHAKE256 X
SYMCRYPT_XMSS_SHAKE256_20_256 = 0x00000012, // SHAKE256 X
SYMCRYPT_XMSS_SHAKE256_10_192 = 0x00000013, // SHAKE256 X
SYMCRYPT_XMSS_SHAKE256_16_192 = 0x00000014, // SHAKE256 X
SYMCRYPT_XMSS_SHAKE256_20_192 = 0x00000015, // SHAKE256 X
} SYMCRYPT_XMSS_ALGID;
typedef enum _SYMCRYPT_XMSSMT_ALGID
{
// Hash Fn. RFC-8391 SP800-208
// SHA-256 X X
SYMCRYPT_XMSSMT_SHA2_20_2_256 = 0x00000001,
SYMCRYPT_XMSSMT_SHA2_20_4_256 = 0x00000002,
SYMCRYPT_XMSSMT_SHA2_40_2_256 = 0x00000003,
SYMCRYPT_XMSSMT_SHA2_40_4_256 = 0x00000004,
SYMCRYPT_XMSSMT_SHA2_40_8_256 = 0x00000005,
SYMCRYPT_XMSSMT_SHA2_60_3_256 = 0x00000006,
SYMCRYPT_XMSSMT_SHA2_60_6_256 = 0x00000007,
SYMCRYPT_XMSSMT_SHA2_60_12_256 = 0x00000008,
// SHA-512 X
SYMCRYPT_XMSSMT_SHA2_20_2_512 = 0x00000009,
SYMCRYPT_XMSSMT_SHA2_20_4_512 = 0x0000000A,
SYMCRYPT_XMSSMT_SHA2_40_2_512 = 0x0000000B,
SYMCRYPT_XMSSMT_SHA2_40_4_512 = 0x0000000C,
SYMCRYPT_XMSSMT_SHA2_40_8_512 = 0x0000000D,
SYMCRYPT_XMSSMT_SHA2_60_3_512 = 0x0000000E,
SYMCRYPT_XMSSMT_SHA2_60_6_512 = 0x0000000F,
SYMCRYPT_XMSSMT_SHA2_60_12_512 = 0x00000010,
// SHAKE128 X
SYMCRYPT_XMSSMT_SHAKE_20_2_256 = 0x00000011,
SYMCRYPT_XMSSMT_SHAKE_20_4_256 = 0x00000012,
SYMCRYPT_XMSSMT_SHAKE_40_2_256 = 0x00000013,
SYMCRYPT_XMSSMT_SHAKE_40_4_256 = 0x00000014,
SYMCRYPT_XMSSMT_SHAKE_40_8_256 = 0x00000015,
SYMCRYPT_XMSSMT_SHAKE_60_3_256 = 0x00000016,
SYMCRYPT_XMSSMT_SHAKE_60_6_256 = 0x00000017,
SYMCRYPT_XMSSMT_SHAKE_60_12_256 = 0x00000018,
// SHAKE256 X
SYMCRYPT_XMSSMT_SHAKE_20_2_512 = 0x00000019,
SYMCRYPT_XMSSMT_SHAKE_20_4_512 = 0x0000001A,
SYMCRYPT_XMSSMT_SHAKE_40_2_512 = 0x0000001B,
SYMCRYPT_XMSSMT_SHAKE_40_4_512 = 0x0000001C,
SYMCRYPT_XMSSMT_SHAKE_40_8_512 = 0x0000001D,
SYMCRYPT_XMSSMT_SHAKE_60_3_512 = 0x0000001E,
SYMCRYPT_XMSSMT_SHAKE_60_6_512 = 0x0000001F,
SYMCRYPT_XMSSMT_SHAKE_60_12_512 = 0x00000020,
// SHA-256 X
SYMCRYPT_XMSSMT_SHA2_20_2_192 = 0x00000021,
SYMCRYPT_XMSSMT_SHA2_20_4_192 = 0x00000022,
SYMCRYPT_XMSSMT_SHA2_40_2_192 = 0x00000023,
SYMCRYPT_XMSSMT_SHA2_40_4_192 = 0x00000024,
SYMCRYPT_XMSSMT_SHA2_40_8_192 = 0x00000025,
SYMCRYPT_XMSSMT_SHA2_60_3_192 = 0x00000026,
SYMCRYPT_XMSSMT_SHA2_60_6_192 = 0x00000027,
SYMCRYPT_XMSSMT_SHA2_60_12_192 = 0x00000028,
// SHAKE256 X
SYMCRYPT_XMSSMT_SHAKE256_20_2_256 = 0x00000029,
SYMCRYPT_XMSSMT_SHAKE256_20_4_256 = 0x0000002A,
SYMCRYPT_XMSSMT_SHAKE256_40_2_256 = 0x0000002B,
SYMCRYPT_XMSSMT_SHAKE256_40_4_256 = 0x0000002C,
SYMCRYPT_XMSSMT_SHAKE256_40_8_256 = 0x0000002D,
SYMCRYPT_XMSSMT_SHAKE256_60_3_256 = 0x0000002E,
SYMCRYPT_XMSSMT_SHAKE256_60_6_256 = 0x0000002F,
SYMCRYPT_XMSSMT_SHAKE256_60_12_256 = 0x00000030,
// SHAKE256 X
SYMCRYPT_XMSSMT_SHAKE256_20_2_192 = 0x00000031,
SYMCRYPT_XMSSMT_SHAKE256_20_4_192 = 0x00000032,
SYMCRYPT_XMSSMT_SHAKE256_40_2_192 = 0x00000033,
SYMCRYPT_XMSSMT_SHAKE256_40_4_192 = 0x00000034,
SYMCRYPT_XMSSMT_SHAKE256_40_8_192 = 0x00000035,
SYMCRYPT_XMSSMT_SHAKE256_60_3_192 = 0x00000036,
SYMCRYPT_XMSSMT_SHAKE256_60_6_192 = 0x00000037,
SYMCRYPT_XMSSMT_SHAKE256_60_12_192 = 0x00000038,
} SYMCRYPT_XMSSMT_ALGID;
typedef enum _SYMCRYPT_XMSSKEY_TYPE
{
SYMCRYPT_XMSSKEY_TYPE_NONE = 0,
SYMCRYPT_XMSSKEY_TYPE_PUBLIC = 1, // Key object contains only public key
SYMCRYPT_XMSSKEY_TYPE_PRIVATE = 2, // Key object contains both public key and private key
} SYMCRYPT_XMSSKEY_TYPE;
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmssParamsFromAlgId(
SYMCRYPT_XMSS_ALGID id,
_Out_ PSYMCRYPT_XMSS_PARAMS pParams);
//
// Populate SYMCRYPT_XMSS_PARAMS structure for the specified XMSS algorithm identifier
// using the predefined parameter sets from RFC 8391 and NIST SP800-208
//
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmssMtParamsFromAlgId(
SYMCRYPT_XMSSMT_ALGID id,
_Out_ PSYMCRYPT_XMSS_PARAMS pParams);
//
// Populate SYMCRYPT_XMSS_PARAMS structure for the specified XMSS^MT algorithm identifier
// using the predefined parameter sets from RFC 8391 and NIST SP800-208
//
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmssSetParams(
_Out_ PSYMCRYPT_XMSS_PARAMS pParams,
UINT32 id, // algorithm identifier
_In_ PCSYMCRYPT_HASH pHash, // hash algorithm
UINT32 cbHashOutput, // hash output size
UINT32 nWinternitzWidth, // Winternitz parameter (width of digits)
UINT32 nTotalTreeHeight, // total tree height
UINT32 nLayers, // number of levels
UINT32 cbPrefix // domain separator prefix length
);
//
// Populates SYMCRYPT_XMSS_PARAMS structure by user defined parameters
//
//
// Parameters:
//
// pParams. Pointer to the structure that will be populated with the
// supplied parameters.
//
// id. Algorithm identifier, will be embedded in key and signature objects.
//
// pHash. Pointer to a hash object that implements a hash function which
// will be used in XMSS/XMSS^MT operations.
//
// cbHashOutput. Output size of the hash function in bytes. Leading cbHashOutput
// bytes are taken as hash output if the hash algorithm's actual output size is larger.
//
// nWinternitzWidth. Winternitz parameter, width of digits in byte sequences.
// See remark below for more explanation.
//
// nTotalTreeHeight. Height of the XMSS/XMSS^MT tree. In a multi-tree setting,
// it is the sum of the tree heights of each layer.
//
// nLayers. Number of layers. For XMSS nLayers=1, otherwise nLayers > 1. When nLayers > 1,
// it must divide nTotalTreeHeight without remainder, so that each layer has height
// nTotalTreeHeight/nLayers.
//
// cbPrefix. Number of bytes in the prefix to the hash inputs used to domain separate
// PRF functions.
//
// Requirements:
//
// cbHashOutput must be nonzero, must be less than or equal to pHash->resultSize,
// and must be less than or equal to SYMCRYPT_HASH_MAX_RESULT_SIZE
//
// nWinternitzWidth must be one of 1, 2, 4, or 8
//
// nTotalTreeHeight must be non-zero, it must be less than or equal to 32 for
// single-tree (nLayers = 1), and must be less than 64 for multi-tree (nLayers > 1)
//
// nLayers must be non-zero and must divide nTotalTreeHeight without remainder
//
// cbPrefix must be non-zero
//
// Remarks:
//
// RFC 8391 specifies w as the length of the Winternitz chains. Here,
// it is used as the width of the digits in an octet string, i.e.,
// base2 logarithm of the chain length, which is similar to its use
// in LMS/HSS in RFC 8554.
//
#define SYMCRYPT_FLAG_XMSSKEY_VERIFY_ROOT (0x00000001)
// Verifies the public root value when importing a private key
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmssSizeofKeyBlobFromParams(
_In_ PCSYMCRYPT_XMSS_PARAMS pParams,
SYMCRYPT_XMSSKEY_TYPE keyType,
_Out_ SIZE_T* pcbKey );
//
// Return the size of an XMSS/XMSS^MT key blob associated with the provided XMSS parameters
//
//
// Parameters:
//
// pParams. Pointer to an XMSS parameters structure that has been properly
// initialized before this call.
//
// keyType. SYMCRYPT_XMSSKEY_TYPE_PUBLIC (resp. SYMCRYPT_XMSSKEY_TYPE_PRIVATE) to
// retrieve the size of the public key (resp. private key).
//
// pcbKey. Pointer to the variable to store the size of a public/private
// key blob associated with the XMSS parameters.
//
// Remarks:
//
// Callers may provide a NULL pointer for the size they are not interested to query.
//
PSYMCRYPT_XMSS_KEY
SYMCRYPT_CALL
SymCryptXmsskeyAllocate(
_In_ PCSYMCRYPT_XMSS_PARAMS pParams,
UINT32 flags );
//
// Allocate an XMSS/XMSS^MT key object and initialize it
//
// After this call, the key object does not contain a key yet. It must be
// followed by a call to SymCryptXmsskeyGenerate or SymCryptXmsskeySetValue.
//
// Allowed flags:
//
// No flags defined for this function
//
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmsskeyGenerate(
_Inout_ PSYMCRYPT_XMSS_KEY pKey,
UINT32 flags );
//
// Generate a public/private XMSS/XMSS^MT key-pair
//
// Parameters:
//
// pKey. Key object to store the public/private key-pair
//
// flags. No flags defined for this function
//
// Return values:
//
// - SYMCRYPT_NO_ERROR
// On successfull key generation
//
// - SYMCRYPT_MEMORY_ALLOCATION_FAILURE
// If there is not enough memory to perform key generation
//
// Remarks:
//
// - Generates a random private key (SK_XMSS, SK_PRF) and a random
// public seed SEED, and computes the public value Root from it.
// - If the function fails, the key object will be in an invalid state.
//
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmsskeySetValue(
_In_reads_bytes_( cbSrc ) PCBYTE pbInput,
SIZE_T cbInput,
SYMCRYPT_XMSSKEY_TYPE keyType,
UINT32 flags,
_Inout_ PSYMCRYPT_XMSS_KEY pKey );
//
// Set an XMSS/XMSS^MT public/private key from key blob
//
// Key formats:
//
// PubKey: algId | Root | Seed
// PrvKey: algId | Root | Seed | Idx | SK_XMSS | SK_PRF
//
// algId and Idx are 32-bit and 64-bit integers respectively, stored in big-endian format.
// Other values are n-bytes where n is the output size (in bytes) of the hash
// algorithm (or the truncated size if the hash output is truncated).
//
// Public-key format is specified in RFC 8391, whereas private-key format is not.
// We define the private-key as an extension of the public-key with the private key
// material.
//
// Parameters:
//
// (pbInput, cbInput). Input key blob to import the key from
//
// keyType. Indicates whether (pbInput, cbInput) contains a public or a private key.
// Must be one of SYMCRYPT_XMSSKEY_TYPE_PUBLIC, or SYMCRYPT_XMSSKEY_TYPE_PRIVATE.
//
// flags. See below
//
// pKey. Pointer to the XMSS key object to be initialized from the key blob
//
// Allowed flags:
//
// - SYMCRYPT_FLAG_XMSSKEY_VERIFY_ROOT
// Can only be specified when importing a private key. Recomputes the
// public root value and compares it to the one that is imported from the
// key blob.
//
// Return values:
//
// - SYMCRYPT_NO_ERROR
// On successfully updating the key object from the provided key blob
//
// - SYMCRYPT_INVALID_ARGUMENT
// If cbInput does not match a public/private key size indicated by keyType parameter
// If an invalid flag is specified, or SYMCRYPT_FLAG_XMSSKEY_VERIFY_ROOT is
// specified when setting a public key
//
// - SYMCRYPT_INLVALID_BLOB
// If the XMSS algorithm ID in the key blob does not match the algorithm ID
// used in creating the key object pointed to by pKey
//
// - SYMCRYPT_MEMORY_ALLOCATION_FAILURE
// If there is not sufficient memory for public root verification (only if
// SYMCRYPT_FLAG_XMSSKEY_VERIFY_ROOT is set in flags)
//
// - SYMCRYPT_HBS_PUBLIC_ROOT_MISMATCH
// If public root value in the key blob does not match the recomputed root value
// (only if key blob is for a private key and SYMCRYPT_FLAG_XMSSKEY_VERIFY_ROOT is
// specified)
//
// Remarks:
//
// - The key blob size pbInput must match the size returned by SymCryptXmssSizeofKeyBlobFromParams
// for the same keyType and XMSS parameters the key object is created with.
// - If the function fails, the key object will be in an invalid state.
//
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmsskeyGetValue(
_In_ PCSYMCRYPT_XMSS_KEY pKey,
SYMCRYPT_XMSSKEY_TYPE keyType,
UINT32 flags,
_Out_writes_bytes_( cbKey ) PBYTE pbOutput,
SIZE_T cbOutput );
//
// Get public/private key value from an XMSS/XMSS^MT key object
//
// Key formats:
//
// PubKey: algId | Root | Seed
// PrvKey: algId | Root | Seed | Idx | SK_XMSS | SK_PRF
//
// algId and Idx are 32-bit and 64-bit integers respectively, stored in big-endian format.
// Other values are n-bytes where n is the output size (in bytes) of the hash
// algorithm (or the truncated size if the hash output is truncated).
//
// Public-key format is specified in RFC 8391, whereas private-key format is not.
// We define the private-key as an extension of the public-key with the private key
// material.
//
// Parameters:
//
// pKey. The key object to export the key material from
//
// keyType. Type of the key (public or private) to get. If the key object
// contains a public key, keyType must be SYMCRYPT_XMSSKEY_TYPE_PUBLIC. If
// the key object contains a private key, keyType can be one of
// SYMCRYPT_XMSSKEY_TYPE_PUBLIC or SYMCRYPT_XMSSKEY_TYPE_PRIVATE
//
// flags. No flags defined for this function
//
// (pbOutput, cbOutput). Buffer to store the exported key blob. cbOutput must match
// the size of the key to be exported, which can be queried by calling
// SymCryptXmssSizeofKeyBlobFromParams.
//
// Return values:
//
// - SYMCRYPT_NO_ERROR
// On successful exporting of the key
//
// - SYMCRYPT_INVALID_ARGUMENT
// If cbOutput does not match the exact size of the key blob for the specified
// keyType
// If the key object does not contain private key material when keyType
// equals SYMCRYPT_XMSSKEY_TYPE_PRIVATE
// If unsupported flags are specified in flags parameter
//
VOID
SYMCRYPT_CALL
SymCryptXmsskeyFree(
_Inout_ PSYMCRYPT_XMSS_KEY pKey);
//
// Free an allocated XMSS/XMSS^MT key object
//
SIZE_T
SYMCRYPT_CALL
SymCryptXmssSizeofSignatureFromParams(
_In_ PCSYMCRYPT_XMSS_PARAMS pParams );
//
// Return the size of the signature for given XMSS parameters
//
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmssSign(
_Inout_ PSYMCRYPT_XMSS_KEY pKey,
_In_reads_bytes_( cbMessage ) PCBYTE pbMessage,
SIZE_T cbMessage,
UINT32 flags,
_Out_writes_bytes_( cbSignature ) PBYTE pbSignature,
SIZE_T cbSignature );
//
// Sign a message using XMSS/XMSS^MT
//
// Parameters:
//
// pKey. Private XMSS/XMSS^MT key used in signing
//
// (pbMessage, cbMessage). Message to be signed
//
// flags. No flags defined for this function
//
// (pbSignature, cbSignature). Buffer to store the generated signature
//
// Requirements:
//
// pKey must contain the private key
//
// cbSignature must be equal to the generated signature size
//
// Return values:
//
// - SYMCRYPT_NO_ERROR on successfull signature generation
//
// - SYMCRYPT_INVALID_ARGUMENT
// If flags parameter is invalid,
// or if the key object does not contain private key,
// or cbSignature is not of correct size
//
// - SYMCRYPT_HBS_NO_OTS_KEYS_LEFT
// If the key doesn't have any one-time-signatures left for signing
//
// Remarks:
//
// The input pbMessage can be of arbitrary length and its randomized hash will be the actual
// value that is going to be signed with a WOTSP signature. Applications wanting to pass the hash
// value of a message to be signed as opposed to the message itself must make sure to have
// domain separation between the space of messages and the hashes of the messages.
//
// The signature size can be queried with SymCryptSizeofXmssSignatureFromParams function.
//
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmssVerify(
_Inout_ PSYMCRYPT_XMSS_KEY pKey,
_In_reads_bytes_( cbMessage ) PCBYTE pbMessage,
SIZE_T cbMessage,
UINT32 flags,
_In_reads_bytes_( cbSignature ) PCBYTE pbSignature,
SIZE_T cbSignature );
//
// Verify an XMSS/XMSS^MT signature on a message
//
// Parameters:
//
// pKey. XMSS key used to verify the signature
//
// (pbMessage, cbMessage) Message for which the signature was created
//
// flags. No flags defined for this function
//
// (pbSignature, cbSignature) XMSS or XMSS^MT signature
//
// Return values:
//
// - SYMCRYPT_NO_ERROR
// If signature verification succeeeds
//
// - SYMCRYPT_INVALID_ARGUMENT
// If flags is invalid or cbSignature is of incorrect size
//
// - SYMCRYPT_SIGNATURE_VERIFICATION_ERROR
// If the signature is not valid
//
// Requirements:
//
// cbSignature must be equal to the exact signature size associated with
// the XMSS parameters.
//
// Remarks:
//
// In XMSS, the message can be arbitrarily long and a randomized hash of the message
// will be computed first to be signed by the WOTSP internally.
//
VOID
SYMCRYPT_CALL
SymCryptXmssSelftest(void);
//
// FIPS self-test for signature verification
//
//
// SymCryptFatal
//

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

@ -2784,6 +2784,42 @@ SYMCRYPT_ALIGN_STRUCT _SYMCRYPT_802_11_SAE_CUSTOM_STATE {
BYTE counter;
};
//
// XMSS
//
typedef SYMCRYPT_ALIGN_STRUCT _SYMCRYPT_XMSS_PARAMS
{
PCSYMCRYPT_HASH hash; // hash function
UINT32 id; // algorithm identifier
UINT32 cbHashOutput; // hash function output size, must be less than or equal to hash->resultSize
UINT32 nWinternitzWidth;// Wintertnitz coefficient, width of digits in bits (chain length = 2^nWinternitzWidth)
UINT32 nTotalTreeHeight;// number of layers times the tree height of one layer (each layer has the same height)
UINT32 nLayers; // hyper-tree layers, 1 for single tree
UINT32 cbPrefix; // length of the domain separator prefix in PRFs
//
// The following are derived from the above
//
UINT32 len1; // number of w-bit digits in the hash output to be signed ( len1 = ceil(8n / w) )
UINT32 len2; // number of w-bit digits in the checksum
UINT32 len; // len1 + len2
UINT32 nLayerHeight; // tree height of a single layer (h / d)
UINT32 cbIdx; // size of leaf counter in bytes (for single trees cbIdx = 4)
UINT32 nLeftShift32; // left shift count to align the checksum digits to MSB of a 32-bit word
BYTE Reserved[16]; // Reserved for future use
} SYMCRYPT_XMSS_PARAMS;
typedef SYMCRYPT_XMSS_PARAMS* PSYMCRYPT_XMSS_PARAMS;
typedef const SYMCRYPT_XMSS_PARAMS* PCSYMCRYPT_XMSS_PARAMS;
struct _SYMCRYPT_XMSS_KEY;
typedef struct _SYMCRYPT_XMSS_KEY SYMCRYPT_XMSS_KEY;
typedef SYMCRYPT_XMSS_KEY* PSYMCRYPT_XMSS_KEY;
typedef const SYMCRYPT_XMSS_KEY* PCSYMCRYPT_XMSS_KEY;
#ifndef _PREFAST_
#if SYMCRYPT_CPU_X86

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

@ -116,6 +116,7 @@ set(SOURCES_COMMON
tlsCbcVerify.c
tlsprf_selftest.c
tlsprf.c
xmss.c
xtsaes.c
)

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

@ -486,6 +486,97 @@ const BYTE rgbSha256Hash[] =
};
// XMSS-SHA2_10_192 public-key and signature for message "abc"
const BYTE rgbXmssSha2_10_192Pubkey[] =
{
// Algorithm ID
0x00, 0x00, 0x00, 0x0d,
// Root
0x7e, 0x63, 0xd5, 0x1d, 0xdf, 0x92, 0x0f, 0x10,
0x63, 0x52, 0x82, 0x38, 0xdf, 0x15, 0x0e, 0x83,
0x5c, 0x74, 0x0a, 0x25, 0x10, 0xc8, 0x3b, 0xdc,
// Seed
0x75, 0x78, 0x08, 0x77, 0xb0, 0x90, 0x02, 0x63,
0x45, 0x4b, 0xf9, 0xad, 0xee, 0x52, 0x04, 0x75,
0x45, 0x13, 0x99, 0xdd, 0x9f, 0xbb, 0xc7, 0x43,
};
const BYTE rgbXmssSha2_10_192Signature[] =
{
// Idx
0x00, 0x00, 0x00, 0x03,
// Randomness
0xf8, 0xbe, 0x24, 0x0e, 0x21, 0x1f, 0x9b, 0x7f, 0x3a, 0x81, 0x82, 0x32, 0x79, 0xe2, 0x2f, 0x42, 0xa5, 0x5a, 0xea, 0x32, 0x75, 0x58, 0x47, 0x8a,
// WOTSP signature
0x2d, 0xaa, 0x55, 0xc6, 0xdb, 0xa4, 0x46, 0x83, 0xda, 0x62, 0xba, 0x67, 0x1a, 0xa2, 0x53, 0x4a, 0xbf, 0xf4, 0x0c, 0x4e, 0x8d, 0xa6, 0x3b, 0xdf,
0x92, 0x1c, 0x80, 0xb7, 0xe6, 0x58, 0x66, 0xf3, 0x5d, 0x01, 0xd7, 0x31, 0x70, 0x7e, 0x22, 0x04, 0x73, 0xb0, 0xaa, 0x7a, 0x64, 0xf9, 0xba, 0xf5,
0x37, 0x58, 0x98, 0x7e, 0x9c, 0x81, 0xd4, 0xa5, 0xe0, 0x2e, 0xed, 0x6b, 0x61, 0x57, 0xe5, 0x73, 0x80, 0x42, 0x79, 0xe2, 0x30, 0x9d, 0xa8, 0x9c,
0x0c, 0x10, 0x1f, 0xb9, 0xf5, 0xa0, 0x17, 0x0e, 0xa0, 0x99, 0xa4, 0xd8, 0x42, 0xea, 0x90, 0xa3, 0xb0, 0x20, 0x89, 0x02, 0x35, 0xfe, 0x86, 0x2e,
0x9a, 0x72, 0x41, 0x72, 0x77, 0xb6, 0xbd, 0x30, 0x05, 0xb0, 0xfa, 0xb4, 0x43, 0xc9, 0xfe, 0x54, 0x3f, 0x78, 0x83, 0x87, 0x1a, 0x10, 0xeb, 0x8a,
0xf3, 0xbe, 0x59, 0x67, 0x86, 0x26, 0x6e, 0xa2, 0xff, 0xaa, 0xb1, 0xa4, 0xb3, 0xcb, 0xfd, 0xe5, 0x31, 0xb3, 0xd4, 0x2a, 0x02, 0x5e, 0xea, 0xfb,
0xea, 0x95, 0x70, 0xa2, 0x56, 0xe9, 0x9e, 0xd1, 0x84, 0x0b, 0xd4, 0xc8, 0xa3, 0xee, 0x46, 0x48, 0x96, 0x1f, 0x30, 0x7d, 0x86, 0x63, 0x47, 0x18,
0xb2, 0xe2, 0x3b, 0xe3, 0x89, 0x28, 0x5b, 0x6f, 0x5d, 0x2a, 0xe4, 0xe5, 0x3e, 0xb2, 0x2a, 0x97, 0x00, 0x04, 0xe7, 0xe3, 0x87, 0xa3, 0x6b, 0x73,
0xe3, 0xcd, 0x99, 0x5a, 0x8b, 0x93, 0x6a, 0x28, 0x53, 0x66, 0x5b, 0x21, 0x0b, 0x88, 0x2f, 0x01, 0x31, 0x37, 0x03, 0x21, 0xf9, 0xd6, 0x47, 0x99,
0x75, 0x81, 0x27, 0x7b, 0x24, 0xa4, 0x23, 0x32, 0x33, 0x6b, 0x3b, 0x8f, 0xe3, 0x5b, 0x38, 0xcc, 0xa5, 0x53, 0xb0, 0x15, 0xd3, 0xc8, 0x42, 0x75,
0x2d, 0x73, 0x5a, 0x80, 0x01, 0x10, 0x66, 0x48, 0xf6, 0x3e, 0x36, 0x84, 0xc8, 0xc0, 0x7a, 0xf6, 0xfb, 0xe1, 0xe8, 0x15, 0x3e, 0x9e, 0x0c, 0xd0,
0x0c, 0x45, 0x82, 0xa3, 0xfa, 0x8a, 0x0b, 0x6f, 0x84, 0x0b, 0x98, 0xf9, 0x58, 0x88, 0xb8, 0x13, 0xc7, 0xd7, 0x4e, 0x91, 0x89, 0x2f, 0xc0, 0x6f,
0x00, 0xf1, 0x6d, 0x67, 0xea, 0xb8, 0xae, 0xbb, 0xa9, 0x12, 0xcb, 0xe6, 0x69, 0xd6, 0x0e, 0xb3, 0xfb, 0xa8, 0xb0, 0x42, 0x06, 0x64, 0x25, 0x07,
0xcc, 0xb7, 0xa8, 0x05, 0x51, 0xc2, 0x9f, 0xe9, 0xed, 0x59, 0xb9, 0xb0, 0x9d, 0x4c, 0x56, 0x8e, 0xc2, 0x48, 0xf6, 0x4a, 0x8b, 0x71, 0x90, 0xa1,
0x3c, 0xd2, 0xf5, 0xab, 0x74, 0xca, 0xaf, 0x1c, 0x31, 0xa6, 0x45, 0x30, 0x89, 0xb4, 0xe1, 0x4a, 0x82, 0x08, 0x75, 0x46, 0x16, 0xd8, 0x1e, 0x8a,
0x42, 0x6c, 0xa0, 0x63, 0x71, 0x41, 0x4f, 0x50, 0xa8, 0xa2, 0x61, 0xcf, 0xb7, 0xd7, 0x4d, 0x91, 0x55, 0xf2, 0xf2, 0xdf, 0xf6, 0xe2, 0xac, 0xb3,
0x6f, 0x54, 0x32, 0xb9, 0xf0, 0x3d, 0x8e, 0xf3, 0x04, 0xae, 0xdd, 0x8f, 0x53, 0xb9, 0x8b, 0xe3, 0xcc, 0x3d, 0xbc, 0x54, 0xe4, 0xc4, 0x7c, 0x6d,
0x10, 0xfe, 0xd6, 0xeb, 0x12, 0xeb, 0xd1, 0xb1, 0x0a, 0x74, 0x56, 0x81, 0x3a, 0x05, 0x45, 0x65, 0x37, 0x0e, 0x8c, 0x0c, 0x0d, 0xad, 0x3e, 0x91,
0xc7, 0x9a, 0x3c, 0xe6, 0xd7, 0x3a, 0xfb, 0x9f, 0x54, 0x66, 0x03, 0x0d, 0x9e, 0x18, 0xe5, 0xa2, 0x19, 0xca, 0x3a, 0xaa, 0x99, 0x6f, 0xe8, 0x15,
0xe3, 0x47, 0x4b, 0x90, 0x93, 0x17, 0x89, 0xda, 0x13, 0xff, 0xe5, 0xad, 0x8b, 0xd5, 0xe8, 0xeb, 0x25, 0x3e, 0x10, 0x66, 0x8e, 0x13, 0x01, 0x4d,
0xc1, 0xc9, 0x17, 0x56, 0x4e, 0x23, 0xef, 0x34, 0x22, 0xed, 0x8d, 0x84, 0x7c, 0xd8, 0x42, 0x7b, 0x72, 0x3d, 0x45, 0x1f, 0x23, 0x60, 0x46, 0x1d,
0x60, 0xb4, 0xaf, 0x6d, 0xb9, 0xc3, 0xe3, 0xd4, 0x05, 0xee, 0x24, 0xb7, 0x1e, 0xbe, 0x37, 0x3d, 0x62, 0xc5, 0xe1, 0x6c, 0xd7, 0xc3, 0x43, 0xf4,
0x1c, 0x8b, 0x95, 0xb8, 0x31, 0x0d, 0x6f, 0x51, 0x0b, 0xb8, 0xf0, 0x87, 0xf2, 0x94, 0x5c, 0x25, 0x2d, 0x84, 0x9a, 0x3b, 0x6b, 0x13, 0x61, 0xd6,
0x94, 0xa9, 0x53, 0x30, 0xd1, 0x00, 0x82, 0xb1, 0x04, 0x29, 0x78, 0x43, 0x60, 0x92, 0x39, 0xf0, 0x9a, 0xfe, 0xfb, 0x5c, 0x7c, 0x5e, 0x5e, 0x54,
0xcc, 0x9e, 0xf7, 0x67, 0x1c, 0x15, 0x6b, 0xa4, 0x5d, 0x90, 0xdd, 0x5c, 0x82, 0xef, 0x12, 0xca, 0x0f, 0x42, 0xc7, 0x54, 0x0b, 0xfb, 0x8a, 0xc5,
0xfe, 0x6f, 0xdc, 0x95, 0x09, 0xd9, 0x7c, 0x19, 0xc6, 0x66, 0x8a, 0xff, 0x45, 0x2d, 0x59, 0xd1, 0x82, 0xdd, 0x56, 0xaa, 0x65, 0xf7, 0x37, 0x76,
0x66, 0xc4, 0x4d, 0x70, 0x4b, 0xc8, 0x3f, 0x47, 0xc2, 0xe8, 0xd3, 0xb6, 0xe4, 0x4e, 0xa7, 0xc3, 0x0a, 0x29, 0x69, 0x57, 0xba, 0x64, 0x23, 0xd4,
0x75, 0x74, 0x12, 0x85, 0xf8, 0x42, 0x1d, 0xc9, 0xd0, 0x65, 0x5a, 0x8f, 0xed, 0x49, 0xbb, 0x3d, 0x2e, 0xe5, 0xee, 0x14, 0x95, 0xc1, 0x92, 0xf6,
0xf7, 0xac, 0xe1, 0x07, 0x00, 0x6c, 0x9b, 0xd9, 0xa8, 0x41, 0x96, 0xdc, 0x8b, 0x07, 0x05, 0xb8, 0x16, 0x54, 0x34, 0x29, 0xf9, 0x3e, 0x5a, 0x86,
0x82, 0x93, 0xa2, 0x5f, 0xf8, 0x4b, 0x3c, 0x52, 0xf8, 0x5a, 0x62, 0x0e, 0x01, 0xe0, 0x26, 0xcd, 0x3b, 0x04, 0xa8, 0xe1, 0x00, 0xc9, 0x06, 0x16,
0x51, 0x79, 0xaa, 0xb4, 0x56, 0x44, 0x08, 0x20, 0x17, 0xc1, 0x2f, 0x17, 0xc5, 0x8c, 0xbb, 0xad, 0x8c, 0x28, 0x53, 0x29, 0x1c, 0xde, 0xf1, 0xa3,
0xa1, 0x04, 0x1d, 0x01, 0x7f, 0xe5, 0xa8, 0xb2, 0xea, 0xb6, 0x4b, 0x7b, 0x3e, 0x3b, 0x50, 0x6b, 0x2a, 0x72, 0x5a, 0x5e, 0xd7, 0x9b, 0xf4, 0x16,
0x1f, 0xec, 0x18, 0x2f, 0xc7, 0xa0, 0xb2, 0xb5, 0x25, 0xd0, 0x34, 0x64, 0x89, 0x00, 0x00, 0x85, 0xab, 0x6e, 0x90, 0x31, 0x3f, 0x91, 0x59, 0x35,
0x5c, 0x88, 0x25, 0xe6, 0xc3, 0x79, 0xde, 0x27, 0x8a, 0xab, 0x40, 0x4f, 0x17, 0xba, 0x04, 0xc7, 0x1a, 0xd9, 0x36, 0x92, 0x9c, 0x6a, 0x3c, 0xc8,
0x28, 0x6b, 0x2d, 0x15, 0x86, 0x6c, 0xe4, 0x4d, 0x48, 0x70, 0xbb, 0x09, 0xeb, 0xa9, 0x69, 0xef, 0xff, 0xee, 0xed, 0xbf, 0x82, 0x61, 0xb3, 0x3d,
0x63, 0x70, 0xfb, 0x4c, 0x8c, 0x1d, 0xca, 0xf4, 0x6f, 0x10, 0x36, 0x3b, 0x00, 0x65, 0x0c, 0x40, 0x47, 0x4c, 0xbb, 0x9f, 0x7a, 0x53, 0x72, 0x91,
0x6d, 0x4a, 0xe0, 0xf4, 0x89, 0xeb, 0x53, 0x99, 0x1a, 0x1a, 0xf3, 0xee, 0xc3, 0x93, 0xc7, 0x30, 0x3f, 0x61, 0xb6, 0xab, 0x6f, 0x0a, 0xab, 0xa8,
0xbf, 0x33, 0x69, 0x82, 0xda, 0x12, 0xc8, 0xab, 0x8f, 0x01, 0x84, 0x30, 0x51, 0xf3, 0x12, 0xc5, 0xe2, 0x1c, 0xb7, 0x63, 0xb8, 0x14, 0x33, 0x5f,
0x7b, 0x9a, 0x68, 0x4f, 0x27, 0xf9, 0x40, 0xa0, 0xad, 0x23, 0xf5, 0xf2, 0xf4, 0x78, 0xc4, 0x93, 0x2d, 0xfc, 0xe8, 0xea, 0x5c, 0x00, 0x2a, 0x13,
0x4f, 0x2b, 0x5b, 0x26, 0x39, 0x50, 0xaf, 0x52, 0x33, 0xdd, 0xcd, 0xf3, 0x86, 0x53, 0x8f, 0xc6, 0xfe, 0x87, 0x2e, 0x73, 0xab, 0x34, 0xcb, 0xd4,
0xc8, 0x76, 0x9d, 0x00, 0xd7, 0x98, 0x5b, 0x85, 0x95, 0x75, 0xcd, 0xb0, 0x07, 0xa6, 0xaf, 0xa8, 0xf5, 0x58, 0x2e, 0xc8, 0xd0, 0x50, 0x7c, 0xc2,
0x1e, 0x71, 0x86, 0x86, 0xdb, 0x72, 0xcc, 0x68, 0x78, 0x51, 0x6d, 0xe1, 0x13, 0xdc, 0x6c, 0x89, 0xa6, 0x4a, 0xf5, 0x43, 0xf3, 0x29, 0x31, 0xbe,
0x16, 0xab, 0x8b, 0xdf, 0x52, 0x0a, 0xc1, 0x7d, 0x04, 0x57, 0x39, 0xbb, 0x9a, 0x8d, 0x64, 0x7f, 0xf1, 0x64, 0x9e, 0xfc, 0x12, 0x8b, 0x84, 0x85,
0x5e, 0x93, 0x35, 0xa6, 0x18, 0xcb, 0xbb, 0x1f, 0x37, 0xda, 0xc2, 0x19, 0xa3, 0x6e, 0x31, 0x8a, 0xa5, 0x50, 0xea, 0x70, 0xe1, 0x72, 0x20, 0x35,
0x09, 0x47, 0xa3, 0xc8, 0xbc, 0x23, 0xdf, 0x9c, 0x26, 0x36, 0x1b, 0x5a, 0x1f, 0x5f, 0x33, 0x81, 0xd6, 0xbd, 0x94, 0x84, 0x06, 0x81, 0x80, 0x1a,
0xbd, 0x01, 0x9f, 0x4c, 0x66, 0x79, 0xc1, 0x2f, 0x84, 0x3a, 0xbb, 0x30, 0x68, 0xce, 0xd3, 0x94, 0xec, 0x92, 0xee, 0xd2, 0xe5, 0x28, 0x3f, 0xdd,
0x3f, 0xf1, 0x8d, 0x71, 0x5a, 0x56, 0xe3, 0x88, 0x2c, 0x6e, 0x6f, 0xd7, 0x41, 0x41, 0xa4, 0xa6, 0xcb, 0x38, 0xfd, 0x8e, 0x18, 0xde, 0x7c, 0xd2,
0x9d, 0xec, 0xae, 0xac, 0xce, 0x5b, 0x20, 0x6f, 0x43, 0x06, 0x70, 0x1b, 0x1a, 0x10, 0xfd, 0x1c, 0x24, 0x8a, 0x99, 0xa2, 0x6e, 0xde, 0x2c, 0xfe,
0xd2, 0x49, 0xe7, 0xa3, 0x4b, 0x76, 0x1a, 0xf1, 0xee, 0xee, 0xd3, 0xb5, 0x1c, 0xb1, 0xdc, 0x20, 0xe5, 0x5c, 0x8d, 0x83, 0xa6, 0xf8, 0x12, 0x2e,
0x6c, 0x6a, 0x2e, 0x16, 0x23, 0xed, 0x3c, 0x96, 0x52, 0x9c, 0x51, 0x0f, 0x2d, 0xbe, 0x1b, 0x3d, 0x6a, 0xd2, 0xf5, 0x43, 0xde, 0x7a, 0x5c, 0x07,
0x85, 0x42, 0x89, 0x49, 0xa6, 0x08, 0x82, 0x13, 0xcd, 0xa1, 0xd5, 0x7d, 0x86, 0x51, 0x9b, 0x20, 0x44, 0x59, 0x71, 0x24, 0x72, 0xcc, 0xf0, 0x69,
// Authentication nodes
0x51, 0x4f, 0x87, 0x42, 0xee, 0x41, 0x95, 0x4d, 0x7c, 0x77, 0x36, 0x33, 0x58, 0x8c, 0xaa, 0x8e, 0x24, 0x53, 0xaf, 0x69, 0xdc, 0x0a, 0xd9, 0x62,
0x5b, 0x42, 0xf1, 0x46, 0xcd, 0x85, 0x59, 0x18, 0x85, 0x48, 0xd3, 0x4c, 0xbe, 0xd6, 0xb3, 0x36, 0x3f, 0x1f, 0x2b, 0x30, 0x13, 0x87, 0x2b, 0xd5,
0xcd, 0xb7, 0x6b, 0x19, 0x68, 0x16, 0x91, 0x25, 0xc2, 0x0e, 0xbe, 0xb6, 0xbb, 0x6d, 0xe1, 0x37, 0x4d, 0x4c, 0x0a, 0x80, 0x02, 0x01, 0xdd, 0xfb,
0x0e, 0xb3, 0xaa, 0xf9, 0x83, 0x0d, 0x44, 0x72, 0x64, 0x5b, 0xec, 0xbf, 0xe0, 0x98, 0xd7, 0x4f, 0x09, 0x85, 0xf9, 0x99, 0x88, 0x78, 0xa7, 0xad,
0x6b, 0xce, 0xa3, 0xa0, 0x74, 0x72, 0xe1, 0x3a, 0x39, 0x29, 0x3f, 0x1b, 0xcd, 0xfe, 0x60, 0x54, 0xf5, 0xdb, 0xa3, 0xd6, 0x21, 0xde, 0x8c, 0x6f,
0x33, 0x52, 0x0c, 0xfb, 0x61, 0x60, 0x88, 0xb3, 0x17, 0x8a, 0xe5, 0x4a, 0xaa, 0x5b, 0x64, 0x01, 0x33, 0x57, 0x46, 0x91, 0x61, 0x95, 0x93, 0x08,
0xe8, 0x0d, 0xba, 0xda, 0x0c, 0xeb, 0x96, 0x7b, 0x73, 0xa5, 0x79, 0xe4, 0x0b, 0x93, 0x51, 0x28, 0xa3, 0x44, 0x76, 0x62, 0xe6, 0xbe, 0xca, 0x0e,
0x37, 0x7b, 0xf6, 0xfb, 0xbd, 0x6c, 0xd7, 0x8f, 0xba, 0x75, 0xd5, 0x6b, 0xc1, 0xc2, 0x04, 0xfa, 0xf8, 0xe3, 0x07, 0x10, 0x6f, 0xb4, 0x97, 0xf1,
0xd7, 0xa8, 0x83, 0xa9, 0x9f, 0x20, 0x9c, 0xfc, 0xa7, 0x45, 0x71, 0x36, 0xeb, 0x26, 0xc7, 0x1d, 0x8a, 0x3c, 0x66, 0x78, 0x02, 0xc5, 0x76, 0xa1,
0xd5, 0xc2, 0x15, 0x86, 0x2e, 0x8a, 0x46, 0xde, 0x45, 0xcf, 0xaf, 0xdd, 0xe3, 0xbe, 0xb6, 0x5e, 0x88, 0x1f, 0x9e, 0x63, 0xa6, 0xca, 0x89, 0x8b,
};
VOID
SYMCRYPT_CALL
SymCryptDhSecretAgreementSelftest(void)
@ -847,4 +938,58 @@ SymCryptRsaSelftest(void)
SymCryptRsaSignVerifyTest( pkRsakey );
SymCryptRsakeyFree( pkRsakey );
}
}
VOID
SYMCRYPT_CALL
SymCryptXmssVerifySelftest(void)
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
PSYMCRYPT_XMSS_KEY pKey = NULL;
SYMCRYPT_XMSS_PARAMS params;
PBYTE pbSignature;
SIZE_T cbSignature = sizeof(rgbXmssSha2_10_192Signature);
scError = SymCryptXmssParamsFromAlgId(SYMCRYPT_XMSS_SHA2_10_192, &params);
SYMCRYPT_FIPS_ASSERT(scError == SYMCRYPT_NO_ERROR);
pKey = SymCryptXmsskeyAllocate(&params, 0);
SYMCRYPT_FIPS_ASSERT(pKey != NULL);
scError = SymCryptXmsskeySetValue(
rgbXmssSha2_10_192Pubkey,
sizeof(rgbXmssSha2_10_192Pubkey),
SYMCRYPT_XMSSKEY_TYPE_PUBLIC,
0,
pKey);
// Make a copy of the signature so that we can inject errors in it
pbSignature = SymCryptCallbackAlloc(cbSignature);
SYMCRYPT_FIPS_ASSERT(pbSignature != NULL);
memcpy(pbSignature, rgbXmssSha2_10_192Signature, cbSignature);
SymCryptInjectError(pbSignature, cbSignature);
scError = SymCryptXmssVerify(
pKey,
SymCryptTestMsg3,
sizeof(SymCryptTestMsg3),
0,
pbSignature,
cbSignature);
SYMCRYPT_FIPS_ASSERT(scError == SYMCRYPT_NO_ERROR);
SymCryptWipe(pbSignature, cbSignature);
SymCryptCallbackFree(pbSignature);
SymCryptXmsskeyFree(pKey);
}
VOID
SYMCRYPT_CALL
SymCryptXmssSelftest(void)
{
// Perform only signature verification self-test
SymCryptXmssVerifySelftest();
}

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

@ -1877,6 +1877,7 @@ SymCryptCShakeEncodeInputStrings(
// Appends byte_pad( encode_string( pbFunctionNameString ) || encode_string( pbCustomizationString ), pState->inputBlockSize )
VOID
SYMCRYPT_CALL
SymCryptFatalIntercept( UINT32 fatalCode );
@ -4285,6 +4286,217 @@ SymCryptPositiveWidthNafRecoding(
PUINT32 absofKIs,
UINT32 nRecodedDigits );
//
// XMSS
//
//
// ADRS structure definitions as specified in RFC 8391
//
typedef enum _XMSS_ADRS_TYPE
{
XMSS_ADRS_TYPE_OTS = 0,
XMSS_ADRS_TYPE_LTREE = 1,
XMSS_ADRS_TYPE_HASH_TREE = 2,
} XMSS_ADRS_TYPE;
typedef struct _XMSS_OTS_ADDRESS
{
BYTE en32Leaf[4];
BYTE en32Chain[4];
BYTE en32Hash[4];
} XMSS_OTS_ADDRESS, *PXMSS_OTS_ADDRESS;
typedef struct _XMSS_LTREE_ADDRESS
{
BYTE en32Leaf[4];
BYTE en32Height[4];
BYTE en32Index[4];
} XMSS_LTREE_ADDRESS, * PXMSS_LTREE_ADDRESS;
typedef struct _XMSS_HASHTREE_ADDRESS
{
BYTE padding[4];
BYTE en32Height[4];
BYTE en32Index[4];
} XMSS_HASHTREE_ADDRESS, * PXMSS_HASHTREE_ADDRESS;
typedef struct _XMSS_ADRS
{
BYTE en32Layer[4];
BYTE en64Tree[8];
BYTE en32Type[4];
union {
XMSS_OTS_ADDRESS ots;
XMSS_LTREE_ADDRESS ltree;
XMSS_HASHTREE_ADDRESS hashtree;
} u;
BYTE en32KeyAndMask[4];
} XMSS_ADRS, *PXMSS_ADRS;
typedef SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_XMSS_KEY
{
UINT32 version;
SYMCRYPT_XMSS_PARAMS params;
SYMCRYPT_XMSSKEY_TYPE keyType;
// Public key
BYTE Root[SYMCRYPT_HASH_MAX_RESULT_SIZE];
BYTE Seed[SYMCRYPT_HASH_MAX_RESULT_SIZE];
SYMCRYPT_MAGIC_FIELD
// Private key
SYMCRYPT_ALIGN_AT(16) UINT64 Idx; // Aligning on 16-bytes to supress clang warning
// when atomic increment is performed on it.
BYTE SkXmss[SYMCRYPT_HASH_MAX_RESULT_SIZE];
BYTE SkPrf[SYMCRYPT_HASH_MAX_RESULT_SIZE];
} SYMCRYPT_XMSS_KEY;
typedef SYMCRYPT_XMSS_KEY* PSYMCRYPT_XMSS_KEY;
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmssComputePublicRoot(
_In_ PCSYMCRYPT_XMSS_PARAMS pParams,
_In_reads_bytes_( cbSeed ) PCBYTE pbSeed,
SIZE_T cbSeed,
_In_reads_bytes_( cbSkXmss ) PCBYTE pbSkXmss,
SIZE_T cbSkXmss,
_Out_writes_bytes_( cbRoot ) PBYTE pbRoot,
SIZE_T cbRoot );
//
// Compute public root value from SEED and SK_XMSS
//
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptXmsskeyVerifyRoot(
_In_ PCSYMCRYPT_XMSS_KEY pKey );
//
// Verifies that the public root matches the private key by recomputing it
//
VOID
SYMCRYPT_CALL
SymCryptHbsGetWinternitzLengths(
UINT32 n, // data size in bytes
UINT32 w, // digit length in bits (Winternitz coefficient)
_Out_ PUINT32 puLen1, // number of w-bit digits in n
_Out_ PUINT32 puLen2 // number of w-bit digits to store the checksum len1 * (2^w - 1)
);
typedef struct _SYMCRYPT_TREEHASH_NODE
{
UINT32 index;
UINT32 height;
BYTE value[SYMCRYPT_ANYSIZE_ARRAY];
} SYMCRYPT_TREEHASH_NODE, * PSYMCRYPT_TREEHASH_NODE;
#define SYMCRYPT_SIZEOF_TREEHASH_NODE(cbValue) (sizeof(SYMCRYPT_TREEHASH_NODE) - 1 + (cbValue))
#define SYMCRYPT_TREEHASH_NODE_GET(aNodes, cbValue, i) ((PSYMCRYPT_TREEHASH_NODE)((PBYTE)(aNodes) + (i) * SYMCRYPT_SIZEOF_TREEHASH_NODE(cbValue)))
typedef struct _SYMCRYPT_XMSS_INCREMENTAL_TREEHASH_CONTEXT
{
PCSYMCRYPT_XMSS_PARAMS pParams;
PCBYTE pbSeed;
XMSS_ADRS adrs;
} SYMCRYPT_XMSS_INCREMENTAL_TREEHASH_CONTEXT, * PSYMCRYPT_XMSS_INCREMENTAL_TREEHASH_CONTEXT;
typedef
VOID
(SYMCRYPT_CALL *PSYMCRYPT_INCREMENTAL_TREEHASH_FUNC)(
_In_ PSYMCRYPT_TREEHASH_NODE pNodeLeft,
_In_ PSYMCRYPT_TREEHASH_NODE pNodeRight,
_Out_ PSYMCRYPT_TREEHASH_NODE pNodeOut,
_Inout_ PSYMCRYPT_XMSS_INCREMENTAL_TREEHASH_CONTEXT pContext );
typedef struct _SYMCRYPT_INCREMENTAL_TREEHASH
{
UINT32 cbNode; // node size; height + hash result
UINT32 nSize; // current size of the stack
UINT32 nCapacity; // maximum items
UINT32 nLastLeafIndex;
PSYMCRYPT_INCREMENTAL_TREEHASH_FUNC funcCompressNodes;
PSYMCRYPT_XMSS_INCREMENTAL_TREEHASH_CONTEXT pContext;
SYMCRYPT_TREEHASH_NODE arrNodes[SYMCRYPT_ANYSIZE_ARRAY];
} SYMCRYPT_INCREMENTAL_TREEHASH, *PSYMCRYPT_INCREMENTAL_TREEHASH;
PSYMCRYPT_INCREMENTAL_TREEHASH
SYMCRYPT_CALL
SymCryptHbsIncrementalTreehashInit(
UINT32 nLeaves,
PBYTE pbBuffer,
SIZE_T cbBuffer,
UINT32 cbHashResult,
PSYMCRYPT_INCREMENTAL_TREEHASH_FUNC funcCompressNodes,
PSYMCRYPT_XMSS_INCREMENTAL_TREEHASH_CONTEXT pContext);
PSYMCRYPT_TREEHASH_NODE
SYMCRYPT_CALL
SymCryptHbsIncrementalTreehashGetNode(
_In_ PSYMCRYPT_INCREMENTAL_TREEHASH pIncHash,
SIZE_T index );
PSYMCRYPT_TREEHASH_NODE
SYMCRYPT_CALL
SymCryptHbsIncrementalTreehashAllocNode(
_Inout_ PSYMCRYPT_INCREMENTAL_TREEHASH pIncHash,
UINT32 nLeafIndex );
VOID
SYMCRYPT_CALL
SymCryptHbsIncrementalTreehashGetTopNodes(
_Inout_ PSYMCRYPT_INCREMENTAL_TREEHASH pIncHash,
_Out_ PSYMCRYPT_TREEHASH_NODE *ppNodeLeft,
_Out_ PSYMCRYPT_TREEHASH_NODE *ppNodeRight );
PSYMCRYPT_TREEHASH_NODE
SYMCRYPT_CALL
SymCryptHbsIncrementalTreehashProcessCommon(
_Inout_ PSYMCRYPT_INCREMENTAL_TREEHASH pIncHash,
BOOLEAN fFinal );
PSYMCRYPT_TREEHASH_NODE
SYMCRYPT_CALL
SymCryptHbsIncrementalTreehashProcess(
_Inout_ PSYMCRYPT_INCREMENTAL_TREEHASH pIncHash);
PSYMCRYPT_TREEHASH_NODE
SYMCRYPT_CALL
SymCryptHbsIncrementalTreehashFinalize(
_Inout_ PSYMCRYPT_INCREMENTAL_TREEHASH pIncHash);
UINT32
SYMCRYPT_CALL
SymCryptHbsIncrementalTreehashStackDepth(
UINT32 nLeaves);
SIZE_T
SYMCRYPT_CALL
SymCryptHbsSizeofScratchBytesForIncrementalTreehash(
UINT32 cbNode,
UINT32 nLeaves);
// Atomics.
//
// We define all our SymCrypt atomics below. Different compilers/environments have different
@ -4499,4 +4711,31 @@ SymCryptCountTrailingZeros32( UINT32 value )
#endif
return (UINT32) index;
}
}
FORCEINLINE
UINT32
SymCryptCountLeadingZeros32( UINT32 value )
{
ULONG zeros = 0;
if(value == 0)
{
return 32;
}
#if SYMCRYPT_MS_VC && (SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_ARM64 | SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_ARM)
_BitScanReverse(&zeros, value);
zeros = 31 - zeros;
#elif SYMCRYPT_GNUC
zeros = __builtin_clz(value);
#else
while( (value & 0x80000000) == 0 )
{
zeros++;
value <<= 1;
}
#endif
return (UINT32)zeros;
}

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

@ -146,6 +146,7 @@
<ClCompile Include="tlsCbcVerify.c" />
<ClCompile Include="tlsprf.c" />
<ClCompile Include="tlsprf_selftest.c" />
<ClCompile Include="xmss.c" />
<ClCompile Include="xtsaes.c" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)'=='x64'">
@ -180,7 +181,6 @@
<Message Importance="high" Text="Generating build info header" />
<Exec Command="python ..\scripts\version.py --build-info" />
</Target>
<Target Name="GetDriverProjectAttributes" Returns="@(DriverProjectAttributes)" />
<Target Name="GetPackageFiles" Returns="@(FullyQualifiedFilesToPackage)" />
</Project>

2099
lib/xmss.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -559,4 +559,17 @@ VERSION_103.4
SymCryptSskdfMac;
SymCryptSskdfHash;
SymCryptSskdfSelfTest;
SymCryptXmsskeyAllocate;
SymCryptXmsskeyFree;
SymCryptXmsskeyGenerate;
SymCryptXmsskeyGetValue;
SymCryptXmsskeySetValue;
SymCryptXmssSizeofKeyBlobFromParams;
SymCryptXmssMtParamsFromAlgId;
SymCryptXmssParamsFromAlgId;
SymCryptXmssSetParams;
SymCryptXmssSign;
SymCryptXmssSizeofSignatureFromParams;
SymCryptXmssVerify;
SymCryptXmssSelftest;
} VERSION_103.2;

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

@ -524,6 +524,19 @@ EXPORTS
; SymCryptXtsAesExpandKeyEx
; SymCryptXtsAesKeyCopy
; SymCryptXtsAesSelftest
; SymCryptXmsskeyAllocate
; SymCryptXmsskeyFree
; SymCryptXmsskeyGenerate
; SymCryptXmsskeyGetValue
; SymCryptXmsskeySetValue
; SymCryptXmssSizeofKeyBlobFromParams
; SymCryptXmssMtParamsFromAlgId
; SymCryptXmssParamsFromAlgId
; SymCryptXmssSetParams
; SymCryptXmssSign
; SymCryptXmssSizeofSignatureFromParams
; SymCryptXmssVerify
; SymCryptXmssSelftest
SymCryptDeprecatedStatusIndicator
SymCryptEntropyAccumulatorInit0

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

@ -527,3 +527,17 @@ EXPORTS
SymCryptXtsAesExpandKeyEx
SymCryptXtsAesKeyCopy
SymCryptXtsAesSelftest
SymCryptXmsskeyAllocate
SymCryptXmsskeyFree
SymCryptXmsskeyGenerate
SymCryptXmsskeyGetValue
SymCryptXmsskeySetValue
SymCryptXmssSizeofKeyBlobFromParams
SymCryptXmssMtParamsFromAlgId
SymCryptXmssParamsFromAlgId
SymCryptXmssSetParams
SymCryptXmssSign
SymCryptXmssSizeofSignatureFromParams
SymCryptXmssVerify
SymCryptXmssSelftest

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

@ -520,3 +520,16 @@ FUNCTION(SymCryptPaddingPkcs7Add)
FUNCTION(SymCryptPaddingPkcs7Remove)
FUNCTION(SymCryptFipsGetSelftestsPerformed)
FUNCTION(SymCryptDeprecatedStatusIndicator)
FUNCTION(SymCryptXmsskeyAllocate)
FUNCTION(SymCryptXmsskeyFree)
FUNCTION(SymCryptXmsskeyGenerate)
FUNCTION(SymCryptXmsskeyGetValue)
FUNCTION(SymCryptXmsskeySetValue)
FUNCTION(SymCryptXmssSizeofKeyBlobFromParams)
FUNCTION(SymCryptXmssMtParamsFromAlgId)
FUNCTION(SymCryptXmssParamsFromAlgId)
FUNCTION(SymCryptXmssSetParams)
FUNCTION(SymCryptXmssSign)
FUNCTION(SymCryptXmssSizeofSignatureFromParams)
FUNCTION(SymCryptXmssVerify)
FUNCTION(SymCryptXmssSelftest)

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

@ -1681,6 +1681,98 @@ public:
};
// Hash-Based Signatures
class HbsImplementation : public AlgorithmImplementation
{
public:
HbsImplementation() {};
virtual ~HbsImplementation() {};
private:
HbsImplementation(const HbsImplementation&);
VOID operator=(const HbsImplementation&);
public:
virtual NTSTATUS setKey(
UINT32 uAlgId,
BOOL fMultitree,
_In_reads_bytes_(cbSrc) PCBYTE pbSrc,
SIZE_T cbSrc,
BOOL fVerify ) = 0;
// Set an XMSS key from algorithm identifier and key blob.
//
// If fVerify is TRUE then this function computes the public root
// from the private key -only if the key is private- and compares
// it to the public root that is in the private key.
virtual NTSTATUS sign(
_In_reads_bytes_(cbMsg) PCBYTE pbMsg,
SIZE_T cbMsg,
_Out_writes_bytes_(cbSignature) PBYTE pbSignature,
SIZE_T cbSignature ) = 0;
// Sign a message using the private key initialized by setKey()
virtual NTSTATUS verify(
_In_reads_bytes_(cbMsg) PCBYTE pbMsg,
SIZE_T cbMsg,
_In_reads_bytes_(cbSignature) PCBYTE pbSignature,
SIZE_T cbSignature ) = 0;
// Verify a signature on a message using the private key initialized
// by setKey()
};
//
// A template class to store the state of an XMSS implementation in.
//
template<class Implementation, class Algorithm> class XmssImpState;
//
// Template class for the actual XMSS implementations
//
template< class Implementation, class Algorithm >
class XmssImp : public HbsImplementation
{
public:
XmssImp();
virtual ~XmssImp();
private:
XmssImp(const XmssImp&);
VOID operator=(const XmssImp&);
public:
virtual NTSTATUS setKey(
UINT32 uAlgId,
BOOL fMultitree,
_In_reads_bytes_(cbSrc) PCBYTE pbSrc,
SIZE_T cbSrc,
BOOL fVerify );
virtual NTSTATUS sign(
_In_reads_bytes_(cbMsg) PCBYTE pbMsg,
SIZE_T cbMsg,
_Out_writes_bytes_(cbSignature) PBYTE pbSignature,
SIZE_T cbSignature ) ;
virtual NTSTATUS verify(
_In_reads_bytes_(cbMsg) PCBYTE pbMsg,
SIZE_T cbMsg,
_In_reads_bytes_(cbSignature) PCBYTE pbSignature,
SIZE_T cbSignature );
static const String s_algName;
static const String s_modeName;
static const String s_impName;
XmssImpState<Implementation, Algorithm> state;
};
//
// The stub classes we use to distinguish our implementations and algorithms contain the
// name of said implementation/algorithm. We use this to auto-define the algorithm name
@ -1855,6 +1947,15 @@ const String DsaImp<Imp,Alg>::s_algName = Alg::name;
template< class Imp, class Alg>
const String DsaImp<Imp,Alg>::s_modeName;
template< class Implementation, class Algorithm >
const String XmssImp<Implementation,Algorithm>::s_algName = Algorithm::name;
template< class Implementation, class Algorithm >
const String XmssImp<Implementation,Algorithm>::s_modeName;
template< class Implementation, class Algorithm >
const String XmssImp<Implementation,Algorithm>::s_impName = Implementation::name;
//
// Template declaration for performance functions (for those implementations that wish to use them)
//

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

@ -571,6 +571,19 @@
#define ScDispatchSymCryptDeprecatedStatusIndicator(...) SCTEST_CALL_DISPATCHFN(SymCryptDeprecatedStatusIndicator, __VA_ARGS__)
#define ScDispatchSymCryptXmsskeyAllocate(...) SCTEST_CALL_DISPATCHFN(SymCryptXmsskeyAllocate, __VA_ARGS__)
#define ScDispatchSymCryptXmsskeyFree(...) SCTEST_CALL_DISPATCHFN(SymCryptXmsskeyFree, __VA_ARGS__)
#define ScDispatchSymCryptXmsskeyGenerate(...) SCTEST_CALL_DISPATCHFN(SymCryptXmsskeyGenerate, __VA_ARGS__)
#define ScDispatchSymCryptXmsskeyGetValue(...) SCTEST_CALL_DISPATCHFN(SymCryptXmsskeyGetValue, __VA_ARGS__)
#define ScDispatchSymCryptXmsskeySetValue(...) SCTEST_CALL_DISPATCHFN(SymCryptXmsskeySetValue, __VA_ARGS__)
#define ScDispatchSymCryptXmssSizeofKeyBlobFromParams(...) SCTEST_CALL_DISPATCHFN(SymCryptXmssSizeofKeyBlobFromParams, __VA_ARGS__)
#define ScDispatchSymCryptXmssMtParamsFromAlgId(...) SCTEST_CALL_DISPATCHFN(SymCryptXmssMtParamsFromAlgId, __VA_ARGS__)
#define ScDispatchSymCryptXmssParamsFromAlgId(...) SCTEST_CALL_DISPATCHFN(SymCryptXmssParamsFromAlgId, __VA_ARGS__)
#define ScDispatchSymCryptXmssSetParams(...) SCTEST_CALL_DISPATCHFN(SymCryptXmssSetParams, __VA_ARGS__)
#define ScDispatchSymCryptXmssSign(...) SCTEST_CALL_DISPATCHFN(SymCryptXmssSign, __VA_ARGS__)
#define ScDispatchSymCryptXmssSizeofSignatureFromParams(...) SCTEST_CALL_DISPATCHFN(SymCryptXmssSizeofSignatureFromParams, __VA_ARGS__)
#define ScDispatchSymCryptXmssVerify(...) SCTEST_CALL_DISPATCHFN(SymCryptXmssVerify, __VA_ARGS__)
#define ScDispatchSymCryptXmssSelftest(...) SCTEST_CALL_DISPATCHFN(SymCryptXmssSelftest, __VA_ARGS__)
#define ScDispatchSymCryptMarvin32DefaultSeed SCTEST_GET_DISPATCHSYM(SymCryptMarvin32DefaultSeed)
#define ScDispatchSymCryptMd2Algorithm SCTEST_GET_DISPATCHSYM(SymCryptMd2Algorithm)

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

@ -558,6 +558,19 @@
#define ScShimSymCryptDeprecatedStatusIndicator(...) SCTEST_CALL_SCIMPFN(SymCryptDeprecatedStatusIndicator, __VA_ARGS__)
#define ScShimSymCryptXmsskeyAllocate(...) SCTEST_CALL_SCIMPFN(SymCryptXmsskeyAllocate, __VA_ARGS__)
#define ScShimSymCryptXmsskeyFree(...) SCTEST_CALL_SCIMPFN(SymCryptXmsskeyFree, __VA_ARGS__)
#define ScShimSymCryptXmsskeyGenerate(...) SCTEST_CALL_SCIMPFN(SymCryptXmsskeyGenerate, __VA_ARGS__)
#define ScShimSymCryptXmsskeyGetValue(...) SCTEST_CALL_SCIMPFN(SymCryptXmsskeyGetValue, __VA_ARGS__)
#define ScShimSymCryptXmsskeySetValue(...) SCTEST_CALL_SCIMPFN(SymCryptXmsskeySetValue, __VA_ARGS__)
#define ScShimSymCryptXmssSizeofKeyBlobFromParams(...) SCTEST_CALL_SCIMPFN(SymCryptXmssSizeofKeyBlobFromParams, __VA_ARGS__)
#define ScShimSymCryptXmssMtParamsFromAlgId(...) SCTEST_CALL_SCIMPFN(SymCryptXmssMtParamsFromAlgId, __VA_ARGS__)
#define ScShimSymCryptXmssParamsFromAlgId(...) SCTEST_CALL_SCIMPFN(SymCryptXmssParamsFromAlgId, __VA_ARGS__)
#define ScShimSymCryptXmssSetParams(...) SCTEST_CALL_SCIMPFN(SymCryptXmssSetParams, __VA_ARGS__)
#define ScShimSymCryptXmssSign(...) SCTEST_CALL_SCIMPFN(SymCryptXmssSign, __VA_ARGS__)
#define ScShimSymCryptXmssSizeofSignatureFromParams(...) SCTEST_CALL_SCIMPFN(SymCryptXmssSizeofSignatureFromParams, __VA_ARGS__)
#define ScShimSymCryptXmssVerify(...) SCTEST_CALL_SCIMPFN(SymCryptXmssVerify, __VA_ARGS__)
#define ScShimSymCryptXmssSelftest(...) SCTEST_CALL_SCIMPFN(SymCryptXmssSelftest, __VA_ARGS__)
#define ScShimSymCryptMarvin32DefaultSeed SCTEST_GET_SCIMPSYM(SymCryptMarvin32DefaultSeed)
#define ScShimSymCryptMd2Algorithm SCTEST_GET_SCIMPSYM(SymCryptMd2Algorithm)

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

@ -418,3 +418,9 @@ public:
PSYMCRYPT_DLGROUP pGroup;
PSYMCRYPT_DLKEY pKey;
};
template<>
class XmssImpState<ImpXxx, AlgXmss> {
public:
PSYMCRYPT_XMSS_KEY pKey;
};

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

@ -76,7 +76,7 @@ const SELFTEST_INFO g_selfTests[] =
{&SymCryptSshKdfSha256SelfTest, "SshKdfSha256" },
{&SymCryptSshKdfSha512SelfTest, "SshKdfSha512" },
{&SymCryptSskdfSelfTest, "Sskdf" },
{&SymCryptXmssSelftest, "Xmss" },
{NULL, NULL},
};

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

@ -946,6 +946,11 @@ public:
const static char * name;
};
class AlgXmss {
public:
const static char * name;
};
class AlgDeveloperTest{
public:
const static char * name;
@ -1398,6 +1403,9 @@ testDsaAlgorithms();
VOID
testStatusIndicator(BOOL);
VOID
testHbs();
KatData *
getCustomResource( _In_ PSTR resourceName, _In_ PSTR resourceType );
@ -1847,6 +1855,17 @@ printXmmRegisters( PCSTR text );
#define PERF_KEY_W22519 ( PERF_KEY_SW_TEST_CURVE | 32 )
#define PERF_KEY_W448 ( PERF_KEY_SW_TEST_CURVE | 56 )
#define PERF_KEY_XMSS_SHA2_10_256 (SYMCRYPT_XMSS_SHA2_10_256)
#define PERF_KEY_XMSS_SHA2_16_256 (SYMCRYPT_XMSS_SHA2_16_256)
#define PERF_KEY_XMSS_SHA2_20_256 (SYMCRYPT_XMSS_SHA2_20_256)
#define PERF_KEY_XMSS_SHA2_10_512 (SYMCRYPT_XMSS_SHA2_10_512)
#define PERF_KEY_XMSS_SHA2_16_512 (SYMCRYPT_XMSS_SHA2_16_512)
#define PERF_KEY_XMSS_SHA2_20_512 (SYMCRYPT_XMSS_SHA2_20_512)
#define PERF_KEY_XMSS_SHAKE256_10_256 (SYMCRYPT_XMSS_SHAKE256_10_256)
#define PERF_KEY_XMSS_SHAKE256_16_256 (SYMCRYPT_XMSS_SHAKE256_16_256)
#define PERF_KEY_XMSS_SHAKE256_20_256 (SYMCRYPT_XMSS_SHAKE256_20_256)
PCBYTE
getPerfTestModulus( UINT32 exKeySize );

27812
unittest/kat_hbs.dat Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -37,6 +37,7 @@ set(SOURCES
perf.cpp
testPaddingPkcs7.cpp
testStatusIndicator.cpp
testHbs.cpp
)
# Append Windows-specific sources

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

@ -246,6 +246,8 @@ const char * AlgEcdsaVerify::name = "EcdsaVerify";
const char * AlgEcdh::name = "Ecdh";
const char * AlgXmss::name = "Xmss";
const char * AlgDeveloperTest::name = "DeveloperTest";
const char * ModeEcb::name = "Ecb";
@ -613,6 +615,7 @@ const char * g_algorithmNames[] = {
AlgEcdsaSign::name,
AlgEcdsaVerify::name,
AlgEcdh::name,
AlgXmss::name,
AlgDeveloperTest::name,
NULL,
@ -1533,6 +1536,8 @@ runFunctionalTests()
testEcc();
testHbs();
printSymCryptFipsGetSelftestsPerformed();
testStatusIndicator(g_printStatusIndicator);

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

@ -276,6 +276,7 @@ const ALG_MEASURE_PARAMS g_algMeasureParams[] =
"EcdsaVerify" , 1, {PERF_KEY_NIST192, PERF_KEY_NIST224, PERF_KEY_NIST256, PERF_KEY_NIST384, PERF_KEY_NIST521, PERF_KEY_NUMS256, PERF_KEY_NUMS384, PERF_KEY_NUMS512, PERF_KEY_W22519, PERF_KEY_W448,}, {},
"Ecdh" , 1, {PERF_KEY_NIST192, PERF_KEY_NIST224, PERF_KEY_NIST256, PERF_KEY_NIST384, PERF_KEY_NIST521, PERF_KEY_NUMS256, PERF_KEY_NUMS384, PERF_KEY_NUMS512, PERF_KEY_W22519, PERF_KEY_W448, PERF_KEY_C255_19,}, {},
"IEEE802_11SaeCustom" , 0, {}, {},
"Xmss" , 1, { PERF_KEY_XMSS_SHA2_10_256, PERF_KEY_XMSS_SHA2_16_256, PERF_KEY_XMSS_SHA2_20_256, PERF_KEY_XMSS_SHA2_10_512, PERF_KEY_XMSS_SHAKE256_10_256 }, { PERF_DATASIZE_SAME_AS_KEYSIZE },
// Enable the line below if you are running perf on the developer test
// "DeveloperTest" , 1, {1},{},
@ -998,6 +999,23 @@ const struct {
{ PERF_KEY_XTS_DATA_UNIT_4096, " 4k" },
};
const struct {
UINT32 algId;
BOOL bMultitree;
char* name;
} g_XmssIdNameMappings[] = {
{ SYMCRYPT_XMSS_SHA2_10_256, FALSE, "SHA2_10_256" },
{ SYMCRYPT_XMSS_SHA2_16_256, FALSE, "SHA2_16_256" },
{ SYMCRYPT_XMSS_SHA2_20_256, FALSE, "SHA2_20_256" },
{ SYMCRYPT_XMSS_SHA2_10_512, FALSE, "SHA2_10_512" },
{ SYMCRYPT_XMSS_SHA2_16_512, FALSE, "SHA2_16_512" },
{ SYMCRYPT_XMSS_SHA2_20_512, FALSE, "SHA2_20_512" },
{ SYMCRYPT_XMSS_SHAKE256_10_256, FALSE, "SHAKE256_10_256" },
{ SYMCRYPT_XMSS_SHAKE256_16_256, FALSE, "SHAKE256_16_256" },
{ SYMCRYPT_XMSS_SHAKE256_20_256, FALSE, "SHAKE256_20_256" },
};
VOID measurePerfOneAlg( AlgorithmImplementation * pAlgImp )
{
PerfDataFn dataFn = pAlgImp->m_perfDataFunction;
@ -1063,15 +1081,27 @@ VOID measurePerfOneAlg( AlgorithmImplementation * pAlgImp )
perfInfo.strPostfix = "";
for( SIZE_T i=0; i < ARRAY_SIZE( g_exKeyParamMapping ); i++ )
for (SIZE_T i = 0; i < ARRAY_SIZE(g_exKeyParamMapping); i++)
{
if( keyFlags == g_exKeyParamMapping[i].exKeyParam )
if (keyFlags == g_exKeyParamMapping[i].exKeyParam)
{
perfInfo.strPostfix = g_exKeyParamMapping[i].str;
break;
}
}
if (STRICMP(pParams->algName, "Xmss") == 0)
{
for (SIZE_T i = 0; i < ARRAY_SIZE(g_XmssIdNameMappings); i++)
{
if (*k == g_XmssIdNameMappings[i].algId)
{
perfInfo.strPostfix = g_XmssIdNameMappings[i].name;
break;
}
}
}
if( dataFn != NULL )
{
perfInfo.operationName = "";

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -90,6 +90,11 @@ template<class Implementation>
void
SetupSymCryptEckey( PBYTE buf1, PBYTE buf2, PBYTE buf3, UINT32 setRandomFlags );
template<class Implementation>
void
SetupSymCryptXmsskey( UINT32 algId );
VOID
trialDivisionSetFakePrime( PSYMCRYPT_TRIALDIVISION_PRIME p )
{
@ -345,6 +350,8 @@ addSymCryptImplementationToGlobalList()
addImplementationToGlobalList<EccImp<ImpScVariant, AlgEcdsaVerify>>();
addImplementationToGlobalList<EccImp<ImpScVariant, AlgEcdh>>();
addImplementationToGlobalList<XmssImp<ImpScVariant, AlgXmss>>();
#if SYMCRYPT_MS_VC
addImplementationToGlobalList<ArithImp<ImpScVariant, AlgIEEE802_11SaeCustom>>();
#endif

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

@ -90,6 +90,7 @@ const SELFTEST_INFO g_selfTests_allocating[] =
{&SymCryptDsaSelftest, "DSA" },
{&SymCryptEcDsaSelftest, "ECDSA" },
{&SymCryptRsaSelftest, "RSA" },
{&SymCryptXmssSelftest, "Xmss" },
{NULL, NULL},
};

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

@ -73,6 +73,7 @@
<ClCompile Include="testXof.cpp" />
<ClCompile Include="testXts.cpp" />
<ClCompile Include="testStatusIndicator.cpp" />
<ClCompile Include="testHbs.cpp" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)'=='x64'">
<MASM Include="amd64\savevectors.asm" />

726
unittest/lib/testHbs.cpp Normal file
Просмотреть файл

@ -0,0 +1,726 @@
//
// Test Hash-based Signatures
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "precomp.h"
extern
"C"
{
VOID
SYMCRYPT_CALL
SymCryptHbsGetWinternitzLengths(
UINT32 n, // blob size in bytes
UINT32 w, // digit length in bits (Winternitz coefficient)
_Out_ PUINT32 puLen1, // number of w-bit digits in n
_Out_ PUINT32 puLen2 // number of w-bit digits to store the checksum <= len1 * (2^w - 1)
);
UINT32
SymCryptCountLeadingZeros32( UINT32 value );
}
typedef struct _SYMCRYPT_WINTERNITZ_LENGTHS
{
UINT32 n;
UINT32 w;
UINT32 len1;
UINT32 len2;
} SYMCRYPT_WINTERNITZ_LENGTHS, * PSYMCRYPT_WINTERNITZ_LENGTHS;
//
// Precomputed digit counts in Excel
//
// len1 = CEILING.MATH(8 * n / w)
// len2 = FLOOR.MATH(LOG(len1 * (POWER(2, w) - 1), 2) / w) + 1
//
static const SYMCRYPT_WINTERNITZ_LENGTHS _SymCryptWinternitzLengths[] = {
// n w len1 len2
{ 24, 1, 192, 8 },
{ 24, 2, 96, 5 },
{ 24, 3, 64, 3 },
{ 24, 4, 48, 3 },
{ 24, 5, 39, 3 },
{ 24, 6, 32, 2 },
{ 24, 7, 28, 2 },
{ 24, 8, 24, 2 },
{ 32, 1, 256, 9 },
{ 32, 2, 128, 5 },
{ 32, 3, 86, 4 },
{ 32, 4, 64, 3 },
{ 32, 5, 52, 3 },
{ 32, 6, 43, 2 },
{ 32, 7, 37, 2 },
{ 32, 8, 32, 2 },
{ 64, 1, 512, 10 },
{ 64, 2, 256, 5 },
{ 64, 3, 171, 4 },
{ 64, 4, 128, 3 },
{ 64, 5, 103, 3 },
{ 64, 6, 86, 3 },
{ 64, 7, 74, 2 },
{ 64, 8, 64, 2 },
};
VOID
testWinternitzLengths()
{
for (UINT32 i = 0; i < sizeof(_SymCryptWinternitzLengths) / sizeof(_SymCryptWinternitzLengths[0]); i++)
{
UINT32 len1, len2;
SymCryptHbsGetWinternitzLengths(
_SymCryptWinternitzLengths[i].n,
_SymCryptWinternitzLengths[i].w,
&len1,
&len2);
CHECK4( len1 == _SymCryptWinternitzLengths[i].len1,
"Incorrect Winternitz digit count for len1: expecting %d got %d",
_SymCryptWinternitzLengths[i].len1,
len1);
CHECK4( len2 == _SymCryptWinternitzLengths[i].len2,
"Incorrect Winternitz digit count for len2: expecting %d got %d",
_SymCryptWinternitzLengths[i].len2,
len2);
}
}
class HbsMultiImp : public HbsImplementation
{
public:
HbsMultiImp( String algName );
virtual ~HbsMultiImp();
private:
HbsMultiImp(const HbsMultiImp&);
VOID operator=(const HbsMultiImp&);
public:
typedef std::vector<HbsImplementation*> HbsImpPtrVector;
HbsImpPtrVector m_imps; // Implementations we use
HbsImpPtrVector m_comps; // Subset of m_imps; set of ongoing computations
VOID addImplementation(HbsImplementation* pImp );
VOID setImpName();
virtual NTSTATUS setKey(UINT32, BOOL, PCBYTE, SIZE_T, BOOL);
virtual NTSTATUS sign(PCBYTE, SIZE_T, PBYTE, SIZE_T);
virtual NTSTATUS verify(PCBYTE, SIZE_T, PCBYTE, SIZE_T);
};
VOID
HbsMultiImp::setImpName()
{
String sumAlgName;
char* sepStr = "<";
for (HbsImpPtrVector::const_iterator i = m_imps.begin(); i != m_imps.end(); ++i)
{
sumAlgName += sepStr + (*i)->m_algorithmName;
sepStr = "+";
}
m_implementationName = sumAlgName + ">";
}
HbsMultiImp::HbsMultiImp(String algName)
{
m_algorithmName = algName;
getAllImplementations<HbsImplementation>(algName, &m_imps);
}
VOID
HbsMultiImp::addImplementation(HbsImplementation* pImp)
{
m_imps.push_back(pImp);
setImpName();
}
HbsMultiImp::~HbsMultiImp()
{
//
// Propagate the # KAT failures to the individual algorithms.
//
for (HbsImpPtrVector::iterator i = m_imps.begin(); i != m_imps.end(); ++i)
{
(*i)->m_nErrorKatFailure += m_nErrorKatFailure;
}
}
NTSTATUS
HbsMultiImp::setKey(
UINT32 uAlgId,
BOOL fMultitree,
PCBYTE pbSrc,
SIZE_T cbSrc,
BOOL fVerify )
{
m_comps.clear();
for (HbsImpPtrVector::const_iterator i = m_imps.begin(); i != m_imps.end(); ++i)
{
if ((*i)->setKey(uAlgId, fMultitree, pbSrc, cbSrc, fVerify) == STATUS_SUCCESS)
{
m_comps.push_back(*i);
}
}
return m_comps.size() == 0 ? STATUS_NOT_SUPPORTED : STATUS_SUCCESS;
}
NTSTATUS
HbsMultiImp::sign(
PCBYTE pbMsg,
SIZE_T cbMsg,
PBYTE pbSignature,
SIZE_T cbSignature )
{
NTSTATUS status = STATUS_SUCCESS;
ResultMerge res;
PBYTE pbBuffer = NULL;
pbBuffer = new BYTE[cbSignature];
CHECK(pbBuffer != nullptr, "Memory allocation error");
for (HbsImpPtrVector::const_iterator i = m_comps.begin(); i != m_comps.end(); ++i)
{
SymCryptWipe(pbBuffer, cbSignature);
if ((*i)->sign(pbMsg, cbMsg, pbBuffer, cbSignature) != STATUS_SUCCESS)
{
CHECK(FALSE, "Signature generation error");
continue;
}
res.addResult((*i), pbBuffer, cbSignature);
}
res.getResult(pbSignature, cbSignature);
delete[] pbBuffer;
return status;
}
NTSTATUS
HbsMultiImp::verify(
PCBYTE pbMsg,
SIZE_T cbMsg,
PCBYTE pbSignature,
SIZE_T cbSignature )
{
NTSTATUS status = STATUS_SUCCESS;
ResultMerge res;
BYTE b[4];
for (HbsImpPtrVector::const_iterator i = m_comps.begin(); i != m_comps.end(); ++i)
{
status = (*i)->verify(pbMsg, cbMsg, pbSignature, cbSignature);
SYMCRYPT_STORE_MSBFIRST32(b, status);
res.addResult((*i), b, 4);
}
res.getResult(b, 4);
status = SYMCRYPT_LOAD_MSBFIRST32(b);
return status;
}
VOID
testHbsVerify(
HbsImplementation* pHbs,
UINT32 AlgId,
BOOL fMultitree,
_In_reads_(cbMsg) PCBYTE pbMsg,
SIZE_T cbMsg,
_In_reads_(cbPubkey) PCBYTE pbPubkey,
SIZE_T cbPubkey,
_In_reads_(cbSig) PCBYTE pbSig,
SIZE_T cbSig,
LONGLONG line )
{
NTSTATUS status;
UNREFERENCED_PARAMETER(line);
status = pHbs->setKey(AlgId, fMultitree, pbPubkey, cbPubkey, FALSE);
CHECK3(status == STATUS_SUCCESS, "Hbs setKey failed for algid = %u", AlgId);
status = pHbs->verify(pbMsg, cbMsg, pbSig, cbSig);
CHECK3(status == STATUS_SUCCESS, "Hbs verify failed for algid = %u", AlgId);
}
VOID
testHbsSign(
HbsImplementation* pHbs,
UINT32 AlgId,
BOOL fMultitree,
_In_reads_(cbMsg) PCBYTE pbMsg,
SIZE_T cbMsg,
_In_reads_(cbPrvkey) PCBYTE pbPrvkey,
SIZE_T cbPrvkey,
_In_reads_(cbSig) PCBYTE pbSig,
SIZE_T cbSig,
LONGLONG line )
{
NTSTATUS status;
PBYTE pbSig2 = nullptr;
UNREFERENCED_PARAMETER(line);
pbSig2 = new BYTE[cbSig];
CHECK3(pbSig2 != nullptr, "Memory allocation failed for %u bytes", cbSig);
status = pHbs->setKey(AlgId, fMultitree, pbPrvkey, cbPrvkey, FALSE);
CHECK3(status == STATUS_SUCCESS, "Hbs setKey failed for algid = %u", AlgId);
status = pHbs->sign(pbMsg, cbMsg, pbSig2, cbSig);
CHECK3(status == STATUS_SUCCESS, "Hbs sign failed for algid = %u", AlgId);
int bMatch = memcmp(pbSig, pbSig2, cbSig) == 0;
CHECK3(bMatch == TRUE, "generated signature does not match the given one for alg id %d", AlgId);
delete[] pbSig2;
}
VOID
testHbsKeygen(
HbsImplementation* pHbs,
UINT32 AlgId,
BOOL fMultitree,
_In_reads_(cbPrvkey) PCBYTE pbPrvkey,
SIZE_T cbPrvkey,
LONGLONG line )
{
NTSTATUS status;
UNREFERENCED_PARAMETER(line);
status = pHbs->setKey(AlgId, fMultitree, pbPrvkey, cbPrvkey, TRUE);
CHECK3(status == STATUS_SUCCESS, "Hbs setKey failed for algid = %u", AlgId);
}
VOID
testHbsKats()
{
KatData* katHbs = getCustomResource("kat_hbs.dat", "KAT_HBS");
KAT_ITEM katItem;
static String g_currentCategory;
BOOL skipData = TRUE;
String sep = " ";
BOOL doneAnything = FALSE;
std::unique_ptr<HbsMultiImp> pHbsMultiImp;
while (1)
{
katHbs->getKatItem(&katItem);
if (katItem.type == KAT_TYPE_END)
{
break;
}
if (katItem.type == KAT_TYPE_CATEGORY)
{
g_currentCategory = katItem.categoryName;
pHbsMultiImp.reset(new HbsMultiImp(g_currentCategory));
skipData = (pHbsMultiImp->m_imps.size() == 0);
if (!skipData)
{
iprint("%s%s", sep.c_str(), g_currentCategory.c_str());
sep = ", ";
doneAnything = TRUE;
}
}
if (skipData)
{
continue;
}
if (katItem.type == KAT_TYPE_DATASET)
{
if (katIsFieldPresent(katItem, "pubkey"))
{
//
// Signature verification test
//
BOOL fMultitree = FALSE;
UINT32 nExpectedItems = 4;
if (katIsFieldPresent(katItem, "multitree"))
{
fMultitree = katParseInteger(katItem, "multitree") > 0;
nExpectedItems++;
}
CHECK3(katItem.dataItems.size() == nExpectedItems, "Incorrect number of items in Hbs signature verification record ending at line %lld", katHbs->m_line);
UINT32 algId = (UINT32)katParseInteger(katItem, "algid");
BString katMsg = katParseData(katItem, "msg");
BString katPubkey = katParseData(katItem, "pubkey");
BString katSig = katParseData(katItem, "sig");
testHbsVerify(
pHbsMultiImp.get(),
algId,
fMultitree,
(PCBYTE)katMsg.data(),
katMsg.size(),
(PCBYTE)katPubkey.data(),
katPubkey.size(),
(PCBYTE)katSig.data(),
katSig.size(),
katHbs->m_line);
continue;
}
if (katIsFieldPresent(katItem, "prvkey"))
{
if (katIsFieldPresent(katItem, "msg"))
{
//
// Signature generation test
//
BOOL fMultitree = FALSE;
UINT32 nExpectedItems = 4;
if (katIsFieldPresent(katItem, "multitree"))
{
fMultitree = katParseInteger(katItem, "multitree") > 0;
nExpectedItems++;
}
CHECK3(katItem.dataItems.size() == nExpectedItems, "Incorrect number of items in Hbs signature verification record ending at line %lld", katHbs->m_line);
UINT32 algId = (UINT32)katParseInteger(katItem, "algid");
BString katMsg = katParseData(katItem, "msg");
BString katPrvkey = katParseData(katItem, "prvkey");
BString katSig = katParseData(katItem, "sig");
testHbsSign(
pHbsMultiImp.get(),
algId,
fMultitree,
(PCBYTE)katMsg.data(),
katMsg.size(),
(PCBYTE)katPrvkey.data(),
katPrvkey.size(),
(PCBYTE)katSig.data(),
katSig.size(),
katHbs->m_line);
}
else
{
//
// Key generation test
//
BOOL fMultitree = FALSE;
UINT32 nExpectedItems = 2;
if (katIsFieldPresent(katItem, "multitree"))
{
fMultitree = katParseInteger(katItem, "multitree") > 0;
nExpectedItems++;
}
CHECK3(katItem.dataItems.size() == nExpectedItems, "Incorrect number of items in Hbs signature verification record ending at line %lld", katHbs->m_line);
UINT32 algId = (UINT32)katParseInteger(katItem, "algid");
BString katPrvkey = katParseData(katItem, "prvkey");
testHbsKeygen(
pHbsMultiImp.get(),
algId,
fMultitree,
(PCBYTE)katPrvkey.data(),
katPrvkey.size(),
katHbs->m_line);
}
continue;
}
FATAL2("Unknown data record ending at line %lld", katHbs->m_line);
}
}
if (doneAnything)
{
iprint("\n");
}
delete katHbs;
}
VOID
testXmssCustomParameters()
{
SYMCRYPT_XMSS_PARAMS params;
PSYMCRYPT_XMSS_KEY pKey;
PBYTE pbSignature;
SYMCRYPT_ERROR scError;
SIZE_T cbSignature;
BYTE msg[] = { 0x00, 0x01, 0x03, 0x04 };
PCSYMCRYPT_HASH pHash = SymCryptSha256Algorithm;
//
// Test varying Winternitz lengths with custom tree heights
//
for (UINT8 w = 1; w <= 8; w <<= 1)
{
for (UINT8 h = 1; h <= 4; h++)
{
ScDispatchSymCryptWipe(&params, sizeof(SYMCRYPT_XMSS_PARAMS));
scError = ScDispatchSymCryptXmssSetParams(
&params,
0, // alg id
pHash, // hash alg.
(UINT8)pHash->resultSize, // n
w, // w
h, // h
(UINT8)1, // d
(UINT8)pHash->resultSize); // cbPrefix
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
pKey = ScDispatchSymCryptXmsskeyAllocate(&params, 0);
CHECK(pKey != nullptr, "?");
scError = ScDispatchSymCryptXmsskeyGenerate(pKey, 0);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
cbSignature = ScDispatchSymCryptXmssSizeofSignatureFromParams(&params);
pbSignature = new BYTE[cbSignature];
CHECK(pbSignature != nullptr, "?");
// Sign and Verify with each WOTSP key
for (UINT32 idx = 0; idx < (1UL << h); idx++)
{
scError = ScDispatchSymCryptXmssSign(pKey, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
scError = ScDispatchSymCryptXmssVerify(pKey, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
// Modify the signature and expect verification failure
UINT32 nModifyPos = g_rng.uint32() % cbSignature;
pbSignature[nModifyPos] ^= 1;
scError = ScDispatchSymCryptXmssVerify(pKey, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError != SYMCRYPT_NO_ERROR, "?");
}
// All one-time signatures are consumed above, we shouldn't be able to sign anymore
scError = ScDispatchSymCryptXmssSign(pKey, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError == SYMCRYPT_HBS_NO_OTS_KEYS_LEFT, "?");
delete[] pbSignature;
ScDispatchSymCryptXmsskeyFree(pKey);
}
}
}
VOID
testXmssImportExport()
{
SYMCRYPT_XMSS_PARAMS params;
PSYMCRYPT_XMSS_KEY pKeyPrivate;
PSYMCRYPT_XMSS_KEY pKeyPublic;
SYMCRYPT_ERROR scError;
PBYTE pbPrivateKeyBlob;
PBYTE pbPublicKeyBlob;
SIZE_T cbPrivateKey;
SIZE_T cbPublicKey;
PBYTE pbSignature;
PBYTE pbSignature2;
SIZE_T cbSignature;
BYTE msg[] = { 0x01 };
scError = ScDispatchSymCryptXmssParamsFromAlgId(SYMCRYPT_XMSS_SHA2_10_256, &params);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
// Create a private key
pKeyPrivate = ScDispatchSymCryptXmsskeyAllocate(&params, 0);
CHECK(pKeyPrivate != nullptr, "?");
scError = ScDispatchSymCryptXmsskeyGenerate(pKeyPrivate, 0);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
scError = ScDispatchSymCryptXmssSizeofKeyBlobFromParams(&params, SYMCRYPT_XMSSKEY_TYPE_PUBLIC, &cbPublicKey);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
scError = ScDispatchSymCryptXmssSizeofKeyBlobFromParams(&params, SYMCRYPT_XMSSKEY_TYPE_PRIVATE, &cbPrivateKey);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
// Export private key
pbPrivateKeyBlob = new BYTE[cbPrivateKey];
CHECK(pbPrivateKeyBlob != nullptr, "?");
scError = ScDispatchSymCryptXmsskeyGetValue(pKeyPrivate, SYMCRYPT_XMSSKEY_TYPE_PRIVATE, 0, pbPrivateKeyBlob, cbPrivateKey);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
// Export public key
pbPublicKeyBlob = new BYTE[cbPublicKey];
CHECK(pbPublicKeyBlob != nullptr, "?");
scError = ScDispatchSymCryptXmsskeyGetValue(pKeyPrivate, SYMCRYPT_XMSSKEY_TYPE_PUBLIC, 0, pbPublicKeyBlob, cbPublicKey);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
// Sign and verify a message
cbSignature = ScDispatchSymCryptXmssSizeofSignatureFromParams(&params);
pbSignature = new BYTE[cbSignature];
CHECK(pbSignature != nullptr, "?");
scError = ScDispatchSymCryptXmssSign(pKeyPrivate, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
scError = ScDispatchSymCryptXmssVerify(pKeyPrivate, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
// Done with the original private key
ScDispatchSymCryptXmsskeyFree(pKeyPrivate);
// Import the private key from the key blob
pKeyPrivate = ScDispatchSymCryptXmsskeyAllocate(&params, 0);
CHECK(pKeyPrivate != nullptr, "?");
scError = ScDispatchSymCryptXmsskeySetValue(pbPrivateKeyBlob, cbPrivateKey, SYMCRYPT_XMSSKEY_TYPE_PRIVATE, 0, pKeyPrivate);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
// Sign the message again with the imported private key and check if the same signature is produced
pbSignature2 = new BYTE[cbSignature];
CHECK(pbSignature2 != nullptr, "?");
scError = ScDispatchSymCryptXmssSign(pKeyPrivate, msg, sizeof(msg), 0, pbSignature2, cbSignature);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
CHECK(memcmp(pbSignature, pbSignature2, cbSignature) == 0, "?");
ScDispatchSymCryptXmsskeyFree(pKeyPrivate);
// Import the public key and verify the signature
pKeyPublic = ScDispatchSymCryptXmsskeyAllocate(&params, 0);
CHECK(pKeyPublic != nullptr, "?");
scError = ScDispatchSymCryptXmsskeySetValue(pbPublicKeyBlob, cbPublicKey, SYMCRYPT_XMSSKEY_TYPE_PUBLIC, 0, pKeyPublic);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
scError = ScDispatchSymCryptXmssVerify(pKeyPublic, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
ScDispatchSymCryptXmsskeyFree(pKeyPublic);
delete[] pbSignature2;
delete[] pbSignature;
delete[] pbPublicKeyBlob;
delete[] pbPrivateKeyBlob;
}
VOID
testXmssMultitree()
{
SYMCRYPT_XMSS_PARAMS params;
PSYMCRYPT_XMSS_KEY pKey;
PBYTE pbSignature;
SYMCRYPT_ERROR scError;
SIZE_T cbSignature;
BYTE msg[] = { 0x00, 0x01, 0x03, 0x04 };
PCSYMCRYPT_HASH pHash = SymCryptSha256Algorithm;
const UINT8 H = 6;
const UINT8 LayerHeights[] = { 1, 2, 3 };
//
// Total tree height is 6
//
// Test all possible layer heights 1, 2, 3, corresponding to
// number of layers 6, 3, 2.
//
for (UINT32 i = 0; i < sizeof(LayerHeights); i++)
{
scError = ScDispatchSymCryptXmssSetParams(
&params,
0,
pHash,
(UINT8)pHash->resultSize,
(UINT8)4,
H,
(UINT8)(H / LayerHeights[i]),
(UINT8)pHash->resultSize);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
pKey = ScDispatchSymCryptXmsskeyAllocate(&params, 0);
CHECK(pKey != nullptr, "?");
scError = ScDispatchSymCryptXmsskeyGenerate(pKey, 0);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
cbSignature = ScDispatchSymCryptXmssSizeofSignatureFromParams(&params);
pbSignature = new BYTE[cbSignature];
CHECK(pbSignature != nullptr, "?");
// Sign and Verify with each WOTSP key
for (UINT32 idx = 0; idx < (1UL << H); idx++)
{
scError = ScDispatchSymCryptXmssSign(pKey, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
scError = ScDispatchSymCryptXmssVerify(pKey, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError == SYMCRYPT_NO_ERROR, "?");
// Modify the signature and expect verification failure
UINT32 nModifyPos = g_rng.uint32() % cbSignature;
pbSignature[nModifyPos] ^= 1;
scError = ScDispatchSymCryptXmssVerify(pKey, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError != SYMCRYPT_NO_ERROR, "?");
}
// All one-time signatures are consumed above, we shouldn't be able to sign anymore
scError = ScDispatchSymCryptXmssSign(pKey, msg, sizeof(msg), 0, pbSignature, cbSignature);
CHECK(scError == SYMCRYPT_HBS_NO_OTS_KEYS_LEFT , "?");
ScDispatchSymCryptXmsskeyFree(pKey);
delete[] pbSignature;
}
}
VOID
testXmss()
{
testWinternitzLengths();
testXmssCustomParameters();
testXmssMultitree();
testXmssImportExport();
}
VOID
testHbs()
{
testXmss();
testHbsKats();
}

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

@ -681,3 +681,16 @@ EXPORTS
SymCrypt802_11SaeCustomDestroy
SymCryptFipsGetSelftestsPerformed
SymCryptDeprecatedStatusIndicator
SymCryptXmsskeyAllocate
SymCryptXmsskeyFree
SymCryptXmsskeyGenerate
SymCryptXmsskeyGetValue
SymCryptXmsskeySetValue
SymCryptXmssSizeofKeyBlobFromParams
SymCryptXmssMtParamsFromAlgId
SymCryptXmssParamsFromAlgId
SymCryptXmssSetParams
SymCryptXmssSign
SymCryptXmssSizeofSignatureFromParams
SymCryptXmssVerify
SymCryptXmssSelftest

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

@ -21,6 +21,6 @@ kat_rsaSign.dat KAT_RSA_SIGN "..\kat_rsaSign.
kat_rsaEnc.dat KAT_RSA_ENC "..\kat_rsaEnc.dat"
kat_dh.dat KAT_DH "..\kat_dh.dat"
kat_dsa.dat KAT_DSA "..\kat_dsa.dat"
kat_hbs.dat KAT_HBS "..\kat_hbs.dat"