Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // hkdf.c |
3 | | // |
4 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
5 | | // |
6 | | |
7 | | // |
8 | | // This module contains the routines to implement the HKDF |
9 | | // function for the TLS protocol 1.3. It is used in |
10 | | // the protocol's key derivation function. |
11 | | // |
12 | | // |
13 | | |
14 | | #include "precomp.h" |
15 | | |
16 | | SYMCRYPT_ERROR |
17 | | SYMCRYPT_CALL |
18 | | SymCryptHkdfExpandKey( |
19 | | _Out_ PSYMCRYPT_HKDF_EXPANDED_KEY pExpandedKey, |
20 | | _In_ PCSYMCRYPT_MAC macAlgorithm, |
21 | | _In_reads_(cbIkm) PCBYTE pbIkm, |
22 | | SIZE_T cbIkm, |
23 | | _In_reads_opt_(cbSalt) PCBYTE pbSalt, |
24 | | SIZE_T cbSalt ) |
25 | 199 | { |
26 | 199 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
27 | | |
28 | 199 | SYMCRYPT_ALIGN BYTE rbPrk[SYMCRYPT_MAC_MAX_RESULT_SIZE] = { 0 }; |
29 | | |
30 | 199 | SYMCRYPT_ASSERT( macAlgorithm->expandedKeySize <= sizeof( pExpandedKey->macKey ) ); |
31 | | |
32 | 199 | scError = SymCryptHkdfExtractPrk( macAlgorithm, pbIkm, cbIkm, pbSalt, cbSalt, rbPrk, macAlgorithm->resultSize ); |
33 | 199 | if (scError != SYMCRYPT_NO_ERROR) |
34 | 0 | { |
35 | 0 | goto cleanup; |
36 | 0 | } |
37 | | |
38 | 199 | scError = SymCryptHkdfPrkExpandKey( pExpandedKey, macAlgorithm, rbPrk, macAlgorithm->resultSize ); |
39 | 199 | if (scError != SYMCRYPT_NO_ERROR) |
40 | 0 | { |
41 | 0 | goto cleanup; |
42 | 0 | } |
43 | | |
44 | 199 | cleanup: |
45 | 199 | SymCryptWipeKnownSize(&rbPrk[0], sizeof(rbPrk)); |
46 | | |
47 | 199 | return scError; |
48 | 199 | } |
49 | | |
50 | | SYMCRYPT_ERROR |
51 | | SYMCRYPT_CALL |
52 | | SymCryptHkdfExtractPrk( |
53 | | _In_ PCSYMCRYPT_MAC macAlgorithm, |
54 | | _In_reads_(cbIkm) PCBYTE pbIkm, |
55 | | SIZE_T cbIkm, |
56 | | _In_reads_opt_(cbSalt) PCBYTE pbSalt, |
57 | | SIZE_T cbSalt, |
58 | | _Out_writes_(cbPrk) PBYTE pbPrk, |
59 | | SIZE_T cbPrk ) |
60 | 199 | { |
61 | 199 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
62 | | |
63 | 199 | SYMCRYPT_MAC_STATE state; |
64 | 199 | SYMCRYPT_MAC_EXPANDED_KEY key; |
65 | | |
66 | | // Ensure that pbPrk is the correct size |
67 | 199 | if (cbPrk != macAlgorithm->resultSize) |
68 | 0 | { |
69 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
70 | 0 | goto cleanup; |
71 | 0 | } |
72 | | |
73 | | // Calculation of PRK = HMAC-Hash(salt, IKM) |
74 | 199 | scError = macAlgorithm->expandKeyFunc( &key, pbSalt, cbSalt ); |
75 | 199 | if (scError != SYMCRYPT_NO_ERROR) |
76 | 0 | { |
77 | 0 | goto cleanup; |
78 | 0 | } |
79 | | |
80 | 199 | macAlgorithm->initFunc( &state, &key ); |
81 | 199 | macAlgorithm->appendFunc( &state, pbIkm, cbIkm ); |
82 | 199 | macAlgorithm->resultFunc( &state, pbPrk ); |
83 | | |
84 | 199 | cleanup: |
85 | 199 | SymCryptWipeKnownSize(&key, sizeof(key)); |
86 | | |
87 | 199 | return scError; |
88 | 199 | } |
89 | | |
90 | | SYMCRYPT_ERROR |
91 | | SYMCRYPT_CALL |
92 | | SymCryptHkdfPrkExpandKey( |
93 | | _Out_ PSYMCRYPT_HKDF_EXPANDED_KEY pExpandedKey, |
94 | | _In_ PCSYMCRYPT_MAC macAlgorithm, |
95 | | _In_reads_(cbPrk) PCBYTE pbPrk, |
96 | | SIZE_T cbPrk ) |
97 | 199 | { |
98 | 199 | SYMCRYPT_ASSERT( macAlgorithm->expandedKeySize <= sizeof( pExpandedKey->macKey ) ); |
99 | | |
100 | 199 | pExpandedKey->macAlg = macAlgorithm; |
101 | 199 | return macAlgorithm->expandKeyFunc( &pExpandedKey->macKey, pbPrk, cbPrk ); |
102 | 199 | } |
103 | | |
104 | | SYMCRYPT_ERROR |
105 | | SYMCRYPT_CALL |
106 | | SymCryptHkdfDerive( |
107 | | _In_ PCSYMCRYPT_HKDF_EXPANDED_KEY pExpandedKey, |
108 | | _In_reads_opt_(cbInfo) PCBYTE pbInfo, |
109 | | SIZE_T cbInfo, |
110 | | _Out_writes_(cbResult) PBYTE pbResult, |
111 | | SIZE_T cbResult) |
112 | 199 | { |
113 | | |
114 | 199 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
115 | | |
116 | 199 | SYMCRYPT_MAC_STATE state; |
117 | | |
118 | 199 | PCSYMCRYPT_MAC pMacAlgorithm = pExpandedKey->macAlg; |
119 | | |
120 | 199 | SYMCRYPT_ALIGN BYTE rbPartialResult[SYMCRYPT_MAC_MAX_RESULT_SIZE]; |
121 | 199 | BYTE * pbCurr = pbResult; |
122 | | |
123 | 199 | SIZE_T cbMacResultSize = pMacAlgorithm->resultSize; |
124 | | |
125 | 199 | BYTE cntr = 0x01; |
126 | | |
127 | | // Check that cbResult <= 255*HashLen |
128 | 199 | if (cbResult > 0xff * cbMacResultSize) |
129 | 44 | { |
130 | 44 | scError = SYMCRYPT_WRONG_DATA_SIZE; |
131 | 44 | goto cleanup; |
132 | 44 | } |
133 | | |
134 | | // In the first iteration T(0) is the empty string |
135 | | // Calculate T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) |
136 | 155 | pMacAlgorithm->initFunc( &state, pExpandedKey ); |
137 | 155 | pMacAlgorithm->appendFunc( &state, pbInfo, cbInfo ); |
138 | 155 | pMacAlgorithm->appendFunc( &state, &cntr, sizeof(cntr) ); |
139 | 155 | pMacAlgorithm->resultFunc( &state, rbPartialResult ); |
140 | | |
141 | | // Store the result in the output buffer |
142 | 155 | memcpy(pbCurr, rbPartialResult, SYMCRYPT_MIN(cbResult, cbMacResultSize)); |
143 | 155 | if (cbResult <= cbMacResultSize) |
144 | 2 | { |
145 | 2 | goto cleanup; |
146 | 2 | } |
147 | | |
148 | | // Update counters |
149 | 153 | cntr++; |
150 | 153 | pbCurr += cbMacResultSize; |
151 | 153 | cbResult -= cbMacResultSize; |
152 | | |
153 | 17.3k | while( cbResult > 0 ) |
154 | 17.3k | { |
155 | | // Calculate T(i) = HMAC-Hash(PRK, T(i-1) | info | 0xi) |
156 | 17.3k | pMacAlgorithm->initFunc( &state, pExpandedKey ); |
157 | 17.3k | pMacAlgorithm->appendFunc( &state, rbPartialResult, cbMacResultSize ); |
158 | 17.3k | pMacAlgorithm->appendFunc( &state, pbInfo, cbInfo ); |
159 | 17.3k | pMacAlgorithm->appendFunc( &state, &cntr, sizeof(cntr) ); |
160 | 17.3k | pMacAlgorithm->resultFunc( &state, rbPartialResult ); |
161 | | |
162 | | // Store the result in the output buffer |
163 | 17.3k | memcpy(pbCurr, rbPartialResult, SYMCRYPT_MIN(cbResult, cbMacResultSize)); |
164 | 17.3k | if (cbResult <= cbMacResultSize) |
165 | 153 | { |
166 | 153 | goto cleanup; |
167 | 153 | } |
168 | | |
169 | | // Update counters |
170 | 17.1k | cntr++; |
171 | 17.1k | pbCurr += cbMacResultSize; |
172 | 17.1k | cbResult -= cbMacResultSize; |
173 | 17.1k | } |
174 | | |
175 | 199 | cleanup: |
176 | 199 | SymCryptWipeKnownSize(&rbPartialResult[0], sizeof(rbPartialResult)); |
177 | | |
178 | 199 | return scError; |
179 | 153 | } |
180 | | |
181 | | // |
182 | | // The full HKDF |
183 | | // |
184 | | SYMCRYPT_ERROR |
185 | | SYMCRYPT_CALL |
186 | | SymCryptHkdf( |
187 | | PCSYMCRYPT_MAC macAlgorithm, |
188 | | _In_reads_(cbIkm) PCBYTE pbIkm, |
189 | | SIZE_T cbIkm, |
190 | | _In_reads_opt_(cbSalt) PCBYTE pbSalt, |
191 | | SIZE_T cbSalt, |
192 | | _In_reads_opt_(cbInfo) PCBYTE pbInfo, |
193 | | SIZE_T cbInfo, |
194 | | _Out_writes_(cbResult) PBYTE pbResult, |
195 | | SIZE_T cbResult) |
196 | 199 | { |
197 | 199 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
198 | 199 | SYMCRYPT_HKDF_EXPANDED_KEY key; |
199 | | |
200 | | // Create the expanded key |
201 | 199 | scError = SymCryptHkdfExpandKey( |
202 | 199 | &key, |
203 | 199 | macAlgorithm, |
204 | 199 | pbIkm, |
205 | 199 | cbIkm, |
206 | 199 | pbSalt, |
207 | 199 | cbSalt ); |
208 | 199 | if (scError != SYMCRYPT_NO_ERROR) |
209 | 0 | { |
210 | 0 | goto cleanup; |
211 | 0 | } |
212 | | |
213 | | // Derive the key |
214 | 199 | scError = SymCryptHkdfDerive( |
215 | 199 | &key, |
216 | 199 | pbInfo, |
217 | 199 | cbInfo, |
218 | 199 | pbResult, |
219 | 199 | cbResult ); |
220 | 199 | if (scError != SYMCRYPT_NO_ERROR) |
221 | 44 | { |
222 | 44 | goto cleanup; |
223 | 44 | } |
224 | | |
225 | 199 | cleanup: |
226 | 199 | SymCryptWipeKnownSize(&key, sizeof(key)); |
227 | | |
228 | 199 | return scError; |
229 | 199 | } |
230 | | |
231 | | |