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+ }
0 commit comments