Skip to content

Commit f89cbf3

Browse files
committed
Merged PR 11087190: SSKDF implementation
## Description: SSKDF implementation and unit tests.   ## Admin Checklist: - [x] You have updated documentation in symcrypt.h to reflect any changes in behavior - [x] You have updated CHANGELOG.md to reflect any changes in behavior - [x] You have updated symcryptunittest to exercise any new functionality - [x] 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 - [x] If you have introduced functionality that varies based on CPU features, you have manually tested with and without relevant features - [X] If you have made significant changes to a particular algorithm, you have checked that performance numbers reported by symcryptunittest are in line with expectations - [X] If you have added new algorithms/modes, you have updated the status indicator text for the associated modules if necessary Related work items: #51795170
1 parent 2f0cd6e commit f89cbf3

31 files changed

+1614
-66
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ New changes will be listed here as they are developed. The version number is det
44
prior to the creation of a new release, based on the changes contained in that release.
55

66
- Internal self-test changes to support FIPS 140-3 certification
7+
- Add SSKDF implementation
78

89
# Version 103.4.3
910

inc/symcrypt.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5494,10 +5494,9 @@ SymCryptSskdfMacDerive(
54945494
// Parameters:
54955495
// - pExpandedSalt : Pointer to a SYMCRYPT_SSKDF_MAC_EXPANDED_SALT structure that is
54965496
// initialized by a prior call to SymCryptSskdfMacExpandSalt.
5497-
// - cbMacOutputSize : Output size used by the MAC algorithm for intermediate computations.
5498-
// Set to 0 for MACs that don't support variable output sizes, or to use
5499-
// the default output size. The default output size for KMAC128 is 32 bytes,
5500-
// and KMAC256 is 64 bytes.
5497+
// - cbMacOutputSize : Output size used by the MAC algorithm for intermediate computations. Must not be
5498+
// greater than 64 bytes. Set to 0 for MACs that don't support variable output sizes,
5499+
// or to use the default output size. The default output size when KMAC is used is cbResult.
55015500
// - pbSecret, cbSecret : Buffer containing the shared secret.
55025501
// - pbInfo, cbInfo : Buffer containing the fixed info.
55035502
// - pbResult, cbResult : Buffer to store the derived key. Exactly cbResult bytes of output will be generated.
@@ -5541,15 +5540,20 @@ SymCryptSskdfHash(
55415540
//
55425541
// Parameters:
55435542
// - hashAlgorithm : Hash algorithm that will be used in the key derivation.
5544-
// - cbMacOutputSize : Output size used by the hash algorithm for intermediate computations.
5543+
// - cbHashOutputSize : Output size used by the hash algorithm for intermediate computations.
55455544
// Set to 0 for hashes that don't support variable output sizes, or to use
5546-
// the default output size.
5545+
// the default output size. Currently, no allowed hash algorithms support
5546+
// variable output sizes, so this should always be set to 0.
55475547
// - pbSecret, cbSecret : Buffer containing the shared secret.
55485548
// - pbInfo, cbInfo : Buffer containing the fixed info.
55495549
// - pbResult, cbResult : Buffer to store the derived key. Exactly cbResult bytes of output will be generated.
55505550
// Must not exceed 2^{32} - 1 times the result size of hashAlgorithm.
55515551
//
55525552

5553+
VOID
5554+
SYMCRYPT_CALL
5555+
SymCryptSskdfSelfTest(void);
5556+
55535557
//==========================================================================
55545558
// RNG ALGORITHMS
55555559
//==========================================================================

inc/symcrypt_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,7 @@ typedef SYMCRYPT_ERROR (SYMCRYPT_CALL * PSYMCRYPT_MAC_EXPAND_KEY)
15011501
typedef VOID (SYMCRYPT_CALL * PSYMCRYPT_MAC_INIT) ( PVOID pState, PCVOID pExpandedKey );
15021502
typedef VOID (SYMCRYPT_CALL * PSYMCRYPT_MAC_APPEND)( PVOID pState, PCBYTE pbData, SIZE_T cbData );
15031503
typedef VOID (SYMCRYPT_CALL * PSYMCRYPT_MAC_RESULT) ( PVOID pState, PVOID pbResult );
1504+
typedef VOID (SYMCRYPT_CALL * PSYMCRYPT_MAC_RESULT_EX) ( PVOID pState, PVOID pbResult, SIZE_T cbResult );
15041505

15051506
typedef struct _SYMCRYPT_MAC
15061507
{

lib/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ set(SOURCES_COMMON
111111
ssh_kdf.c
112112
ssh_kdf_sha256.c
113113
ssh_kdf_sha512.c
114+
sskdf.c
115+
sskdf_selftest.c
114116
tlsCbcVerify.c
115117
tlsprf_selftest.c
116118
tlsprf.c

lib/sskdf.c

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
//
2+
// sskdf.c
3+
//
4+
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5+
//
6+
7+
//
8+
// This module implements Single-Step KDF as specified in SP800-56C section 4.
9+
//
10+
11+
#include "precomp.h"
12+
13+
//
14+
// See the symcrypt.h file for documentation on what the various functions do.
15+
//
16+
17+
18+
#define SYMCRYPT_SSKDF_KMAC_128_DEFAULT_SALT_SIZE (164)
19+
#define SYMCRYPT_SSKDF_KMAC_256_DEFAULT_SALT_SIZE (132)
20+
#define SYMCRYPT_SSKDF_DEFAULT_SALT_MAX SYMCRYPT_SSKDF_KMAC_128_DEFAULT_SALT_SIZE
21+
22+
23+
static const BYTE pbKmacCustomizationString[3] = { 'K', 'D', 'F' };
24+
25+
SYMCRYPT_ERROR
26+
SYMCRYPT_CALL
27+
SymCryptSskdfMacExpandSalt(
28+
_Out_ PSYMCRYPT_SSKDF_MAC_EXPANDED_SALT pExpandedSalt,
29+
_In_ PCSYMCRYPT_MAC macAlgorithm,
30+
_In_reads_opt_(cbSalt) PCBYTE pbSalt,
31+
SIZE_T cbSalt)
32+
{
33+
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
34+
35+
const BYTE pbSaltDefault[SYMCRYPT_SSKDF_DEFAULT_SALT_MAX] = { 0 };
36+
37+
SYMCRYPT_ASSERT( macAlgorithm->expandedKeySize <= sizeof( pExpandedSalt->macKey ) );
38+
39+
pExpandedSalt->macAlg = macAlgorithm;
40+
41+
if ( pbSalt == NULL )
42+
{
43+
if ( macAlgorithm == SymCryptKmac128Algorithm )
44+
{
45+
cbSalt = SYMCRYPT_SSKDF_KMAC_128_DEFAULT_SALT_SIZE;
46+
}
47+
else if ( macAlgorithm == SymCryptKmac256Algorithm )
48+
{
49+
cbSalt = SYMCRYPT_SSKDF_KMAC_256_DEFAULT_SALT_SIZE;
50+
}
51+
else
52+
{
53+
cbSalt = SymCryptHashInputBlockSize( *(macAlgorithm->ppHashAlgorithm) );
54+
}
55+
56+
pbSalt = pbSaltDefault;
57+
}
58+
59+
if ( macAlgorithm == SymCryptKmac128Algorithm )
60+
{
61+
scError = SymCryptKmac128ExpandKeyEx(
62+
&pExpandedSalt->macKey.kmac128Key,
63+
pbSalt,
64+
cbSalt,
65+
pbKmacCustomizationString,
66+
sizeof( pbKmacCustomizationString ) );
67+
}
68+
else if ( macAlgorithm == SymCryptKmac256Algorithm )
69+
{
70+
scError = SymCryptKmac256ExpandKeyEx(
71+
&pExpandedSalt->macKey.kmac256Key,
72+
pbSalt,
73+
cbSalt,
74+
pbKmacCustomizationString,
75+
sizeof( pbKmacCustomizationString ) );
76+
}
77+
else
78+
{
79+
scError = macAlgorithm->expandKeyFunc( &pExpandedSalt->macKey, pbSalt, cbSalt );
80+
}
81+
82+
return scError;
83+
}
84+
85+
SYMCRYPT_ERROR
86+
SYMCRYPT_CALL
87+
SymCryptSskdfMacDerive(
88+
_In_ PCSYMCRYPT_SSKDF_MAC_EXPANDED_SALT pExpandedSalt,
89+
SIZE_T cbMacOutputSize,
90+
_In_reads_(cbSecret) PCBYTE pbSecret,
91+
SIZE_T cbSecret,
92+
_In_reads_opt_(cbInfo) PCBYTE pbInfo,
93+
SIZE_T cbInfo,
94+
_Out_writes_(cbResult) PBYTE pbResult,
95+
SIZE_T cbResult)
96+
{
97+
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
98+
SYMCRYPT_MAC_STATE state;
99+
PCSYMCRYPT_MAC pMacAlgorithm = pExpandedSalt->macAlg;
100+
PSYMCRYPT_MAC_RESULT_EX resultFuncEx = NULL;
101+
102+
SYMCRYPT_ALIGN BYTE rbPartialResult[SYMCRYPT_MAC_MAX_RESULT_SIZE];
103+
PBYTE pbCurr = pbResult;
104+
105+
SIZE_T cbMacResultSize = pMacAlgorithm->resultSize;
106+
SIZE_T cbBlock;
107+
UINT32 cntr = 1;
108+
BYTE ctrBuf[4];
109+
110+
if ( cbMacOutputSize > 64 )
111+
{
112+
scError = SYMCRYPT_INVALID_ARGUMENT;
113+
goto cleanup;
114+
}
115+
116+
if ( pMacAlgorithm == SymCryptKmac128Algorithm )
117+
{
118+
cbMacResultSize = cbMacOutputSize;
119+
resultFuncEx = SymCryptKmac128ResultEx;
120+
}
121+
else if ( pMacAlgorithm == SymCryptKmac256Algorithm )
122+
{
123+
cbMacResultSize = cbMacOutputSize;
124+
resultFuncEx = SymCryptKmac256ResultEx;
125+
}
126+
else if ( cbMacOutputSize > 0 && cbMacOutputSize != pMacAlgorithm->resultSize )
127+
{
128+
scError = SYMCRYPT_INVALID_ARGUMENT;
129+
goto cleanup;
130+
}
131+
132+
while ( cbResult > 0 )
133+
{
134+
SYMCRYPT_STORE_MSBFIRST32( ctrBuf, cntr );
135+
136+
// Calculate K(i) = H(counter || Z || FixedInfo)
137+
pMacAlgorithm->initFunc( &state, &pExpandedSalt->macKey );
138+
pMacAlgorithm->appendFunc( &state, ctrBuf, sizeof( ctrBuf ) );
139+
pMacAlgorithm->appendFunc( &state, pbSecret, cbSecret );
140+
pMacAlgorithm->appendFunc( &state, pbInfo, cbInfo );
141+
142+
cbBlock = SYMCRYPT_MIN( cbResult, cbMacResultSize );
143+
144+
if ( resultFuncEx != NULL )
145+
{
146+
if ( cbMacOutputSize > 0 )
147+
{
148+
resultFuncEx( &state, rbPartialResult, cbMacOutputSize );
149+
}
150+
else
151+
{
152+
// If the output size is not specified, calculate the full result
153+
resultFuncEx( &state, pbResult, cbResult );
154+
break;
155+
}
156+
}
157+
else
158+
{
159+
pMacAlgorithm->resultFunc( &state, rbPartialResult );
160+
}
161+
162+
// Store the result in the output buffer
163+
memcpy( pbCurr, rbPartialResult, cbBlock );
164+
165+
// Update counters
166+
cntr++;
167+
pbCurr += cbBlock;
168+
cbResult -= cbBlock;
169+
}
170+
171+
cleanup:
172+
173+
SymCryptWipeKnownSize( &rbPartialResult[0], sizeof( rbPartialResult ) );
174+
175+
return scError;
176+
}
177+
178+
SYMCRYPT_ERROR
179+
SYMCRYPT_CALL
180+
SymCryptSskdfMac(
181+
_In_ PCSYMCRYPT_MAC macAlgorithm,
182+
SIZE_T cbMacOutputSize,
183+
_In_reads_(cbSecret) PCBYTE pbSecret,
184+
SIZE_T cbSecret,
185+
_In_reads_opt_(cbSalt) PCBYTE pbSalt,
186+
SIZE_T cbSalt,
187+
_In_reads_opt_(cbInfo) PCBYTE pbInfo,
188+
SIZE_T cbInfo,
189+
_Out_writes_(cbResult) PBYTE pbResult,
190+
SIZE_T cbResult)
191+
{
192+
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
193+
SYMCRYPT_SSKDF_MAC_EXPANDED_SALT expandedSalt;
194+
195+
scError = SymCryptSskdfMacExpandSalt( &expandedSalt, macAlgorithm, pbSalt, cbSalt );
196+
197+
if ( scError != SYMCRYPT_NO_ERROR )
198+
{
199+
goto cleanup;
200+
}
201+
202+
scError = SymCryptSskdfMacDerive(
203+
&expandedSalt,
204+
cbMacOutputSize,
205+
pbSecret,
206+
cbSecret,
207+
pbInfo,
208+
cbInfo,
209+
pbResult,
210+
cbResult );
211+
212+
cleanup:
213+
214+
SymCryptWipeKnownSize( &expandedSalt, sizeof( expandedSalt ) );
215+
216+
return scError;
217+
}
218+
219+
SYMCRYPT_ERROR
220+
SYMCRYPT_CALL
221+
SymCryptSskdfHash(
222+
_In_ PCSYMCRYPT_HASH hashAlgorithm,
223+
SIZE_T cbHashOutputSize,
224+
_In_reads_(cbSecret) PCBYTE pbSecret,
225+
SIZE_T cbSecret,
226+
_In_reads_opt_(cbInfo) PCBYTE pbInfo,
227+
SIZE_T cbInfo,
228+
_Out_writes_(cbResult) PBYTE pbResult,
229+
SIZE_T cbResult)
230+
{
231+
SYMCRYPT_HASH_STATE state;
232+
233+
PBYTE pbCurr = pbResult;
234+
235+
SIZE_T cbHashResultSize = hashAlgorithm->resultSize;
236+
SIZE_T cbPartialResult;
237+
UINT32 cntr = 1;
238+
BYTE ctrBuf[4];
239+
240+
if ( cbHashOutputSize > 64 ||
241+
cbHashOutputSize > 0 && cbHashOutputSize != hashAlgorithm->resultSize )
242+
{
243+
return SYMCRYPT_INVALID_ARGUMENT;
244+
}
245+
246+
while ( cbResult > 0 )
247+
{
248+
SYMCRYPT_STORE_MSBFIRST32( ctrBuf, cntr );
249+
250+
cbPartialResult = SYMCRYPT_MIN( cbResult, cbHashResultSize );
251+
252+
// Calculate K(i) = H(counter || Z || FixedInfo)
253+
SymCryptHashInit( hashAlgorithm, &state );
254+
SymCryptHashAppend( hashAlgorithm, &state, ctrBuf, sizeof( ctrBuf ) );
255+
SymCryptHashAppend( hashAlgorithm, &state, pbSecret, cbSecret );
256+
SymCryptHashAppend( hashAlgorithm, &state, pbInfo, cbInfo );
257+
SymCryptHashResult( hashAlgorithm, &state, pbCurr, cbPartialResult );
258+
259+
// Update counters
260+
cntr++;
261+
pbCurr += cbPartialResult;
262+
cbResult -= cbPartialResult;
263+
}
264+
265+
return SYMCRYPT_NO_ERROR;
266+
}

lib/sskdf_selftest.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// sskdf_selftest.c
3+
//
4+
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5+
//
6+
7+
#include "precomp.h"
8+
9+
static const BYTE pbResult[] =
10+
{
11+
0x30, 0xe5, 0x3e, 0x4c, 0xf6, 0xb1, 0xa5, 0x42, 0x5d, 0xc6, 0x4c, 0xe6, 0x15, 0x7f, 0x5f, 0xa6
12+
};
13+
14+
VOID
15+
SYMCRYPT_CALL
16+
SymCryptSskdfSelfTest(void)
17+
{
18+
SYMCRYPT_ALIGN BYTE rbResult[sizeof(pbResult)];
19+
20+
SymCryptSskdfMac(
21+
SymCryptHmacSha512Algorithm,
22+
0,
23+
&SymCryptTestKey32[0], 16,
24+
&SymCryptTestKey32[16], 16,
25+
&SymCryptTestMsg16[0], 16,
26+
rbResult, sizeof(pbResult));
27+
28+
SymCryptInjectError(rbResult, sizeof(pbResult));
29+
30+
if (memcmp(rbResult, pbResult, sizeof(pbResult)) != 0)
31+
{
32+
SymCryptFatal('sskd');
33+
}
34+
}

lib/symcrypt.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@
141141
<ClCompile Include="ssh_kdf.c" />
142142
<ClCompile Include="ssh_kdf_sha256.c" />
143143
<ClCompile Include="ssh_kdf_sha512.c" />
144+
<ClCompile Include="sskdf.c" />
145+
<ClCompile Include="sskdf_selftest.c" />
144146
<ClCompile Include="tlsCbcVerify.c" />
145147
<ClCompile Include="tlsprf.c" />
146148
<ClCompile Include="tlsprf_selftest.c" />

modules/linux/common/exports.ver

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,4 +554,9 @@ VERSION_103.4
554554
SymCryptXtsAesEncryptWith128bTweak;
555555
SymCryptXtsAesExpandKeyEx;
556556
SymCryptXtsAesKeyCopy;
557+
SymCryptSskdfMacExpandSalt;
558+
SymCryptSskdfMacDerive;
559+
SymCryptSskdfMac;
560+
SymCryptSskdfHash;
561+
SymCryptSskdfSelfTest;
557562
} VERSION_103.2;

modules/linux/common/module.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ VOID __attribute__((constructor)) SymCryptModuleMain(void)
6363
SymCryptSshKdfSha256SelfTest();
6464
SymCryptSshKdfSha512SelfTest();
6565

66+
SymCryptSskdfSelfTest();
67+
6668
SymCryptHmacSha3_256Selftest();
6769

6870
g_SymCryptFipsSelftestsPerformed |= SYMCRYPT_SELFTEST_ALGORITHM_STARTUP;

0 commit comments

Comments
 (0)