зеркало из https://github.com/microsoft/SymCrypt.git
Merged PR 7810991: Add SRTP-KDF and SSH-KDF implementations
- Add SRTP-KDF and SSH-KDF implementations - Update `SYMCRYPT_HASH` structure to contain hash state copying function member Related work items: #38101963, #38102026
This commit is contained in:
Родитель
efbfc1f077
Коммит
bc66c79cde
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,3 +1,16 @@
|
|||
# Version 103.0
|
||||
|
||||
- Add SRTP-KDF and SSH-KDF implementations
|
||||
- Add optimized SHA-2 implementations
|
||||
- Fix integer truncation issue in 32-bit Linux builds
|
||||
- Refactor CMake files to simplify build steps and increase flexibility
|
||||
- Fix bug for SymCryptRsakeyGenerate for encrypt-only keys
|
||||
- Create and test against simple SymCrypt Windows test module (DLL)
|
||||
- Remove the module export of g_SymCryptFipsSelftestsPerformed and replace it with SymCryptFipsGetSelftestsPerformed
|
||||
- Enable SymCrypt unit tests to drive a dynamically-linked module
|
||||
- Removed Linux embedded module, as generic ARM64 module is the same
|
||||
- Rejig CPUID logic for VAES and AVX
|
||||
|
||||
# Version 102.0
|
||||
|
||||
- Breaking change to Asymmetric key generation and import handling, sanitizing flags required for FIPS
|
||||
|
|
248
inc/symcrypt.h
248
inc/symcrypt.h
|
@ -760,6 +760,9 @@ SIZE_T
|
|||
SYMCRYPT_CALL
|
||||
SymCryptHashInputBlockSize( _In_ PCSYMCRYPT_HASH pHash );
|
||||
|
||||
SIZE_T
|
||||
SYMCRYPT_CALL
|
||||
SymCryptHashStateSize( _In_ PCSYMCRYPT_HASH pHash );
|
||||
//
|
||||
// SymCryptHashStateSize
|
||||
//
|
||||
|
@ -769,19 +772,9 @@ SymCryptHashInputBlockSize( _In_ PCSYMCRYPT_HASH pHash );
|
|||
// any Symcrypt-implemented hash state, so sizeof( SYMCRYPT_HASH_STATE ) is always
|
||||
// large enough to contain a hash state.
|
||||
//
|
||||
SIZE_T
|
||||
SYMCRYPT_CALL
|
||||
SymCryptHashStateSize( _In_ PCSYMCRYPT_HASH pHash );
|
||||
|
||||
|
||||
|
||||
//
|
||||
// SymCryptHash
|
||||
//
|
||||
// Compute a hash value using any hash function.
|
||||
// The number of bytes written to the pbResult buffer is
|
||||
// min( cbResult, SymCryptHashResultSize( pHash ) )
|
||||
//
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
SymCryptHash(
|
||||
|
@ -790,6 +783,14 @@ SymCryptHash(
|
|||
SIZE_T cbData,
|
||||
_Out_writes_( SYMCRYPT_MIN( cbResult, pHash->resultSize ) ) PBYTE pbResult,
|
||||
SIZE_T cbResult );
|
||||
//
|
||||
// SymCryptHash
|
||||
//
|
||||
// Compute a hash value using any hash function.
|
||||
// The number of bytes written to the pbResult buffer is
|
||||
// min( cbResult, SymCryptHashResultSize( pHash ) )
|
||||
//
|
||||
|
||||
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
|
@ -805,6 +806,7 @@ SymCryptHashAppend(
|
|||
_In_reads_( cbData ) PCBYTE pbData,
|
||||
SIZE_T cbData );
|
||||
|
||||
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
SymCryptHashResult(
|
||||
|
@ -812,8 +814,23 @@ SymCryptHashResult(
|
|||
_Inout_updates_bytes_( pHash->stateSize ) PVOID pState,
|
||||
_Out_writes_( SYMCRYPT_MIN( cbResult, pHash->resultSize ) ) PBYTE pbResult,
|
||||
SIZE_T cbResult );
|
||||
//
|
||||
// SymCryptHashResult
|
||||
//
|
||||
// Finalizes the hash computation by calling the resultFunc member
|
||||
// of pHash.
|
||||
// The hash result is produced to an internal buffer and
|
||||
// the number of bytes written to the pbResult buffer is
|
||||
// min( cbResult, SymCryptHashResultSize( pHash ) )
|
||||
|
||||
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
SymCryptHashStateCopy(
|
||||
_In_ PCSYMCRYPT_HASH pHash,
|
||||
_In_reads_(pHash->stateSize) PCVOID pSrc,
|
||||
_Out_writes_(pHash->stateSize) PVOID pDst);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// MD2
|
||||
//
|
||||
|
@ -3912,6 +3929,217 @@ VOID
|
|||
SYMCRYPT_CALL
|
||||
SymCryptTlsPrf1_2SelfTest();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SSH-KDF as specified in RFC 4253 Section 7.2.
|
||||
//
|
||||
|
||||
|
||||
// Labels defined in RFC 4253
|
||||
#define SYMCRYPT_SSHKDF_IV_CLIENT_TO_SERVER 0x41 // 'A'
|
||||
#define SYMCRYPT_SSHKDF_IV_SERVER_TO_CLIENT 0x42 // 'B'
|
||||
#define SYMCRYPT_SSHKDF_ENCRYPTION_KEY_CLIENT_TO_SERVER 0x43 // 'C'
|
||||
#define SYMCRYPT_SSHKDF_ENCRYPTION_KEY_SERVER_TO_CLIENT 0x44 // 'D'
|
||||
#define SYMCRYPT_SSHKDF_INTEGRITY_KEY_CLIENT_TO_SERVER 0x45 // 'E'
|
||||
#define SYMCRYPT_SSHKDF_INTEGRITY_KEY_SERVER_TO_CLIENT 0x46 // 'F'
|
||||
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSshKdfExpandKey(
|
||||
_Out_ PSYMCRYPT_SSHKDF_EXPANDED_KEY pExpandedKey,
|
||||
_In_ PCSYMCRYPT_HASH pHashFunc,
|
||||
_In_reads_(cbKey) PCBYTE pbKey,
|
||||
SIZE_T cbKey);
|
||||
//
|
||||
// Process the key using the specified hash function and store the result in
|
||||
// SYMCRYPT_SSHKDF_EXPANDED_KEY structure. Once the key is expanded,
|
||||
// SymCryptSshKdfDerive can be called multiple times to generate keys for
|
||||
// different uses/labels.
|
||||
//
|
||||
// After all the keys are derived from a particular "shared secret" key,
|
||||
// SYMCRYPT_SSHKDF_EXPANDED_KEY structure must be wiped.
|
||||
//
|
||||
// Parameters:
|
||||
// - pExpandedKey : Pointer to a SYMCRYPT_SSHKDF_EXPANDED_KEY structure that
|
||||
// will contain the expanded key after the function returns.
|
||||
// - pHashFunc : Hash function that will be used in the key derivation.
|
||||
// This function is saved in SYMCRYPT_SSHKDF_EXPANDED_KEY
|
||||
// so that it is also used by the SymCryptSshKdfDerive function.
|
||||
// - pbKey, cbKey : Buffer contatining the secret key for the KDF.
|
||||
//
|
||||
// Returns SYMCRYPT_NO_ERROR
|
||||
//
|
||||
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSshKdfDerive(
|
||||
_In_ PCSYMCRYPT_SSHKDF_EXPANDED_KEY pExpandedKey,
|
||||
_In_reads_(cbHashValue) PCBYTE pbHashValue,
|
||||
SIZE_T cbHashValue,
|
||||
BYTE label,
|
||||
_In_reads_(cbSessionId) PCBYTE pbSessionId,
|
||||
SIZE_T cbSessionId,
|
||||
_Inout_updates_(cbOutput) PBYTE pbOutput,
|
||||
SIZE_T cbOutput);
|
||||
//
|
||||
// Derive keys using the expanded key that was initialized with SymCryptSshKdfExpandKey
|
||||
// along with other inputs. This function can be called consecutively with varying label
|
||||
// values to generate keys for different purposes as defined in the RFC.
|
||||
//
|
||||
// Parameters:
|
||||
// - pExpandedKey : Pointer to a SYMCRYPT_SSHKDF_EXPANDED_KEY structure that is
|
||||
// initialized by a prior call to SymCryptSshKdfExpandKey.
|
||||
// Must be wiped when SymCryptSshKdfDerive is not going to be called
|
||||
// again with the same expanded key.
|
||||
// - pbHashValue, cbHashValue : Buffer pointing to "exchange hash" value. cbHashValue must be equal
|
||||
// to the output size of the hash function passed to SymCryptSshKdfExpandKey.
|
||||
// - label : Label value used to indicate the type of the derived key.
|
||||
// - pbSessionId, cbSessionId : Buffer pointing to the session identifier. cbSessionId must be equal
|
||||
// to the output size of the hash function passed to SymCryptSshKdfExpandKey.
|
||||
// - pbOutput, cbOutput : Buffer to store the derived key. Exactly cbOutput bytes of output will be generated.
|
||||
//
|
||||
// Returns SYMCRYPT_NO_ERROR
|
||||
//
|
||||
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSshKdf(
|
||||
_In_ PCSYMCRYPT_HASH pHashFunc,
|
||||
_In_reads_(cbKey) PCBYTE pbKey,
|
||||
SIZE_T cbKey,
|
||||
_In_reads_(cbHashValue) PCBYTE pbHashValue,
|
||||
SIZE_T cbHashValue,
|
||||
BYTE label,
|
||||
_In_reads_(cbSessionId) PCBYTE pbSessionId,
|
||||
SIZE_T cbSessionId,
|
||||
_Out_writes_(cbOutput) PBYTE pbOutput,
|
||||
SIZE_T cbOutput);
|
||||
//
|
||||
// This function is a wrapper for using SymCryptSshKdfExpandKey followed by SymCryptSshKdfDerive
|
||||
// in order to produce SSH-KDF output.
|
||||
//
|
||||
// All of the function arguments are forwarded to SymCryptSshKdfExpandKey and SymCryptSshKdfDerive
|
||||
// functions, hence the documentation on those functions apply here as well.
|
||||
//
|
||||
|
||||
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSshKdfSha256SelfTest();
|
||||
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSshKdfSha512SelfTest();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SRTP-KDF as specified in RFC 3711 Section 4.3.1.
|
||||
//
|
||||
|
||||
|
||||
// Labels defined in RFC 3711
|
||||
#define SYMCRYPT_SRTP_ENCRYPTION_KEY 0x00
|
||||
#define SYMCRYPT_SRTP_AUTHENTICATION_KEY 0x01
|
||||
#define SYMCRYPT_SRTP_SALTING_KEY 0x02
|
||||
#define SYMCRYPT_SRTCP_ENCRYPTION_KEY 0x03
|
||||
#define SYMCRYPT_SRTCP_AUTHENTICATION_KEY 0x04
|
||||
#define SYMCRYPT_SRTCP_SALTING_KEY 0x05
|
||||
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSrtpKdfExpandKey(
|
||||
_Out_ PSYMCRYPT_SRTPKDF_EXPANDED_KEY pExpandedKey,
|
||||
_In_reads_(cbKey) PCBYTE pbKey,
|
||||
SIZE_T cbKey);
|
||||
//
|
||||
// Process the key and store the result in SYMCRYPT_SRTPKDF_EXPANDED_KEY structure.
|
||||
// Once the key is expanded, SymCryptSrtpKdfDerive can be called multiple times to
|
||||
// generate keys for different uses/labels.
|
||||
//
|
||||
// After all the keys are derived from a particular "shared secret" key,
|
||||
// SYMCRYPT_SRTPKDF_EXPANDED_KEY structure must be wiped.
|
||||
//
|
||||
// Parameters:
|
||||
// - pExpandedKey : Pointer to a SYMCRYPT_SRTPKDF_EXPANDED_KEY structure that
|
||||
// will contain the expanded key after the function returns.
|
||||
// - pbKey, cbKey : Buffer contatining the secret key for the KDF. cbKey must be
|
||||
// a valid AES key size (16-, 24-, or 32-bytes).
|
||||
//
|
||||
// Returns:
|
||||
// SYMCRYPT_WRONG_KEY_SIZE : If cbKey is not a valid AES key size
|
||||
// SYMCRYPT_NO_ERROR : On success
|
||||
//
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSrtpKdfDerive(
|
||||
_In_ PCSYMCRYPT_SRTPKDF_EXPANDED_KEY pExpandedKey,
|
||||
_In_reads_(cbSalt) PCBYTE pbSalt,
|
||||
SIZE_T cbSalt,
|
||||
UINT32 uKeyDerivationRate,
|
||||
UINT64 uIndex,
|
||||
UINT32 uIndexWidth,
|
||||
BYTE label,
|
||||
_Out_writes_(cbOutput) PBYTE pbOutput,
|
||||
SIZE_T cbOutput);
|
||||
//
|
||||
// Derive keys using the expanded key that was initialized with SymCryptSrtpKdfExpandKey
|
||||
// along with other inputs. This function can be called consecutively with varying label
|
||||
// values to generate keys for different purposes as defined in the RFC.
|
||||
//
|
||||
// Parameters:
|
||||
// - pExpandedKey : Pointer to a SYMCRYPT_SRTPKDF_EXPANDED_KEY structure that is
|
||||
// initialized by a prior call to SymCryptSrtpKdfExpandKey.
|
||||
// Must be wiped when SymCryptSrtpKdfDerive is not going to be called
|
||||
// again with the same expanded key.
|
||||
// - pbSalt, cbSalt : Buffer pointing to the salt value. cbSalt must always be 14 (112-bits).
|
||||
// - uKeyDerivationRate : Key derivation rate; must be zero or 2^i for 0 <= i <= 24.
|
||||
// - uIndex : Denotes an SRTP index value when label is 0x00, 0x01, or 0x02, otherwise
|
||||
// denotes an SRTCP index value.
|
||||
// - uIndexWidth : Denotes how wide uIndex value is. Must be one of 0, 32, or 48. By default,
|
||||
// (when uIndexWidth = 0) uIndex is treated as 48-bits.
|
||||
// RFC 3711 initially defined SRTCP indices to be 32-bit values. It was updated
|
||||
// to be 48-bits by Errata ID 3712. SRTP index values are defined to be 48-bits.
|
||||
// - label : Label value used to indicate the type of the derived key.
|
||||
// - pbOutput, cbOutput : Buffer to store the derived key. Exactly cbOutput bytes of output will be generated.
|
||||
//
|
||||
// Returns:
|
||||
// SYMCRYPT_INVALID_ARGUMENT : If cbSalt is not 14-bytes, or uKeyDerivationRate in invalid.
|
||||
// SYMCRYPT_NO_ERROR : On success.
|
||||
//
|
||||
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSrtpKdf(
|
||||
_In_reads_(cbKey) PCBYTE pbKey,
|
||||
SIZE_T cbKey,
|
||||
_In_reads_(cbSalt) PCBYTE pbSalt,
|
||||
SIZE_T cbSalt,
|
||||
UINT32 uKeyDerivationRate,
|
||||
UINT64 uIndex,
|
||||
UINT32 uIndexWidth,
|
||||
BYTE label,
|
||||
_Out_writes_(cbOutput) PBYTE pbOutput,
|
||||
SIZE_T cbOutput);
|
||||
//
|
||||
// This function is a wrapper for using SymCryptSrtpKdfExpandKey followed by SymCryptSrtpKdfDerive
|
||||
// in order to produce SRTP-KDF output.
|
||||
//
|
||||
// All of the function arguments are forwarded to SymCryptSrtpKdfExpandKey and SymCryptSrtpKdfDerive
|
||||
// functions, hence the documentation on those functions apply here as well.
|
||||
//
|
||||
|
||||
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSrtpKdfSelfTest();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// HKDF
|
||||
//
|
||||
|
|
|
@ -852,6 +852,7 @@ typedef VOID (SYMCRYPT_CALL * PSYMCRYPT_HASH_INIT_FUNC) ( PVOID pSta
|
|||
typedef VOID (SYMCRYPT_CALL * PSYMCRYPT_HASH_APPEND_FUNC) ( PVOID pState, PCBYTE pbData, SIZE_T cbData );
|
||||
typedef VOID (SYMCRYPT_CALL * PSYMCRYPT_HASH_RESULT_FUNC) ( PVOID pState, PVOID pbResult );
|
||||
typedef VOID (SYMCRYPT_CALL * PSYMCRYPT_HASH_APPEND_BLOCKS_FUNC) ( PVOID pChain, PCBYTE pbData, SIZE_T cbData, SIZE_T * pcbRemaining );
|
||||
typedef VOID (SYMCRYPT_CALL * PSYMCRYPT_HASH_STATE_COPY_FUNC) ( PCVOID pStateSrc, PVOID pStateDst );
|
||||
|
||||
typedef SYMCRYPT_ALIGN_STRUCT _SYMCRYPT_HASH
|
||||
{
|
||||
|
@ -859,6 +860,7 @@ typedef SYMCRYPT_ALIGN_STRUCT _SYMCRYPT_HASH
|
|||
PSYMCRYPT_HASH_APPEND_FUNC appendFunc;
|
||||
PSYMCRYPT_HASH_RESULT_FUNC resultFunc;
|
||||
PSYMCRYPT_HASH_APPEND_BLOCKS_FUNC appendBlockFunc;
|
||||
PSYMCRYPT_HASH_STATE_COPY_FUNC stateCopyFunc;
|
||||
UINT32 stateSize; // sizeof( hash state )
|
||||
UINT32 resultSize; // size of hash result
|
||||
UINT32 inputBlockSize;
|
||||
|
@ -1665,6 +1667,23 @@ typedef struct _SYMCRYPT_TLSPRF1_2_EXPANDED_KEY {
|
|||
} SYMCRYPT_TLSPRF1_2_EXPANDED_KEY, *PSYMCRYPT_TLSPRF1_2_EXPANDED_KEY;
|
||||
typedef const SYMCRYPT_TLSPRF1_2_EXPANDED_KEY *PCSYMCRYPT_TLSPRF1_2_EXPANDED_KEY;
|
||||
|
||||
//
|
||||
// SSH-KDF
|
||||
//
|
||||
typedef struct _SYMCRYPT_SSHKDF_EXPANDED_KEY {
|
||||
PCSYMCRYPT_HASH pHashFunc;
|
||||
SYMCRYPT_HASH_STATE hashState;
|
||||
} SYMCRYPT_SSHKDF_EXPANDED_KEY, *PSYMCRYPT_SSHKDF_EXPANDED_KEY;
|
||||
typedef const SYMCRYPT_SSHKDF_EXPANDED_KEY *PCSYMCRYPT_SSHKDF_EXPANDED_KEY;
|
||||
|
||||
//
|
||||
// SRTP-KDF
|
||||
//
|
||||
typedef struct _SYMCRYPT_SRTPKDF_EXPANDED_KEY {
|
||||
SYMCRYPT_AES_EXPANDED_KEY aesExpandedKey;
|
||||
} SYMCRYPT_SRTPKDF_EXPANDED_KEY, *PSYMCRYPT_SRTPKDF_EXPANDED_KEY;
|
||||
typedef const SYMCRYPT_SRTPKDF_EXPANDED_KEY *PCSYMCRYPT_SRTPKDF_EXPANDED_KEY;
|
||||
|
||||
//
|
||||
// HKDF
|
||||
//
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
// The API numbering starts at 100 to avoid number conficts with the old system.
|
||||
//
|
||||
|
||||
#define SYMCRYPT_CODE_VERSION_API 102
|
||||
#define SYMCRYPT_CODE_VERSION_API 103
|
||||
#define SYMCRYPT_CODE_VERSION_MINOR 0
|
||||
#define SYMCRYPT_CODE_VERSION_PATCH 0
|
||||
|
||||
|
|
|
@ -96,6 +96,11 @@ set(SOURCES_COMMON
|
|||
sp800_108_hmacsha256.c
|
||||
sp800_108_hmacsha512.c
|
||||
sp800_108.c
|
||||
srtp_kdf.c
|
||||
srtp_kdf_selftest.c
|
||||
ssh_kdf.c
|
||||
ssh_kdf_sha256.c
|
||||
ssh_kdf_sha512.c
|
||||
tlsCbcVerify.c
|
||||
tlsprf_selftest.c
|
||||
tlsprf.c
|
||||
|
|
|
@ -205,4 +205,13 @@ SymCryptHashResult(
|
|||
SymCryptWipe( buf, pHash->resultSize );
|
||||
}
|
||||
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
SymCryptHashStateCopy(
|
||||
_In_ PCSYMCRYPT_HASH pHash,
|
||||
_In_reads_( pHash->stateSize ) PCVOID pSrc,
|
||||
_Out_writes_( pHash->stateSize ) PVOID pDst)
|
||||
{
|
||||
(*pHash->stateCopyFunc)( pSrc, pDst );
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ const SYMCRYPT_HASH SymCryptMd2Algorithm_default = {
|
|||
&SymCryptMd2Append,
|
||||
&SymCryptMd2Result,
|
||||
&SymCryptMd2AppendBlocks,
|
||||
&SymCryptMd2StateCopy,
|
||||
sizeof( SYMCRYPT_MD2_STATE ),
|
||||
SYMCRYPT_MD2_RESULT_SIZE,
|
||||
SYMCRYPT_MD2_INPUT_BLOCK_SIZE,
|
||||
|
|
|
@ -35,6 +35,7 @@ const SYMCRYPT_HASH SymCryptMd4Algorithm_default = {
|
|||
&SymCryptMd4Append,
|
||||
&SymCryptMd4Result,
|
||||
&SymCryptMd4AppendBlocks,
|
||||
&SymCryptMd4StateCopy,
|
||||
sizeof( SYMCRYPT_MD4_STATE ),
|
||||
SYMCRYPT_MD4_RESULT_SIZE,
|
||||
SYMCRYPT_MD4_INPUT_BLOCK_SIZE,
|
||||
|
|
|
@ -32,6 +32,7 @@ const SYMCRYPT_HASH SymCryptMd5Algorithm_default = {
|
|||
&SymCryptMd5Append,
|
||||
&SymCryptMd5Result,
|
||||
&SymCryptMd5AppendBlocks,
|
||||
&SymCryptMd5StateCopy,
|
||||
sizeof( SYMCRYPT_MD5_STATE ),
|
||||
SYMCRYPT_MD5_RESULT_SIZE,
|
||||
SYMCRYPT_MD5_INPUT_BLOCK_SIZE,
|
||||
|
|
|
@ -18,6 +18,7 @@ const SYMCRYPT_HASH SymCryptSha1Algorithm_default = {
|
|||
&SymCryptSha1Append,
|
||||
&SymCryptSha1Result,
|
||||
&SymCryptSha1AppendBlocks,
|
||||
&SymCryptSha1StateCopy,
|
||||
sizeof( SYMCRYPT_SHA1_STATE ),
|
||||
SYMCRYPT_SHA1_RESULT_SIZE,
|
||||
SYMCRYPT_SHA1_INPUT_BLOCK_SIZE,
|
||||
|
|
|
@ -21,6 +21,7 @@ const SYMCRYPT_HASH SymCryptSha256Algorithm_default = {
|
|||
&SymCryptSha256Append,
|
||||
&SymCryptSha256Result,
|
||||
&SymCryptSha256AppendBlocks,
|
||||
&SymCryptSha256StateCopy,
|
||||
sizeof( SYMCRYPT_SHA256_STATE ),
|
||||
SYMCRYPT_SHA256_RESULT_SIZE,
|
||||
SYMCRYPT_SHA256_INPUT_BLOCK_SIZE,
|
||||
|
|
|
@ -97,6 +97,7 @@ const SYMCRYPT_HASH SymCryptSha384Algorithm_default = {
|
|||
&SymCryptSha384Append,
|
||||
&SymCryptSha384Result,
|
||||
&SymCryptSha512AppendBlocks,
|
||||
&SymCryptSha384StateCopy,
|
||||
sizeof( SYMCRYPT_SHA384_STATE ),
|
||||
SYMCRYPT_SHA384_RESULT_SIZE,
|
||||
SYMCRYPT_SHA384_INPUT_BLOCK_SIZE,
|
||||
|
@ -109,6 +110,7 @@ const SYMCRYPT_HASH SymCryptSha512Algorithm_default = {
|
|||
&SymCryptSha512Append,
|
||||
&SymCryptSha512Result,
|
||||
&SymCryptSha512AppendBlocks,
|
||||
&SymCryptSha512StateCopy,
|
||||
sizeof( SYMCRYPT_SHA512_STATE ),
|
||||
SYMCRYPT_SHA512_RESULT_SIZE,
|
||||
SYMCRYPT_SHA512_INPUT_BLOCK_SIZE,
|
||||
|
|
|
@ -139,6 +139,11 @@ SOURCES= \
|
|||
sp800_108_hmacsha1.c \
|
||||
sp800_108_hmacsha256.c \
|
||||
sp800_108_hmacsha512.c \
|
||||
srtp_kdf.c \
|
||||
srtp_kdf_selftest.c \
|
||||
ssh_kdf.c \
|
||||
ssh_kdf_sha256.c \
|
||||
ssh_kdf_sha512.c \
|
||||
tlsprf.c \
|
||||
tlsprf_selftest.c \
|
||||
hkdf.c \
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
//
|
||||
// srtp_kdf.c
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
|
||||
//
|
||||
|
||||
//
|
||||
// This module implements SRTP-KDF specified in RFC 3711 Section 4.3.1.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
|
||||
#define SYMCRYPT_SRTP_KDF_SALT_SIZE (112 / 8)
|
||||
|
||||
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSrtpKdfExpandKey(
|
||||
_Out_ PSYMCRYPT_SRTPKDF_EXPANDED_KEY pExpandedKey,
|
||||
_In_reads_(cbKey) PCBYTE pbKey,
|
||||
SIZE_T cbKey)
|
||||
{
|
||||
return SymCryptAesExpandKeyEncryptOnly(&pExpandedKey->aesExpandedKey, pbKey, cbKey);
|
||||
}
|
||||
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSrtpKdfDerive(
|
||||
_In_ PCSYMCRYPT_SRTPKDF_EXPANDED_KEY pExpandedKey,
|
||||
_In_reads_(cbSalt) PCBYTE pbSalt,
|
||||
SIZE_T cbSalt,
|
||||
UINT32 uKeyDerivationRate,
|
||||
UINT64 uIndex,
|
||||
UINT32 uIndexWidth,
|
||||
BYTE label,
|
||||
_Out_writes_(cbOutput) PBYTE pbOutput,
|
||||
SIZE_T cbOutput)
|
||||
{
|
||||
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
|
||||
BYTE X[16] = { 0 };
|
||||
|
||||
//
|
||||
// uIndexWidth must be one of 0, 32 or 48. RFC 3711 defines SRTP indices to be
|
||||
// 48-bits. SRTCP indices were first specified as 32-bit values and then updated to
|
||||
// 48-bits by Errata ID 3712. uIndexWidth parameter allows specifying the width of
|
||||
// the uIndex parameter for both SRTP and SRTCP indices. The test vectors use
|
||||
// 32-bit SRTCP index values.
|
||||
//
|
||||
// The default value of 0 is equivalent to setting uIndexWidth to 48.
|
||||
if (uIndexWidth == 0)
|
||||
{
|
||||
uIndexWidth = 48;
|
||||
}
|
||||
else if (uIndexWidth != 32 && uIndexWidth != 48)
|
||||
{
|
||||
scError = SYMCRYPT_INVALID_ARGUMENT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (cbSalt != SYMCRYPT_SRTP_KDF_SALT_SIZE)
|
||||
{
|
||||
scError = SYMCRYPT_INVALID_ARGUMENT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// uKeyDerivationRate must be zero or 2^i for 0 <= i <= 24.
|
||||
// This is verified by checking both it is not greater than 2^24 and it is either zero or a power of two.
|
||||
if( (uKeyDerivationRate > (1 << 24)) || ((uKeyDerivationRate & (uKeyDerivationRate - 1)) != 0) )
|
||||
{
|
||||
scError = SYMCRYPT_INVALID_ARGUMENT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Initialize X to Salt || 0
|
||||
memcpy(X, pbSalt, cbSalt);
|
||||
|
||||
// (uIndex DIV uKeyDerivationRate) operation can be performed with a right shift as
|
||||
// uKeyDerivationRate is either zero or a power of 2. When uKeyDerivationRate is zero,
|
||||
// DIV operation should evaluate to zero, which can be performed by shifting uIndex by 48 bits,
|
||||
// i.e., maximum value it may have.
|
||||
UINT32 kdrShift = 48;
|
||||
if (uKeyDerivationRate)
|
||||
{
|
||||
for (UINT32 i = 0; i <= 24; i++)
|
||||
{
|
||||
if (uKeyDerivationRate == (1UL << i))
|
||||
{
|
||||
kdrShift = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT64 r = uIndex >> kdrShift;
|
||||
|
||||
UINT64 key_id = ((UINT64)label << uIndexWidth) | r;
|
||||
|
||||
// XOR key_id into salt
|
||||
//
|
||||
// X = S0 ... |S6 ... S13| 0 0
|
||||
// | key_id |
|
||||
//
|
||||
PBYTE pbXorPos = &X[SYMCRYPT_SRTP_KDF_SALT_SIZE - sizeof(key_id)];
|
||||
UINT64 uSaltLsb = SYMCRYPT_LOAD_MSBFIRST64(pbXorPos);
|
||||
SYMCRYPT_STORE_MSBFIRST64(pbXorPos, uSaltLsb ^ key_id);
|
||||
|
||||
//
|
||||
// We break the read-once/write once rule here by writing to the pbOutput buffer twice.
|
||||
// The first write wipes the buffer so that we get the raw keystream bytes from AES-CTR encryption.
|
||||
// The second write to pbOutput occurs with the SymCryptAesCtrMsb64() call that produces the keystream bytes.
|
||||
//
|
||||
// Modification of pbOutput between the two calls does not leak any information, it just results in flipping of the
|
||||
// corresponding bits of the correct output.
|
||||
SymCryptWipe(pbOutput, cbOutput);
|
||||
SymCryptAesCtrMsb64(&pExpandedKey->aesExpandedKey, X, pbOutput, pbOutput, cbOutput & ~0xf);
|
||||
|
||||
// SymCryptAesCtrMsb64 only processes full blocks. If cbOutput is not a multiple of 16 we generate the last block of
|
||||
// keystream to local buffer and copy the necessary number of bytes to output.
|
||||
if (cbOutput & 0xf)
|
||||
{
|
||||
BYTE lastBlockBytes[16] = { 0 };
|
||||
|
||||
SymCryptAesCtrMsb64(&pExpandedKey->aesExpandedKey, X, lastBlockBytes, lastBlockBytes, 16);
|
||||
|
||||
memcpy(pbOutput + 16 * (cbOutput / 16), lastBlockBytes, cbOutput & 0xf);
|
||||
|
||||
SymCryptWipeKnownSize(lastBlockBytes, sizeof(lastBlockBytes));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
return scError;
|
||||
}
|
||||
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSrtpKdf(
|
||||
_In_reads_(cbKey) PCBYTE pbKey,
|
||||
SIZE_T cbKey,
|
||||
_In_reads_(cbSalt) PCBYTE pbSalt,
|
||||
SIZE_T cbSalt,
|
||||
UINT32 uKeyDerivationRate,
|
||||
UINT64 uIndex,
|
||||
UINT32 uIndexWidth,
|
||||
BYTE label,
|
||||
_Out_writes_(cbOutput) PBYTE pbOutput,
|
||||
SIZE_T cbOutput)
|
||||
{
|
||||
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
|
||||
SYMCRYPT_SRTPKDF_EXPANDED_KEY expandedKey;
|
||||
|
||||
scError = SymCryptSrtpKdfExpandKey(&expandedKey, pbKey, cbKey);
|
||||
|
||||
if (scError != SYMCRYPT_NO_ERROR)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
scError = SymCryptSrtpKdfDerive(&expandedKey,
|
||||
pbSalt, cbSalt,
|
||||
uKeyDerivationRate,
|
||||
uIndex, uIndexWidth,
|
||||
label,
|
||||
pbOutput, cbOutput);
|
||||
|
||||
cleanup:
|
||||
|
||||
SymCryptWipeKnownSize(&expandedKey, sizeof(expandedKey));
|
||||
|
||||
return scError;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// srtp_kdf_selftest.c
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
|
||||
static const BYTE pbKey[] =
|
||||
{
|
||||
0xc4, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72, 0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90
|
||||
};
|
||||
|
||||
static const BYTE pbSalt[] =
|
||||
{
|
||||
0x0e, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56, 0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6
|
||||
};
|
||||
|
||||
static const UINT64 uIndex = 0x487165649cca;
|
||||
|
||||
static const UINT32 uSRTCPIndex = 0x56f3f197;
|
||||
|
||||
static const UINT32 uKeyDerivationRate = 0;
|
||||
|
||||
static const BYTE label = SYMCRYPT_SRTP_ENCRYPTION_KEY;
|
||||
|
||||
static const BYTE pbResultAes128[] =
|
||||
{
|
||||
0xdc, 0x38, 0x21, 0x92, 0xab, 0x65, 0x10, 0x8a, 0x86, 0xb2, 0x59, 0xb6, 0x1b, 0x3a, 0xf4, 0x6f
|
||||
};
|
||||
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSrtpKdfSelfTest()
|
||||
{
|
||||
SYMCRYPT_SRTPKDF_EXPANDED_KEY expandedKey;
|
||||
SYMCRYPT_ALIGN BYTE rbResultAes128[sizeof(pbResultAes128)];
|
||||
|
||||
SymCryptSrtpKdfExpandKey(&expandedKey, pbKey, sizeof(pbKey));
|
||||
|
||||
SymCryptSrtpKdfDerive(&expandedKey,
|
||||
pbSalt, sizeof(pbSalt),
|
||||
uKeyDerivationRate,
|
||||
(label < SYMCRYPT_SRTCP_ENCRYPTION_KEY) ? uIndex : uSRTCPIndex,
|
||||
(label < SYMCRYPT_SRTCP_ENCRYPTION_KEY) ? 48 : 32,
|
||||
label,
|
||||
rbResultAes128, sizeof(rbResultAes128));
|
||||
|
||||
SymCryptInjectError(rbResultAes128, sizeof(rbResultAes128));
|
||||
|
||||
if (memcmp(rbResultAes128, pbResultAes128, sizeof(pbResultAes128)) != 0)
|
||||
{
|
||||
SymCryptFatal('srtp');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
//
|
||||
// ssh_kdf.c
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
|
||||
//
|
||||
|
||||
//
|
||||
// This module implements SSH-KDF specified in RFC 4253 Section 7.2.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSshKdfExpandKey(
|
||||
_Out_ PSYMCRYPT_SSHKDF_EXPANDED_KEY pExpandedKey,
|
||||
_In_ PCSYMCRYPT_HASH pHashFunc,
|
||||
_In_reads_(cbKey) PCBYTE pbKey,
|
||||
SIZE_T cbKey)
|
||||
{
|
||||
pExpandedKey->pHashFunc = pHashFunc;
|
||||
|
||||
SymCryptHashInit(pHashFunc, &pExpandedKey->hashState);
|
||||
SymCryptHashAppend(pHashFunc, &pExpandedKey->hashState, pbKey, cbKey);
|
||||
|
||||
return SYMCRYPT_NO_ERROR;
|
||||
}
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSshKdfDerive(
|
||||
_In_ PCSYMCRYPT_SSHKDF_EXPANDED_KEY pExpandedKey,
|
||||
_In_reads_(cbHashValue) PCBYTE pbHashValue,
|
||||
SIZE_T cbHashValue,
|
||||
BYTE label,
|
||||
_In_reads_(cbSessionId) PCBYTE pbSessionId,
|
||||
SIZE_T cbSessionId,
|
||||
_Inout_updates_(cbOutput) PBYTE pbOutput,
|
||||
SIZE_T cbOutput)
|
||||
{
|
||||
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
|
||||
SYMCRYPT_HASH_STATE hashState;
|
||||
|
||||
PCBYTE pcbOutputSave = pbOutput;
|
||||
PCSYMCRYPT_HASH pHashFunc = pExpandedKey->pHashFunc;
|
||||
SIZE_T cbHashResultSize = SymCryptHashResultSize(pHashFunc);
|
||||
|
||||
|
||||
while (cbOutput > 0)
|
||||
{
|
||||
SIZE_T cbGeneratedOutput = pbOutput - pcbOutputSave;
|
||||
|
||||
SymCryptHashStateCopy(pHashFunc, &pExpandedKey->hashState, &hashState);
|
||||
SymCryptHashAppend(pHashFunc, &hashState, pbHashValue, cbHashValue); // hashState has (K || H)
|
||||
|
||||
// label and session ID are appended only in the first iteration
|
||||
if (cbGeneratedOutput == 0)
|
||||
{
|
||||
SymCryptHashAppend(pHashFunc, &hashState, &label, 1);
|
||||
SymCryptHashAppend(pHashFunc, &hashState, pbSessionId, cbSessionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We break the read-once write-once rule here by appending data to a
|
||||
// hash computation from pbOutput that was written by SymCryptHashResult()
|
||||
// below.
|
||||
// Modification of data in pbOutput buffer after it's written and before
|
||||
// used again will have uncontrolled disturbances in the hash output and cannot
|
||||
// be used to gain knowledge about the secret key.
|
||||
SymCryptHashAppend(pHashFunc, &hashState, pcbOutputSave, cbGeneratedOutput); // hashState has (K || H || K1 .. Ki)
|
||||
}
|
||||
|
||||
SymCryptHashResult(pHashFunc, &hashState, pbOutput, cbOutput);
|
||||
|
||||
SIZE_T bytesCopied = SYMCRYPT_MIN(cbOutput, cbHashResultSize);
|
||||
|
||||
pbOutput += bytesCopied;
|
||||
cbOutput -= bytesCopied;
|
||||
}
|
||||
|
||||
return scError;
|
||||
}
|
||||
|
||||
|
||||
SYMCRYPT_ERROR
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSshKdf(
|
||||
_In_ PCSYMCRYPT_HASH pHashFunc,
|
||||
_In_reads_(cbKey) PCBYTE pbKey,
|
||||
SIZE_T cbKey,
|
||||
_In_reads_(cbHashValue) PCBYTE pbHashValue,
|
||||
SIZE_T cbHashValue,
|
||||
BYTE label,
|
||||
_In_reads_(cbSessionId) PCBYTE pbSessionId,
|
||||
SIZE_T cbSessionId,
|
||||
_Out_writes_(cbOutput) PBYTE pbOutput,
|
||||
SIZE_T cbOutput)
|
||||
{
|
||||
SYMCRYPT_SSHKDF_EXPANDED_KEY expandedKey;
|
||||
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
|
||||
|
||||
scError = SymCryptSshKdfExpandKey(&expandedKey, pHashFunc, pbKey, cbKey);
|
||||
|
||||
if (scError != SYMCRYPT_NO_ERROR)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
scError = SymCryptSshKdfDerive(&expandedKey,
|
||||
pbHashValue, cbHashValue,
|
||||
label,
|
||||
pbSessionId, cbSessionId,
|
||||
pbOutput, cbOutput);
|
||||
|
||||
cleanup:
|
||||
|
||||
SymCryptWipeKnownSize(&expandedKey, sizeof(expandedKey));
|
||||
|
||||
return scError;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// ssh_kdf_sha256.c
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
|
||||
|
||||
static const BYTE pbKey[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x81, 0x00, 0x87, 0x5c, 0x55, 0x1c, 0xef, 0x52, 0x6a, 0x4a, 0x8b, 0xe1, 0xa7,
|
||||
0xdf, 0x27, 0xe9, 0xed, 0x35, 0x4b, 0xac, 0x9a, 0xfb, 0x71, 0xf5, 0x3d, 0xba, 0xe9, 0x05, 0x67,
|
||||
0x9d, 0x14, 0xf9, 0xfa, 0xf2, 0x46, 0x9c, 0x53, 0x45, 0x7c, 0xf8, 0x0a, 0x36, 0x6b, 0xe2, 0x78,
|
||||
0x96, 0x5b, 0xa6, 0x25, 0x52, 0x76, 0xca, 0x2d, 0x9f, 0x4a, 0x97, 0xd2, 0x71, 0xf7, 0x1e, 0x50,
|
||||
0xd8, 0xa9, 0xec, 0x46, 0x25, 0x3a, 0x6a, 0x90, 0x6a, 0xc2, 0xc5, 0xe4, 0xf4, 0x8b, 0x27, 0xa6,
|
||||
0x3c, 0xe0, 0x8d, 0x80, 0x39, 0x0a, 0x49, 0x2a, 0xa4, 0x3b, 0xad, 0x9d, 0x88, 0x2c, 0xca, 0xc2,
|
||||
0x3d, 0xac, 0x88, 0xbc, 0xad, 0xa4, 0xb4, 0xd4, 0x26, 0xa3, 0x62, 0x08, 0x3d, 0xab, 0x65, 0x69,
|
||||
0xc5, 0x4c, 0x22, 0x4d, 0xd2, 0xd8, 0x76, 0x43, 0xaa, 0x22, 0x76, 0x93, 0xe1, 0x41, 0xad, 0x16,
|
||||
0x30, 0xce, 0x13, 0x14, 0x4e
|
||||
};
|
||||
|
||||
static const BYTE pbHash[] =
|
||||
{
|
||||
0x0e, 0x68, 0x3f, 0xc8, 0xa9, 0xed, 0x7c, 0x2f, 0xf0, 0x2d, 0xef, 0x23, 0xb2, 0x74, 0x5e, 0xbc,
|
||||
0x99, 0xb2, 0x67, 0xda, 0xa8, 0x6a, 0x4a, 0xa7, 0x69, 0x72, 0x39, 0x08, 0x82, 0x53, 0xf6, 0x42
|
||||
};
|
||||
|
||||
static const BYTE pbSessionId[] =
|
||||
{
|
||||
0x0e, 0x68, 0x3f, 0xc8, 0xa9, 0xed, 0x7c, 0x2f, 0xf0, 0x2d, 0xef, 0x23, 0xb2, 0x74, 0x5e, 0xbc,
|
||||
0x99, 0xb2, 0x67, 0xda, 0xa8, 0x6a, 0x4a, 0xa7, 0x69, 0x72, 0x39, 0x08, 0x82, 0x53, 0xf6, 0x42
|
||||
};
|
||||
|
||||
static const BYTE label = SYMCRYPT_SSHKDF_ENCRYPTION_KEY_CLIENT_TO_SERVER;
|
||||
|
||||
static const BYTE pbResult[] =
|
||||
{
|
||||
0x4a, 0x63, 0x14, 0xd2, 0xf7, 0x51, 0x1b, 0xf8, 0x8f, 0xad, 0x39, 0xfb, 0x68, 0x92, 0xf3, 0xf2, 0x18, 0xca, 0xfd, 0x53, 0x0e, 0x72, 0xfe, 0x43
|
||||
};
|
||||
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSshKdfSha256SelfTest()
|
||||
{
|
||||
SYMCRYPT_SSHKDF_EXPANDED_KEY expandedKey;
|
||||
SYMCRYPT_ALIGN BYTE rbResult[sizeof(pbResult)];
|
||||
|
||||
SymCryptSshKdfExpandKey(&expandedKey, SymCryptSha256Algorithm, pbKey, sizeof(pbKey));
|
||||
|
||||
SymCryptSshKdfDerive(&expandedKey,
|
||||
pbHash, sizeof(pbHash),
|
||||
label,
|
||||
pbSessionId, sizeof(pbSessionId),
|
||||
rbResult, sizeof(rbResult)
|
||||
);
|
||||
|
||||
SymCryptInjectError(rbResult, sizeof(rbResult));
|
||||
|
||||
if (memcmp(rbResult, pbResult, sizeof(pbResult)) != 0)
|
||||
{
|
||||
SymCryptFatal('sshk');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
//
|
||||
// ssh_kdf_sha512.c
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
|
||||
|
||||
static const BYTE pbKey[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x80, 0x57, 0x53, 0x08, 0xca, 0x39, 0x57, 0x98, 0xbb, 0x21, 0xec, 0x54, 0x38,
|
||||
0xc4, 0x6a, 0x88, 0xff, 0xa3, 0xf7, 0xf7, 0x67, 0x1c, 0x06, 0xf9, 0x24, 0xab, 0xf7, 0xc3, 0xcf,
|
||||
0xb4, 0x6c, 0x78, 0xc0, 0x25, 0x59, 0x6e, 0x4a, 0xba, 0x50, 0xc3, 0x27, 0x10, 0x89, 0x18, 0x4a,
|
||||
0x44, 0x7a, 0x57, 0x1a, 0xbb, 0x7f, 0x4a, 0x1b, 0x1c, 0x41, 0xf5, 0xd5, 0xca, 0x80, 0x62, 0x94,
|
||||
0x0d, 0x43, 0x69, 0x77, 0x85, 0x89, 0xfd, 0xe8, 0x1a, 0x71, 0xb2, 0x22, 0x8f, 0x01, 0x8c, 0x4c,
|
||||
0x83, 0x6c, 0xf3, 0x89, 0xf8, 0x54, 0xf8, 0x6d, 0xe7, 0x1a, 0x68, 0xb1, 0x69, 0x3f, 0xe8, 0xff,
|
||||
0xa1, 0xc5, 0x9c, 0xe7, 0xe9, 0xf9, 0x22, 0x3d, 0xeb, 0xad, 0xa2, 0x56, 0x6d, 0x2b, 0x0e, 0x56,
|
||||
0x78, 0xa4, 0x8b, 0xfb, 0x53, 0x0e, 0x7b, 0xee, 0x42, 0xbd, 0x2a, 0xc7, 0x30, 0x4a, 0x0a, 0x5a,
|
||||
0xe3, 0x39, 0xa2, 0xcd
|
||||
};
|
||||
|
||||
static const BYTE pbHash[] =
|
||||
{
|
||||
0xa4, 0x12, 0x5a, 0xa9, 0x89, 0x80, 0x92, 0xca, 0x50, 0xc3, 0xc1, 0x63, 0x1c, 0x03, 0xdc, 0xbc,
|
||||
0x9d, 0xf9, 0x5c, 0xeb, 0xb4, 0x09, 0x88, 0x1e, 0x58, 0x01, 0x08, 0xb6, 0xcc, 0x47, 0x04, 0xb7,
|
||||
0x6c, 0xc7, 0x7b, 0x87, 0x95, 0xfd, 0x59, 0x40, 0x56, 0x1e, 0x32, 0x24, 0xcc, 0x75, 0x84, 0x85,
|
||||
0x18, 0x99, 0x2b, 0xd8, 0xd9, 0xb7, 0x0f, 0xe0, 0xfc, 0x97, 0x7a, 0x47, 0x60, 0x63, 0xc8, 0xbf
|
||||
};
|
||||
|
||||
static const BYTE pbSessionId[] =
|
||||
{
|
||||
0xa4, 0x12, 0x5a, 0xa9, 0x89, 0x80, 0x92, 0xca, 0x50, 0xc3, 0xc1, 0x63, 0x1c, 0x03, 0xdc, 0xbc,
|
||||
0x9d, 0xf9, 0x5c, 0xeb, 0xb4, 0x09, 0x88, 0x1e, 0x58, 0x01, 0x08, 0xb6, 0xcc, 0x47, 0x04, 0xb7,
|
||||
0x6c, 0xc7, 0x7b, 0x87, 0x95, 0xfd, 0x59, 0x40, 0x56, 0x1e, 0x32, 0x24, 0xcc, 0x75, 0x84, 0x85,
|
||||
0x18, 0x99, 0x2b, 0xd8, 0xd9, 0xb7, 0x0f, 0xe0, 0xfc, 0x97, 0x7a, 0x47, 0x60, 0x63, 0xc8, 0xbf
|
||||
};
|
||||
|
||||
static const BYTE label = SYMCRYPT_SSHKDF_ENCRYPTION_KEY_CLIENT_TO_SERVER;
|
||||
|
||||
static const BYTE pbResult[] =
|
||||
{
|
||||
0x7e, 0x4a, 0x72, 0x1f, 0xb7, 0x37, 0x9e, 0xbb, 0x42, 0x33, 0x06, 0x46, 0x4d, 0x57, 0xdb, 0x46,
|
||||
0xaf, 0xa3, 0xcc, 0xa1, 0x0a, 0x1d, 0x7f, 0xeb
|
||||
};
|
||||
|
||||
VOID
|
||||
SYMCRYPT_CALL
|
||||
SymCryptSshKdfSha512SelfTest()
|
||||
{
|
||||
SYMCRYPT_SSHKDF_EXPANDED_KEY expandedKey;
|
||||
SYMCRYPT_ALIGN BYTE rbResult[sizeof(pbResult)];
|
||||
|
||||
SymCryptSshKdfExpandKey(&expandedKey, SymCryptSha512Algorithm, pbKey, sizeof(pbKey));
|
||||
|
||||
SymCryptSshKdfDerive(&expandedKey,
|
||||
pbHash, sizeof(pbHash),
|
||||
label,
|
||||
pbSessionId, sizeof(pbSessionId),
|
||||
rbResult, sizeof(rbResult)
|
||||
);
|
||||
|
||||
SymCryptInjectError(rbResult, sizeof(rbResult));
|
||||
|
||||
if (memcmp(rbResult, pbResult, sizeof(pbResult)) != 0)
|
||||
{
|
||||
SymCryptFatal('sshk');
|
||||
}
|
||||
}
|
|
@ -411,4 +411,13 @@ VERSION_103.0
|
|||
{
|
||||
global:
|
||||
SymCryptFipsGetSelftestsPerformed;
|
||||
} VERSION_102.0;
|
||||
SymCryptSrtpKdf;
|
||||
SymCryptSrtpKdfExpandKey;
|
||||
SymCryptSrtpKdfDerive;
|
||||
SymCryptSrtpKdfSelfTest;
|
||||
SymCryptSshKdf;
|
||||
SymCryptSshKdfExpandKey;
|
||||
SymCryptSshKdfDerive;
|
||||
SymCryptSshKdfSha256SelfTest;
|
||||
SymCryptSshKdfSha512SelfTest;
|
||||
} VERSION_102.0;
|
||||
|
|
|
@ -59,6 +59,11 @@ VOID __attribute__((constructor)) SymCryptModuleMain()
|
|||
|
||||
SymCryptPbkdf2_HmacSha1SelfTest();
|
||||
|
||||
SymCryptSrtpKdfSelfTest();
|
||||
|
||||
SymCryptSshKdfSha256SelfTest();
|
||||
SymCryptSshKdfSha512SelfTest();
|
||||
|
||||
g_SymCryptFipsSelftestsPerformed |= SYMCRYPT_SELFTEST_ALGORITHM_STARTUP;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -384,6 +384,8 @@ typedef enum _KDF_ARGUMENT_TYPE {
|
|||
KdfArgumentSp800_108 = 3,
|
||||
KdfArgumentTlsPrf = 4,
|
||||
KdfArgumentHkdf = 5,
|
||||
KdfArgumentSshKdf = 6,
|
||||
KdfArgumentSrtpKdf = 7,
|
||||
} KDF_ARGUMENT_TYPE;
|
||||
|
||||
typedef struct _KDF_GENERIC_ARGUMENTS {
|
||||
|
@ -418,6 +420,24 @@ typedef struct _KDF_HKDF_ARGUMENTS {
|
|||
SIZE_T cbInfo;
|
||||
} KDF_HKDF_ARGUMENTS;
|
||||
|
||||
typedef struct _KDF_SSHKDF_ARGUMENTS {
|
||||
PCSYMCRYPT_HASH hash;
|
||||
PCBYTE pbHashValue;
|
||||
SIZE_T cbHashValue;
|
||||
PCBYTE pbSessionId;
|
||||
SIZE_T cbSessionId;
|
||||
BYTE label;
|
||||
} KDF_SSHKDF_ARGUMENTS;
|
||||
|
||||
typedef struct _KDF_SRTPKDF_ARGUMENTS {
|
||||
PCBYTE pbSalt;
|
||||
SIZE_T cbSalt;
|
||||
UINT32 uKeyDerivationRate;
|
||||
UINT64 uIndex;
|
||||
UINT32 uIndexWidth;
|
||||
BYTE label;
|
||||
} KDF_SRTPKDF_ARGUMENTS;
|
||||
|
||||
typedef struct _KDF_ARGUMENTS {
|
||||
KDF_ARGUMENT_TYPE argType;
|
||||
union {
|
||||
|
@ -426,6 +446,8 @@ typedef struct _KDF_ARGUMENTS {
|
|||
KDF_SP800_108_ARGUMENTS uSp800_108;
|
||||
KDF_TLSPRF_ARGUMENTS uTlsPrf;
|
||||
KDF_HKDF_ARGUMENTS uHkdf;
|
||||
KDF_SSHKDF_ARGUMENTS uSshKdf;
|
||||
KDF_SRTPKDF_ARGUMENTS uSrtpKdf;
|
||||
};
|
||||
} KDF_ARGUMENTS, *PKDF_ARGUMENTS;
|
||||
typedef const KDF_ARGUMENTS *PCKDF_ARGUMENTS;
|
||||
|
|
|
@ -86,7 +86,7 @@ BString katParseData( KAT_ITEM & item, LPCSTR name );
|
|||
//
|
||||
|
||||
LONGLONG katParseInteger( KAT_ITEM & item, LPCSTR name );
|
||||
|
||||
|
||||
BOOL katIsFieldPresent( KAT_ITEM & item, LPCSTR name );
|
||||
|
||||
const KAT_DATA_ITEM * findDataItem( KAT_ITEM & item, LPCSTR name );
|
||||
|
|
|
@ -265,6 +265,15 @@
|
|||
#define ScDispatchSymCryptHkdfDerive(...) SCTEST_CALL_DISPATCHFN(SymCryptHkdfDerive, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptHkdf(...) SCTEST_CALL_DISPATCHFN(SymCryptHkdf, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptHkdfSelfTest(...) SCTEST_CALL_DISPATCHFN(SymCryptHkdfSelfTest, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptSshKdf(...) SCTEST_CALL_DISPATCHFN(SymCryptSshKdf, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptSshKdfExpandKey(...) SCTEST_CALL_DISPATCHFN(SymCryptSshKdfExpandKey, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptSshKdfDerive(...) SCTEST_CALL_DISPATCHFN(SymCryptSshKdfDerive, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptSshKdfSha256SelfTest(...) SCTEST_CALL_DISPATCHFN(SymCryptSshKdfSha256SelfTest, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptSshKdfSha512SelfTest(...) SCTEST_CALL_DISPATCHFN(SymCryptSshKdfSha512SelfTest, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptSrtpKdf(...) SCTEST_CALL_DISPATCHFN(SymCryptSrtpKdf, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptSrtpKdfExpandKey(...) SCTEST_CALL_DISPATCHFN(SymCryptSrtpKdfExpandKey, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptSrtpKdfDerive(...) SCTEST_CALL_DISPATCHFN(SymCryptSrtpKdfDerive, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptSrtpKdfSelfTest(...) SCTEST_CALL_DISPATCHFN(SymCryptSrtpKdfSelfTest, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptRngAesInstantiate(...) SCTEST_CALL_DISPATCHFN(SymCryptRngAesInstantiate, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptRngAesGenerate(...) SCTEST_CALL_DISPATCHFN(SymCryptRngAesGenerate, __VA_ARGS__)
|
||||
#define ScDispatchSymCryptRngAesReseed(...) SCTEST_CALL_DISPATCHFN(SymCryptRngAesReseed, __VA_ARGS__)
|
||||
|
|
|
@ -272,6 +272,15 @@
|
|||
#define ScShimSymCryptHkdfDerive(...) SCTEST_CALL_SCIMPFN(SymCryptHkdfDerive, __VA_ARGS__)
|
||||
#define ScShimSymCryptHkdf(...) SCTEST_CALL_SCIMPFN(SymCryptHkdf, __VA_ARGS__)
|
||||
#define ScShimSymCryptHkdfSelfTest(...) SCTEST_CALL_SCIMPFN(SymCryptHkdfSelfTest, __VA_ARGS__)
|
||||
#define ScShimSymCryptSshKdf(...) SCTEST_CALL_SCIMPFN(SymCryptSshKdf, __VA_ARGS__)
|
||||
#define ScShimSymCryptSshKdfExpandKey(...) SCTEST_CALL_SCIMPFN(SymCryptSshKdfExpandKey, __VA_ARGS__)
|
||||
#define ScShimSymCryptSshKdfDerive(...) SCTEST_CALL_SCIMPFN(SymCryptSshKdfDerive, __VA_ARGS__)
|
||||
#define ScShimSymCryptSshKdfSha256SelfTest(...) SCTEST_CALL_SCIMPFN(SymCryptSshKdfSha256SelfTest, __VA_ARGS__)
|
||||
#define ScShimSymCryptSshKdfSha512SelfTest(...) SCTEST_CALL_SCIMPFN(SymCryptSshKdfSha512SelfTest, __VA_ARGS__)
|
||||
#define ScShimSymCryptSrtpKdf(...) SCTEST_CALL_SCIMPFN(SymCryptSrtpKdf, __VA_ARGS__)
|
||||
#define ScShimSymCryptSrtpKdfExpandKey(...) SCTEST_CALL_SCIMPFN(SymCryptSrtpKdfExpandKey, __VA_ARGS__)
|
||||
#define ScShimSymCryptSrtpKdfDerive(...) SCTEST_CALL_SCIMPFN(SymCryptSrtpKdfDerive, __VA_ARGS__)
|
||||
#define ScShimSymCryptSrtpKdfSelfTest(...) SCTEST_CALL_SCIMPFN(SymCryptSrtpKdfSelfTest, __VA_ARGS__)
|
||||
#define ScShimSymCryptRngAesInstantiate(...) SCTEST_CALL_SCIMPFN(SymCryptRngAesInstantiate, __VA_ARGS__)
|
||||
#define ScShimSymCryptRngAesGenerate(...) SCTEST_CALL_SCIMPFN(SymCryptRngAesGenerate, __VA_ARGS__)
|
||||
#define ScShimSymCryptRngAesReseed(...) SCTEST_CALL_SCIMPFN(SymCryptRngAesReseed, __VA_ARGS__)
|
||||
|
|
|
@ -259,6 +259,18 @@ public:
|
|||
SYMCRYPT_HKDF_EXPANDED_KEY key;
|
||||
};
|
||||
|
||||
template<class BaseAlg>
|
||||
class KdfImpState<ImpXxx, AlgSshKdf, BaseAlg> {
|
||||
public:
|
||||
SYMCRYPT_SSHKDF_EXPANDED_KEY key;
|
||||
};
|
||||
|
||||
template<class BaseAlg>
|
||||
class KdfImpState<ImpXxx, AlgSrtpKdf, BaseAlg> {
|
||||
public:
|
||||
SYMCRYPT_SRTPKDF_EXPANDED_KEY key;
|
||||
};
|
||||
|
||||
template<>
|
||||
class XtsImpState<ImpXxx, AlgXtsAes> {
|
||||
public:
|
||||
|
|
|
@ -60,6 +60,9 @@ const SELFTEST_INFO g_selfTests[] =
|
|||
{&SymCryptParallelSha256Selftest, "ParallelSha256" },
|
||||
{&SymCryptParallelSha384Selftest, "ParallelSha384" },
|
||||
{&SymCryptParallelSha512Selftest, "ParallelSha512" },
|
||||
{&SymCryptSrtpKdfSelfTest, "SrtpKdf" },
|
||||
{&SymCryptSshKdfSha256SelfTest, "SshKdfSha256" },
|
||||
{&SymCryptSshKdfSha512SelfTest, "SshKdfSha512" },
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
|
|
@ -701,6 +701,16 @@ public:
|
|||
const static char * name;
|
||||
};
|
||||
|
||||
class AlgSshKdf{
|
||||
public:
|
||||
const static char * name;
|
||||
};
|
||||
|
||||
class AlgSrtpKdf{
|
||||
public:
|
||||
const static char * name;
|
||||
};
|
||||
|
||||
class AlgHkdf{
|
||||
public:
|
||||
const static char * name;
|
||||
|
|
1618
unittest/kat_kdf.dat
1618
unittest/kat_kdf.dat
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -112,6 +112,10 @@ const char * AlgTlsPrf1_1::name = "TlsPrf1_1";
|
|||
|
||||
const char * AlgTlsPrf1_2::name = "TlsPrf1_2";
|
||||
|
||||
const char * AlgSshKdf::name = "SshKdf";
|
||||
|
||||
const char * AlgSrtpKdf::name = "SrtpKdf";
|
||||
|
||||
const char * AlgHkdf::name = "Hkdf";
|
||||
|
||||
const char * AlgXtsAes::name = "XtsAes";
|
||||
|
@ -505,6 +509,8 @@ const char * g_algorithmNames[] = {
|
|||
AlgSp800_108::name,
|
||||
AlgTlsPrf1_1::name,
|
||||
AlgTlsPrf1_2::name,
|
||||
AlgSshKdf::name,
|
||||
AlgSrtpKdf::name,
|
||||
AlgHkdf::name,
|
||||
AlgXtsAes::name,
|
||||
AlgTlsCbcHmacSha1::name,
|
||||
|
|
|
@ -260,6 +260,8 @@ const ALG_MEASURE_PARAMS g_algMeasureParams[] =
|
|||
"TlsPrf1_2HmacSha256" , 0, {32}, { 32, 64, 128, 512, 1024 },
|
||||
"TlsPrf1_2HmacSha384" , 0, {32}, { 32, 64, 128, 512, 1024 },
|
||||
"TlsPrf1_2HmacSha512" , 0, {32}, { 32, 64, 128, 512, 1024 },
|
||||
"SrtpKdfAes" , 0, {16, 24, 32}, {16, 24, 32},
|
||||
"SshKdfSha256" , 0, {128, 256}, {16, 24, 32},
|
||||
"HkdfHmacSha256" , 0, {32}, { 32, 64, 128, 512, 1024 },
|
||||
"HkdfHmacSha1" , 0, {32}, { 32, 64, 128, 512, 1024 },
|
||||
"XtsAes" , 0, {32,48,64}, {512, 1024, 2048, 4096, 8192, 16384, 32768},
|
||||
|
|
|
@ -357,6 +357,42 @@
|
|||
#undef ALG_Name
|
||||
|
||||
|
||||
#define ALG_NAME SSHKDF
|
||||
#define ALG_Name SshKdf
|
||||
|
||||
#define ALG_Base Sha1
|
||||
#include "sc_imp_kdfpattern.cpp"
|
||||
#include "sc_imp_sshkdfpattern.cpp"
|
||||
#undef ALG_Base
|
||||
|
||||
#define ALG_Base Sha256
|
||||
#include "sc_imp_kdfpattern.cpp"
|
||||
#include "sc_imp_sshkdfpattern.cpp"
|
||||
#undef ALG_Base
|
||||
|
||||
#define ALG_Base Sha384
|
||||
#include "sc_imp_kdfpattern.cpp"
|
||||
#include "sc_imp_sshkdfpattern.cpp"
|
||||
#undef ALG_Base
|
||||
|
||||
#define ALG_Base Sha512
|
||||
#include "sc_imp_kdfpattern.cpp"
|
||||
#include "sc_imp_sshkdfpattern.cpp"
|
||||
#undef ALG_Base
|
||||
|
||||
#undef ALG_NAME
|
||||
#undef ALG_Name
|
||||
|
||||
#define ALG_NAME SRTPKDF
|
||||
#define ALG_Name SrtpKdf
|
||||
|
||||
#define ALG_Base Aes
|
||||
#include "sc_imp_srtpkdfpattern.cpp"
|
||||
#undef ALG_Base
|
||||
|
||||
#undef ALG_NAME
|
||||
#undef ALG_Name
|
||||
|
||||
//
|
||||
// There is not enough structure to the CCM & GCM modes to share an implementation
|
||||
//
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
//
|
||||
// Pattern file for the Symcrypt SRTP-KDF implementations.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
|
||||
//
|
||||
|
||||
//
|
||||
// The following (up to // <<<<<<<) is (almost) duplicate code from the sc_imp_kdfpattern.cpp file.
|
||||
// We add it here due to the uniqueness of the expand key algorithm (It takes as input the salt which
|
||||
// for the perf function we set it of size equal to keySize).
|
||||
//
|
||||
|
||||
template<> VOID algImpKeyPerfFunction<ImpXxx, AlgXxx, BaseAlgXxx>(PBYTE buf1, PBYTE buf2, PBYTE buf3, SIZE_T keySize);
|
||||
template<> VOID algImpCleanPerfFunction<ImpXxx, AlgXxx, BaseAlgXxx>(PBYTE buf1, PBYTE buf2, PBYTE buf3);
|
||||
template<> VOID algImpDataPerfFunction<ImpXxx, AlgXxx, BaseAlgXxx>(PBYTE buf1, PBYTE buf2, PBYTE buf3, SIZE_T dataSize);
|
||||
|
||||
//
|
||||
// Empty constructor.
|
||||
//
|
||||
template<>
|
||||
KdfImp<ImpXxx, AlgXxx, BaseAlgXxx>::KdfImp()
|
||||
{
|
||||
m_perfDataFunction = &algImpDataPerfFunction <ImpXxx, AlgXxx, BaseAlgXxx>;
|
||||
m_perfKeyFunction = &algImpKeyPerfFunction <ImpXxx, AlgXxx, BaseAlgXxx>;
|
||||
m_perfCleanFunction = &algImpCleanPerfFunction<ImpXxx, AlgXxx, BaseAlgXxx>;
|
||||
}
|
||||
|
||||
template<>
|
||||
KdfImp<ImpXxx, AlgXxx, BaseAlgXxx>::~KdfImp<ImpXxx, AlgXxx, BaseAlgXxx>()
|
||||
{
|
||||
}
|
||||
|
||||
template<>
|
||||
VOID
|
||||
algImpKeyPerfFunction<ImpXxx, AlgXxx, BaseAlgXxx>(PBYTE buf1, PBYTE buf2, PBYTE buf3, SIZE_T keySize)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(buf3);
|
||||
SYMCRYPT_XxxExpandKey((SYMCRYPT_XXX_EXPANDED_KEY*)buf1, buf2, keySize);
|
||||
}
|
||||
|
||||
template<>
|
||||
VOID
|
||||
algImpCleanPerfFunction<ImpXxx, AlgXxx, BaseAlgXxx>(PBYTE buf1, PBYTE buf2, PBYTE buf3)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(buf2);
|
||||
UNREFERENCED_PARAMETER(buf3);
|
||||
SymCryptWipeKnownSize(buf1, sizeof(SYMCRYPT_XXX_EXPANDED_KEY));
|
||||
}
|
||||
|
||||
// <<<<<<<<<<<<<<<<
|
||||
|
||||
template<>
|
||||
VOID
|
||||
KdfImp<ImpXxx, AlgSrtpKdf, BaseAlgXxx>::derive(
|
||||
_In_reads_(cbKey) PCBYTE pbKey,
|
||||
SIZE_T cbKey,
|
||||
_In_ PKDF_ARGUMENTS pArgs,
|
||||
_Out_writes_(cbDst) PBYTE pbDst,
|
||||
SIZE_T cbDst)
|
||||
{
|
||||
SYMCRYPT_ERROR scError;
|
||||
SYMCRYPT_SRTPKDF_EXPANDED_KEY expandedKey;
|
||||
BYTE buffer1[1024];
|
||||
BYTE buffer2[sizeof(buffer1)];
|
||||
BYTE expandedKeyChecksum1[SYMCRYPT_MARVIN32_RESULT_SIZE];
|
||||
BYTE expandedKeyChecksum2[SYMCRYPT_MARVIN32_RESULT_SIZE];
|
||||
|
||||
CHECK(cbDst <= sizeof(buffer1), "SRTP-KDF output too large");
|
||||
|
||||
|
||||
switch (pArgs->argType)
|
||||
{
|
||||
case KdfArgumentSrtpKdf:
|
||||
break;
|
||||
|
||||
default:
|
||||
CHECK(FALSE, "Unknown argument type for SRTP-KDF");
|
||||
return;
|
||||
}
|
||||
|
||||
scError = ScShimSymCryptSrtpKdfExpandKey(&expandedKey, pbKey, cbKey);
|
||||
CHECK(scError == SYMCRYPT_NO_ERROR, "Error in SymCryptSrtpKdfExpandKey");
|
||||
|
||||
ScShimSymCryptMarvin32(ScShimSymCryptMarvin32DefaultSeed, (PCBYTE)&expandedKey, sizeof(expandedKey), expandedKeyChecksum1);
|
||||
|
||||
// Note: Test vectors use 32-bit SRTCP index values
|
||||
scError = ScShimSymCryptSrtpKdfDerive(&expandedKey,
|
||||
pArgs->uSrtpKdf.pbSalt, pArgs->uSrtpKdf.cbSalt,
|
||||
pArgs->uSrtpKdf.uKeyDerivationRate,
|
||||
pArgs->uSrtpKdf.uIndex, pArgs->uSrtpKdf.label < 3 ? 48 : 32,
|
||||
pArgs->uSrtpKdf.label,
|
||||
buffer1, cbDst);
|
||||
CHECK(scError == SYMCRYPT_NO_ERROR, "Error in SymCryptSrtpKdfDerive");
|
||||
|
||||
ScShimSymCryptMarvin32(ScShimSymCryptMarvin32DefaultSeed, (PCBYTE)&expandedKey, sizeof(expandedKey), expandedKeyChecksum2);
|
||||
CHECK(memcmp(expandedKeyChecksum1, expandedKeyChecksum2, SYMCRYPT_MARVIN32_RESULT_SIZE) == 0, "SymCryptSrtpKdfDerive modified expanded key");
|
||||
|
||||
scError = ScShimSymCryptSrtpKdf(pbKey, cbKey,
|
||||
pArgs->uSrtpKdf.pbSalt, pArgs->uSrtpKdf.cbSalt,
|
||||
pArgs->uSrtpKdf.uKeyDerivationRate,
|
||||
pArgs->uSrtpKdf.uIndex, pArgs->uSrtpKdf.label < 3 ? 48 : 32,
|
||||
pArgs->uSrtpKdf.label,
|
||||
buffer2, cbDst);
|
||||
CHECK(scError == SYMCRYPT_NO_ERROR, "Error in SymCryptSrtpKdf");
|
||||
|
||||
CHECK(memcmp(buffer1, buffer2, cbDst) == 0, "SymCrypt SRTP-KDF calling versions disagree");
|
||||
|
||||
memcpy(pbDst, buffer1, cbDst);
|
||||
}
|
||||
|
||||
template<>
|
||||
VOID
|
||||
algImpDataPerfFunction<ImpXxx, AlgXxx, BaseAlgXxx>(PBYTE buf1, PBYTE buf2, PBYTE buf3, SIZE_T dataSize)
|
||||
{
|
||||
ScShimSymCryptSrtpKdfDerive((PCSYMCRYPT_SRTPKDF_EXPANDED_KEY)buf1,
|
||||
buf2, // pbSalt
|
||||
112 / 8, // cbSalt
|
||||
0, // uKeyDerivationRate
|
||||
0, // uIndex
|
||||
48, // uIndexWidth
|
||||
(BYTE)0, // label
|
||||
buf3, dataSize);
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// Pattern file for the Symcrypt SSH-KDF implementations.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
|
||||
//
|
||||
|
||||
|
||||
template<>
|
||||
VOID
|
||||
KdfImp<ImpXxx, AlgSshKdf, BaseAlgXxx>::derive(
|
||||
_In_reads_(cbKey) PCBYTE pbKey,
|
||||
SIZE_T cbKey,
|
||||
_In_ PKDF_ARGUMENTS pArgs,
|
||||
_Out_writes_(cbDst) PBYTE pbDst,
|
||||
SIZE_T cbDst)
|
||||
{
|
||||
SYMCRYPT_ERROR scError;
|
||||
SYMCRYPT_SSHKDF_EXPANDED_KEY expandedKey;
|
||||
BYTE buffer1[1024];
|
||||
BYTE buffer2[sizeof(buffer1)];
|
||||
BYTE expandedKeyChecksum1[SYMCRYPT_MARVIN32_RESULT_SIZE];
|
||||
BYTE expandedKeyChecksum2[SYMCRYPT_MARVIN32_RESULT_SIZE];
|
||||
|
||||
CHECK(cbDst <= sizeof(buffer1), "SSH-KDF output too large");
|
||||
|
||||
|
||||
switch (pArgs->argType)
|
||||
{
|
||||
case KdfArgumentSshKdf:
|
||||
break;
|
||||
|
||||
default:
|
||||
CHECK(FALSE, "Unknown argument type for SSH-KDF");
|
||||
return;
|
||||
}
|
||||
|
||||
scError = ScShimSymCryptSshKdfExpandKey(&expandedKey, pArgs->uSshKdf.hash, pbKey, cbKey);
|
||||
CHECK(scError == SYMCRYPT_NO_ERROR, "Error in SymCryptSshKdfExpandKey");
|
||||
|
||||
ScShimSymCryptMarvin32(ScShimSymCryptMarvin32DefaultSeed, (PCBYTE)&expandedKey, sizeof(expandedKey), expandedKeyChecksum1);
|
||||
|
||||
scError = ScShimSymCryptSshKdfDerive(&expandedKey,
|
||||
pArgs->uSshKdf.pbHashValue, pArgs->uSshKdf.cbHashValue,
|
||||
pArgs->uSshKdf.label,
|
||||
pArgs->uSshKdf.pbSessionId, pArgs->uSshKdf.cbSessionId,
|
||||
buffer1, cbDst);
|
||||
CHECK(scError == SYMCRYPT_NO_ERROR, "Error in SymCryptSshKdfDerive");
|
||||
|
||||
ScShimSymCryptMarvin32(ScShimSymCryptMarvin32DefaultSeed, (PCBYTE)&expandedKey, sizeof(expandedKey), expandedKeyChecksum2);
|
||||
CHECK(memcmp(expandedKeyChecksum1, expandedKeyChecksum2, SYMCRYPT_MARVIN32_RESULT_SIZE) == 0, "SymCryptSshKdfDerive modified expanded key");
|
||||
|
||||
scError = ScShimSymCryptSshKdf(pArgs->uSshKdf.hash,
|
||||
pbKey, cbKey,
|
||||
pArgs->uSshKdf.pbHashValue, pArgs->uSshKdf.cbHashValue,
|
||||
pArgs->uSshKdf.label,
|
||||
pArgs->uSshKdf.pbSessionId, pArgs->uSshKdf.cbSessionId,
|
||||
buffer2, cbDst);
|
||||
CHECK(scError == SYMCRYPT_NO_ERROR, "Error in SymCryptSshKdf");
|
||||
|
||||
CHECK(memcmp(buffer1, buffer2, cbDst) == 0, "SymCrypt SSH-KDF calling versions disagree");
|
||||
|
||||
memcpy(pbDst, buffer1, cbDst);
|
||||
}
|
||||
|
||||
template<>
|
||||
VOID
|
||||
algImpDataPerfFunction<ImpXxx, AlgXxx, BaseAlgXxx>(PBYTE buf1, PBYTE buf2, PBYTE buf3, SIZE_T dataSize)
|
||||
{
|
||||
PCSYMCRYPT_SSHKDF_EXPANDED_KEY pExpandedKey = (PCSYMCRYPT_SSHKDF_EXPANDED_KEY)buf1;
|
||||
|
||||
ScShimSymCryptSshKdfDerive(pExpandedKey,
|
||||
buf2, pExpandedKey->pHashFunc->resultSize,
|
||||
(BYTE)SYMCRYPT_SSHKDF_ENCRYPTION_KEY_CLIENT_TO_SERVER,
|
||||
buf2, pExpandedKey->pHashFunc->resultSize,
|
||||
buf3, dataSize);
|
||||
}
|
||||
|
|
@ -257,6 +257,13 @@ addSymCryptImplementationToGlobalList()
|
|||
addImplementationToGlobalList<KdfImp<ImpScVariant, AlgHkdf, AlgHmacSha256>>();
|
||||
addImplementationToGlobalList<KdfImp<ImpScVariant, AlgHkdf, AlgHmacSha1>>();
|
||||
|
||||
addImplementationToGlobalList<KdfImp<ImpScVariant, AlgSshKdf, AlgSha1>>();
|
||||
addImplementationToGlobalList<KdfImp<ImpScVariant, AlgSshKdf, AlgSha256>>();
|
||||
addImplementationToGlobalList<KdfImp<ImpScVariant, AlgSshKdf, AlgSha384>>();
|
||||
addImplementationToGlobalList<KdfImp<ImpScVariant, AlgSshKdf, AlgSha512>>();
|
||||
|
||||
addImplementationToGlobalList<KdfImp<ImpScVariant, AlgSrtpKdf, AlgAes>>();
|
||||
|
||||
addImplementationToGlobalList<MacImp<ImpScVariant, AlgPoly1305>>();
|
||||
|
||||
addImplementationToGlobalList<StreamCipherImp<ImpScVariant, AlgRc4>>();
|
||||
|
|
|
@ -63,7 +63,10 @@ const SELFTEST_INFO g_selfTests[] =
|
|||
{&SymCryptParallelSha256Selftest, "ParallelSha256" },
|
||||
{&SymCryptParallelSha384Selftest, "ParallelSha384" },
|
||||
{&SymCryptParallelSha512Selftest, "ParallelSha512" },
|
||||
|
||||
{&SymCryptSrtpKdfSelfTest, "SrtpKdf" },
|
||||
{&SymCryptSshKdfSha256SelfTest, "SshKdfSha256" },
|
||||
{&SymCryptSshKdfSha512SelfTest, "SshKdfSha512" },
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
|
|
@ -418,6 +418,147 @@ testKdfKats()
|
|||
continue;
|
||||
}
|
||||
|
||||
if (katIsFieldPresent(katItem, "session_id"))
|
||||
{
|
||||
args.argType = KdfArgumentSshKdf;
|
||||
CHECK3(katItem.dataItems.size() == 14, "Incorrect number of fields in SSH-KDF record in line %lld", line);
|
||||
|
||||
BString hashName = katParseData(katItem, "hash");
|
||||
|
||||
// The following fields are not used.
|
||||
// We use the size of the data fields from the test vector..
|
||||
//SIZE_T cbSharedSecret = katParseInteger(katItem, "shared secret length");
|
||||
//SIZE_T cbIVLength = katParseInteger(katItem, "iv length");
|
||||
//SIZE_T cbEncryptionKeyLength = katParseInteger(katItem, "encryption key length");
|
||||
|
||||
BString SharedKey = katParseData(katItem, "k");
|
||||
BString HashValue = katParseData(katItem, "h");
|
||||
BString SessionId = katParseData(katItem, "session_id");
|
||||
|
||||
args.uSshKdf.pbHashValue = HashValue.data();
|
||||
args.uSshKdf.cbHashValue = HashValue.size();
|
||||
args.uSshKdf.pbSessionId = SessionId.data();
|
||||
args.uSshKdf.cbSessionId = SessionId.size();
|
||||
args.uSshKdf.hash = nullptr;
|
||||
|
||||
if (!strcmp((const char*)hashName.c_str(), "SHA-1"))
|
||||
{
|
||||
args.uSshKdf.hash = SymCryptSha1Algorithm;
|
||||
}
|
||||
else if (!strcmp((const char*)hashName.c_str(), "SHA-256"))
|
||||
{
|
||||
args.uSshKdf.hash = SymCryptSha256Algorithm;
|
||||
}
|
||||
else if (!strcmp((const char*)hashName.c_str(), "SHA-384"))
|
||||
{
|
||||
args.uSshKdf.hash = SymCryptSha384Algorithm;
|
||||
}
|
||||
else if (!strcmp((const char*)hashName.c_str(), "SHA-512"))
|
||||
{
|
||||
args.uSshKdf.hash = SymCryptSha512Algorithm;
|
||||
}
|
||||
|
||||
CHECK3(args.uSshKdf.hash != nullptr, "Invalid hash function for SSH-KDF record in line %lld", line);
|
||||
|
||||
BString katInitialIV_ClientToServer = katParseData(katItem, "initial iv (client to server)");
|
||||
BString katInitialIV_ServerToClient = katParseData(katItem, "initial iv (server to client)");
|
||||
BString katEncryptionKey_ClientToServer = katParseData(katItem, "encryption key (client to server)");
|
||||
BString katEncryptionKey_ServerToClient = katParseData(katItem, "encryption key (server to client)");
|
||||
BString katIntegrityKey_ClientToServer = katParseData(katItem, "integrity key (client to server)");
|
||||
BString katIntegrityKey_ServerToClient = katParseData(katItem, "integrity key (server to client)");
|
||||
|
||||
args.uSshKdf.label = SYMCRYPT_SSHKDF_IV_CLIENT_TO_SERVER;
|
||||
katKdfSingle(pKdfMultiImp.get(), SharedKey.data(), SharedKey.size(), &args, katInitialIV_ClientToServer.data(), katInitialIV_ClientToServer.size(), line);
|
||||
|
||||
args.uSshKdf.label = SYMCRYPT_SSHKDF_IV_SERVER_TO_CLIENT;
|
||||
katKdfSingle(pKdfMultiImp.get(), SharedKey.data(), SharedKey.size(), &args, katInitialIV_ServerToClient.data(), katInitialIV_ServerToClient.size(), line);
|
||||
|
||||
args.uSshKdf.label = SYMCRYPT_SSHKDF_ENCRYPTION_KEY_CLIENT_TO_SERVER;
|
||||
katKdfSingle(pKdfMultiImp.get(), SharedKey.data(), SharedKey.size(), &args, katEncryptionKey_ClientToServer.data(), katEncryptionKey_ClientToServer.size(), line);
|
||||
|
||||
args.uSshKdf.label = SYMCRYPT_SSHKDF_ENCRYPTION_KEY_SERVER_TO_CLIENT;
|
||||
katKdfSingle(pKdfMultiImp.get(), SharedKey.data(), SharedKey.size(), &args, katEncryptionKey_ServerToClient.data(), katEncryptionKey_ServerToClient.size(), line);
|
||||
|
||||
args.uSshKdf.label = SYMCRYPT_SSHKDF_INTEGRITY_KEY_CLIENT_TO_SERVER;
|
||||
katKdfSingle(pKdfMultiImp.get(), SharedKey.data(), SharedKey.size(), &args, katIntegrityKey_ClientToServer.data(), katIntegrityKey_ClientToServer.size(), line);
|
||||
|
||||
args.uSshKdf.label = SYMCRYPT_SSHKDF_INTEGRITY_KEY_SERVER_TO_CLIENT;
|
||||
katKdfSingle(pKdfMultiImp.get(), SharedKey.data(), SharedKey.size(), &args, katIntegrityKey_ServerToClient.data(), katIntegrityKey_ServerToClient.size(), line);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (katIsFieldPresent(katItem, "srtp k_e"))
|
||||
{
|
||||
args.argType = KdfArgumentSrtpKdf;
|
||||
CHECK3(katItem.dataItems.size() == 12, "Incorrect number of fields in SRTP-KDF record in line %lld", line);
|
||||
|
||||
BString k_master = katParseData(katItem, "k_master");
|
||||
BString master_salt = katParseData(katItem, "master_salt");
|
||||
BString kdr = katParseData(katItem, "kdr");
|
||||
BString index = katParseData(katItem, "index");
|
||||
BString indexSRTCP = katParseData(katItem, "index (srtcp)");
|
||||
|
||||
args.uSrtpKdf.pbSalt = master_salt.data();
|
||||
args.uSrtpKdf.cbSalt = master_salt.size();
|
||||
|
||||
args.uSrtpKdf.uKeyDerivationRate = 0;
|
||||
for (auto x : kdr)
|
||||
{
|
||||
args.uSrtpKdf.uKeyDerivationRate <<= 8;
|
||||
args.uSrtpKdf.uKeyDerivationRate |= x;
|
||||
}
|
||||
|
||||
BString katSRTPk_e = katParseData(katItem, "srtp k_e");
|
||||
BString katSRTPk_a = katParseData(katItem, "srtp k_a");
|
||||
BString katSRTPk_s = katParseData(katItem, "srtp k_s");
|
||||
BString katSRTCPk_e = katParseData(katItem, "srtcp k_e");
|
||||
BString katSRTCPk_a = katParseData(katItem, "srtcp k_a");
|
||||
BString katSRTCPk_s = katParseData(katItem, "srtcp k_s");
|
||||
|
||||
{
|
||||
args.uSrtpKdf.uIndexWidth = 48;
|
||||
|
||||
args.uSrtpKdf.uIndex = 0;
|
||||
for (auto x : index)
|
||||
{
|
||||
args.uSrtpKdf.uIndex <<= 8;
|
||||
args.uSrtpKdf.uIndex |= x;
|
||||
}
|
||||
|
||||
args.uSrtpKdf.label = SYMCRYPT_SRTP_ENCRYPTION_KEY;
|
||||
katKdfSingle(pKdfMultiImp.get(), k_master.data(), k_master.size(), &args, katSRTPk_e.data(), katSRTPk_e.size(), line);
|
||||
|
||||
args.uSrtpKdf.label = SYMCRYPT_SRTP_AUTHENTICATION_KEY;
|
||||
katKdfSingle(pKdfMultiImp.get(), k_master.data(), k_master.size(), &args, katSRTPk_a.data(), katSRTPk_a.size(), line);
|
||||
|
||||
args.uSrtpKdf.label = SYMCRYPT_SRTP_SALTING_KEY;
|
||||
katKdfSingle(pKdfMultiImp.get(), k_master.data(), k_master.size(), &args, katSRTPk_s.data(), katSRTPk_s.size(), line);
|
||||
}
|
||||
|
||||
{
|
||||
args.uSrtpKdf.uIndexWidth = 32;
|
||||
|
||||
args.uSrtpKdf.uIndex = 0;
|
||||
for (auto x : indexSRTCP)
|
||||
{
|
||||
args.uSrtpKdf.uIndex <<= 8;
|
||||
args.uSrtpKdf.uIndex |= x;
|
||||
}
|
||||
|
||||
args.uSrtpKdf.label = SYMCRYPT_SRTCP_ENCRYPTION_KEY;
|
||||
katKdfSingle(pKdfMultiImp.get(), k_master.data(), k_master.size(), &args, katSRTCPk_e.data(), katSRTCPk_e.size(), line);
|
||||
|
||||
args.uSrtpKdf.label = SYMCRYPT_SRTCP_AUTHENTICATION_KEY;
|
||||
katKdfSingle(pKdfMultiImp.get(), k_master.data(), k_master.size(), &args, katSRTCPk_a.data(), katSRTCPk_a.size(), line);
|
||||
|
||||
args.uSrtpKdf.label = SYMCRYPT_SRTCP_SALTING_KEY;
|
||||
katKdfSingle(pKdfMultiImp.get(), k_master.data(), k_master.size(), &args, katSRTCPk_s.data(), katSRTCPk_s.size(), line);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
FATAL2( "Unknown data record at line %lld", line );
|
||||
}
|
||||
|
||||
|
|
|
@ -372,6 +372,15 @@ EXPORTS
|
|||
SymCryptTlsPrf1_2Derive
|
||||
SymCryptTlsPrf1_2ExpandKey
|
||||
SymCryptTlsPrf1_2SelfTest
|
||||
SymCryptSrtpKdf
|
||||
SymCryptSrtpKdfExpandKey
|
||||
SymCryptSrtpKdfDerive
|
||||
SymCryptSrtpKdfSelfTest
|
||||
SymCryptSshKdf
|
||||
SymCryptSshKdfExpandKey
|
||||
SymCryptSshKdfDerive
|
||||
SymCryptSshKdfSha256SelfTest
|
||||
SymCryptSshKdfSha512SelfTest
|
||||
SymCryptUint32Bitsize
|
||||
SymCryptUint32Bytesize
|
||||
SymCryptUint64Bitsize
|
||||
|
|
Загрузка…
Ссылка в новой задаче