diff options
Diffstat (limited to 'src/util/crypto_hkdf.c')
-rw-r--r-- | src/util/crypto_hkdf.c | 368 |
1 files changed, 0 insertions, 368 deletions
diff --git a/src/util/crypto_hkdf.c b/src/util/crypto_hkdf.c deleted file mode 100644 index 838e37d8d..000000000 --- a/src/util/crypto_hkdf.c +++ /dev/null | |||
@@ -1,368 +0,0 @@ | |||
1 | /* | ||
2 | Copyright (c) 2010 Nils Durner | ||
3 | |||
4 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
5 | of this software and associated documentation files (the "Software"), to deal | ||
6 | in the Software without restriction, including without limitation the rights | ||
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
8 | copies of the Software, and to permit persons to whom the Software is | ||
9 | furnished to do so, subject to the following conditions: | ||
10 | |||
11 | The above copyright notice and this permission notice shall be included in | ||
12 | all copies or substantial portions of the Software. | ||
13 | |||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
20 | THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | /** | ||
24 | * @file src/util/crypto_hkdf.c | ||
25 | * @brief Hash-based KDF as defined in RFC 5869 | ||
26 | * @see http://www.rfc-editor.org/rfc/rfc5869.txt | ||
27 | * @todo remove GNUNET references | ||
28 | * @author Nils Durner | ||
29 | * | ||
30 | * The following list of people have reviewed this code and considered | ||
31 | * it correct on the date given (if you reviewed it, please | ||
32 | * have your name added to the list): | ||
33 | * | ||
34 | * - Christian Grothoff (08.10.2010) | ||
35 | * - Nathan Evans (08.10.2010) | ||
36 | * - Matthias Wachs (08.10.2010) | ||
37 | */ | ||
38 | |||
39 | #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-hkdf", __VA_ARGS__) | ||
40 | |||
41 | /** | ||
42 | * Set this to 0 if you compile this code outside of GNUnet. | ||
43 | */ | ||
44 | #define GNUNET_BUILD 1 | ||
45 | |||
46 | /** | ||
47 | * Enable debugging. | ||
48 | */ | ||
49 | #define DEBUG_HKDF 0 | ||
50 | |||
51 | |||
52 | #if GNUNET_BUILD | ||
53 | #include "platform.h" | ||
54 | #include "gnunet_crypto_lib.h" | ||
55 | #include "benchmark.h" | ||
56 | #else | ||
57 | #define GNUNET_NO 0 | ||
58 | #define GNUNET_YES 1 | ||
59 | #define GNUNET_SYSERR -1 | ||
60 | #include <stdlib.h> | ||
61 | #endif | ||
62 | |||
63 | #include <gcrypt.h> | ||
64 | |||
65 | |||
66 | /** | ||
67 | * @brief Compute the HMAC | ||
68 | * @todo use chunked buffers | ||
69 | * @param mac gcrypt MAC handle | ||
70 | * @param key HMAC key | ||
71 | * @param key_len length of key | ||
72 | * @param buf message to be processed | ||
73 | * @param buf_len length of buf | ||
74 | * @return HMAC, freed by caller via gcry_md_close/_reset | ||
75 | */ | ||
76 | static const void * | ||
77 | doHMAC (gcry_md_hd_t mac, | ||
78 | const void *key, | ||
79 | size_t key_len, | ||
80 | const void *buf, | ||
81 | size_t buf_len) | ||
82 | { | ||
83 | if (GPG_ERR_NO_ERROR != | ||
84 | gcry_md_setkey (mac, key, key_len)) | ||
85 | { | ||
86 | GNUNET_break (0); | ||
87 | return NULL; | ||
88 | } | ||
89 | gcry_md_write (mac, | ||
90 | buf, | ||
91 | buf_len); | ||
92 | return (const void *) gcry_md_read (mac, 0); | ||
93 | } | ||
94 | |||
95 | |||
96 | /** | ||
97 | * @brief Generate pseudo-random key | ||
98 | * @param mac gcrypt HMAC handle | ||
99 | * @param xts salt | ||
100 | * @param xts_len length of the @a xts salt | ||
101 | * @param skm source key material | ||
102 | * @param skm_len length of @a skm | ||
103 | * @param prk result buffer (allocated by caller; at least gcry_md_dlen() bytes) | ||
104 | * @return #GNUNET_YES on success | ||
105 | */ | ||
106 | static enum GNUNET_GenericReturnValue | ||
107 | getPRK (gcry_md_hd_t mac, | ||
108 | const void *xts, | ||
109 | size_t xts_len, | ||
110 | const void *skm, | ||
111 | size_t skm_len, | ||
112 | void *prk) | ||
113 | { | ||
114 | const void *ret; | ||
115 | size_t dlen; | ||
116 | |||
117 | dlen = gcry_md_get_algo_dlen (gcry_md_get_algo (mac)); | ||
118 | |||
119 | /* sanity check to bound stack allocation */ | ||
120 | GNUNET_assert (dlen <= 512); | ||
121 | |||
122 | /* From RFC 5869: | ||
123 | * salt - optional salt value (a non-secret random value); | ||
124 | * if not provided, it is set to a string of HashLen zeros. */ | ||
125 | |||
126 | if (0 == xts_len) | ||
127 | { | ||
128 | char zero_salt[dlen]; | ||
129 | |||
130 | memset (zero_salt, 0, dlen); | ||
131 | ret = doHMAC (mac, zero_salt, dlen, skm, skm_len); | ||
132 | } | ||
133 | else | ||
134 | { | ||
135 | ret = doHMAC (mac, xts, xts_len, skm, skm_len); | ||
136 | } | ||
137 | if (NULL == ret) | ||
138 | return GNUNET_SYSERR; | ||
139 | GNUNET_memcpy (prk, | ||
140 | ret, | ||
141 | dlen); | ||
142 | return GNUNET_YES; | ||
143 | } | ||
144 | |||
145 | |||
146 | #if DEBUG_HKDF | ||
147 | static void | ||
148 | dump (const char *src, | ||
149 | const void *p, | ||
150 | unsigned int l) | ||
151 | { | ||
152 | printf ("\n%s: ", src); | ||
153 | for (unsigned int i = 0; i < l; i++) | ||
154 | { | ||
155 | printf ("%2x", (int) ((const unsigned char *) p)[i]); | ||
156 | } | ||
157 | printf ("\n"); | ||
158 | } | ||
159 | |||
160 | |||
161 | #endif | ||
162 | |||
163 | |||
164 | enum GNUNET_GenericReturnValue | ||
165 | GNUNET_CRYPTO_hkdf_v (void *result, | ||
166 | size_t out_len, | ||
167 | int xtr_algo, | ||
168 | int prf_algo, | ||
169 | const void *xts, | ||
170 | size_t xts_len, | ||
171 | const void *skm, | ||
172 | size_t skm_len, | ||
173 | va_list argp) | ||
174 | { | ||
175 | gcry_md_hd_t xtr; | ||
176 | gcry_md_hd_t prf; | ||
177 | const void *hc; | ||
178 | unsigned long i; | ||
179 | unsigned long t; | ||
180 | unsigned long d; | ||
181 | unsigned int k = gcry_md_get_algo_dlen (prf_algo); | ||
182 | unsigned int xtr_len = gcry_md_get_algo_dlen (xtr_algo); | ||
183 | char prk[xtr_len]; | ||
184 | int ret; | ||
185 | size_t ctx_len; | ||
186 | va_list args; | ||
187 | |||
188 | BENCHMARK_START (hkdf); | ||
189 | |||
190 | if (0 == k) | ||
191 | return GNUNET_SYSERR; | ||
192 | if (GPG_ERR_NO_ERROR != | ||
193 | gcry_md_open (&xtr, | ||
194 | xtr_algo, | ||
195 | GCRY_MD_FLAG_HMAC)) | ||
196 | return GNUNET_SYSERR; | ||
197 | if (GPG_ERR_NO_ERROR != | ||
198 | gcry_md_open (&prf, | ||
199 | prf_algo, | ||
200 | GCRY_MD_FLAG_HMAC)) | ||
201 | { | ||
202 | gcry_md_close (xtr); | ||
203 | return GNUNET_SYSERR; | ||
204 | } | ||
205 | va_copy (args, argp); | ||
206 | |||
207 | ctx_len = 0; | ||
208 | while (NULL != va_arg (args, void *)) | ||
209 | { | ||
210 | size_t nxt = va_arg (args, size_t); | ||
211 | if (nxt + ctx_len < nxt) | ||
212 | { | ||
213 | /* integer overflow */ | ||
214 | GNUNET_break (0); | ||
215 | va_end (args); | ||
216 | goto hkdf_error; | ||
217 | } | ||
218 | ctx_len += nxt; | ||
219 | } | ||
220 | |||
221 | va_end (args); | ||
222 | |||
223 | if ( (k + ctx_len < ctx_len) || | ||
224 | (k + ctx_len + 1 < ctx_len) ) | ||
225 | { | ||
226 | /* integer overflow */ | ||
227 | GNUNET_break (0); | ||
228 | goto hkdf_error; | ||
229 | } | ||
230 | |||
231 | memset (result, 0, out_len); | ||
232 | if (GNUNET_YES != | ||
233 | getPRK (xtr, xts, xts_len, skm, skm_len, prk)) | ||
234 | goto hkdf_error; | ||
235 | #if DEBUG_HKDF | ||
236 | dump ("PRK", prk, xtr_len); | ||
237 | #endif | ||
238 | |||
239 | t = out_len / k; | ||
240 | d = out_len % k; | ||
241 | |||
242 | /* K(1) */ | ||
243 | { | ||
244 | size_t plain_len = k + ctx_len + 1; | ||
245 | char *plain; | ||
246 | const void *ctx; | ||
247 | char *dst; | ||
248 | |||
249 | plain = GNUNET_malloc (plain_len); | ||
250 | dst = plain + k; | ||
251 | va_copy (args, argp); | ||
252 | while ((ctx = va_arg (args, void *))) | ||
253 | { | ||
254 | size_t len; | ||
255 | |||
256 | len = va_arg (args, size_t); | ||
257 | GNUNET_memcpy (dst, ctx, len); | ||
258 | dst += len; | ||
259 | } | ||
260 | va_end (args); | ||
261 | |||
262 | if (t > 0) | ||
263 | { | ||
264 | plain[k + ctx_len] = (char) 1; | ||
265 | #if DEBUG_HKDF | ||
266 | dump ("K(1)", plain, plain_len); | ||
267 | #endif | ||
268 | hc = doHMAC (prf, prk, xtr_len, &plain[k], ctx_len + 1); | ||
269 | if (hc == NULL) | ||
270 | { | ||
271 | GNUNET_free (plain); | ||
272 | goto hkdf_error; | ||
273 | } | ||
274 | GNUNET_memcpy (result, hc, k); | ||
275 | result += k; | ||
276 | } | ||
277 | |||
278 | /* K(i+1) */ | ||
279 | for (i = 1; i < t; i++) | ||
280 | { | ||
281 | GNUNET_memcpy (plain, result - k, k); | ||
282 | plain[k + ctx_len] = (char) (i + 1); | ||
283 | gcry_md_reset (prf); | ||
284 | #if DEBUG_HKDF | ||
285 | dump ("K(i+1)", plain, plain_len); | ||
286 | #endif | ||
287 | hc = doHMAC (prf, prk, xtr_len, plain, plain_len); | ||
288 | if (NULL == hc) | ||
289 | { | ||
290 | GNUNET_free (plain); | ||
291 | goto hkdf_error; | ||
292 | } | ||
293 | GNUNET_memcpy (result, hc, k); | ||
294 | result += k; | ||
295 | } | ||
296 | |||
297 | /* K(t):d */ | ||
298 | if (d > 0) | ||
299 | { | ||
300 | if (t > 0) | ||
301 | { | ||
302 | GNUNET_memcpy (plain, result - k, k); | ||
303 | i++; | ||
304 | } | ||
305 | plain[k + ctx_len] = (char) i; | ||
306 | gcry_md_reset (prf); | ||
307 | #if DEBUG_HKDF | ||
308 | dump ("K(t):d", plain, plain_len); | ||
309 | #endif | ||
310 | if (t > 0) | ||
311 | hc = doHMAC (prf, prk, xtr_len, plain, plain_len); | ||
312 | else | ||
313 | hc = doHMAC (prf, prk, xtr_len, plain + k, plain_len - k); | ||
314 | if (hc == NULL) | ||
315 | { | ||
316 | GNUNET_free (plain); | ||
317 | goto hkdf_error; | ||
318 | } | ||
319 | GNUNET_memcpy (result, hc, d); | ||
320 | } | ||
321 | #if DEBUG_HKDF | ||
322 | dump ("result", result - k, out_len); | ||
323 | #endif | ||
324 | |||
325 | ret = GNUNET_YES; | ||
326 | GNUNET_free (plain); | ||
327 | goto hkdf_ok; | ||
328 | } | ||
329 | hkdf_error: | ||
330 | ret = GNUNET_SYSERR; | ||
331 | hkdf_ok: | ||
332 | gcry_md_close (xtr); | ||
333 | gcry_md_close (prf); | ||
334 | BENCHMARK_END (hkdf); | ||
335 | return ret; | ||
336 | } | ||
337 | |||
338 | |||
339 | enum GNUNET_GenericReturnValue | ||
340 | GNUNET_CRYPTO_hkdf (void *result, | ||
341 | size_t out_len, | ||
342 | int xtr_algo, | ||
343 | int prf_algo, | ||
344 | const void *xts, | ||
345 | size_t xts_len, | ||
346 | const void *skm, | ||
347 | size_t skm_len, ...) | ||
348 | { | ||
349 | va_list argp; | ||
350 | enum GNUNET_GenericReturnValue ret; | ||
351 | |||
352 | va_start (argp, skm_len); | ||
353 | ret = | ||
354 | GNUNET_CRYPTO_hkdf_v (result, | ||
355 | out_len, | ||
356 | xtr_algo, | ||
357 | prf_algo, | ||
358 | xts, | ||
359 | xts_len, | ||
360 | skm, | ||
361 | skm_len, | ||
362 | argp); | ||
363 | va_end (argp); | ||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | |||
368 | /* end of crypto_hkdf.c */ | ||