diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2023-10-18 13:37:38 +0200 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2023-10-18 13:37:38 +0200 |
commit | 9ef4abad615bea12d13be542b8ae5fbeb2dfee32 (patch) | |
tree | 8875a687e004d331c9ea6a1d511a328c72b88113 /src/util/crypto_hkdf.c | |
parent | e95236b3ed78cd597c15f34b89385295702b627f (diff) | |
download | gnunet-9ef4abad615bea12d13be542b8ae5fbeb2dfee32.tar.gz gnunet-9ef4abad615bea12d13be542b8ae5fbeb2dfee32.zip |
NEWS: Refactoring components under src/ into lib/, plugin/, cli/ and service/
This also includes a necessary API refactoring of crypto from IDENTITY
to UTIL.
Diffstat (limited to 'src/util/crypto_hkdf.c')
-rw-r--r-- | src/util/crypto_hkdf.c | 369 |
1 files changed, 0 insertions, 369 deletions
diff --git a/src/util/crypto_hkdf.c b/src/util/crypto_hkdf.c deleted file mode 100644 index e724bc9ba..000000000 --- a/src/util/crypto_hkdf.c +++ /dev/null | |||
@@ -1,369 +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 | |||
54 | #include "platform.h" | ||
55 | #include "gnunet_util_lib.h" | ||
56 | #include "benchmark.h" | ||
57 | #else | ||
58 | #define GNUNET_NO 0 | ||
59 | #define GNUNET_YES 1 | ||
60 | #define GNUNET_SYSERR -1 | ||
61 | #include <stdlib.h> | ||
62 | #endif | ||
63 | |||
64 | #include <gcrypt.h> | ||
65 | |||
66 | |||
67 | /** | ||
68 | * @brief Compute the HMAC | ||
69 | * @todo use chunked buffers | ||
70 | * @param mac gcrypt MAC handle | ||
71 | * @param key HMAC key | ||
72 | * @param key_len length of key | ||
73 | * @param buf message to be processed | ||
74 | * @param buf_len length of buf | ||
75 | * @return HMAC, freed by caller via gcry_md_close/_reset | ||
76 | */ | ||
77 | static const void * | ||
78 | doHMAC (gcry_md_hd_t mac, | ||
79 | const void *key, | ||
80 | size_t key_len, | ||
81 | const void *buf, | ||
82 | size_t buf_len) | ||
83 | { | ||
84 | if (GPG_ERR_NO_ERROR != | ||
85 | gcry_md_setkey (mac, key, key_len)) | ||
86 | { | ||
87 | GNUNET_break (0); | ||
88 | return NULL; | ||
89 | } | ||
90 | gcry_md_write (mac, | ||
91 | buf, | ||
92 | buf_len); | ||
93 | return (const void *) gcry_md_read (mac, 0); | ||
94 | } | ||
95 | |||
96 | |||
97 | /** | ||
98 | * @brief Generate pseudo-random key | ||
99 | * @param mac gcrypt HMAC handle | ||
100 | * @param xts salt | ||
101 | * @param xts_len length of the @a xts salt | ||
102 | * @param skm source key material | ||
103 | * @param skm_len length of @a skm | ||
104 | * @param prk result buffer (allocated by caller; at least gcry_md_dlen() bytes) | ||
105 | * @return #GNUNET_YES on success | ||
106 | */ | ||
107 | static enum GNUNET_GenericReturnValue | ||
108 | getPRK (gcry_md_hd_t mac, | ||
109 | const void *xts, | ||
110 | size_t xts_len, | ||
111 | const void *skm, | ||
112 | size_t skm_len, | ||
113 | void *prk) | ||
114 | { | ||
115 | const void *ret; | ||
116 | size_t dlen; | ||
117 | |||
118 | dlen = gcry_md_get_algo_dlen (gcry_md_get_algo (mac)); | ||
119 | |||
120 | /* sanity check to bound stack allocation */ | ||
121 | GNUNET_assert (dlen <= 512); | ||
122 | |||
123 | /* From RFC 5869: | ||
124 | * salt - optional salt value (a non-secret random value); | ||
125 | * if not provided, it is set to a string of HashLen zeros. */ | ||
126 | |||
127 | if (0 == xts_len) | ||
128 | { | ||
129 | char zero_salt[dlen]; | ||
130 | |||
131 | memset (zero_salt, 0, dlen); | ||
132 | ret = doHMAC (mac, zero_salt, dlen, skm, skm_len); | ||
133 | } | ||
134 | else | ||
135 | { | ||
136 | ret = doHMAC (mac, xts, xts_len, skm, skm_len); | ||
137 | } | ||
138 | if (NULL == ret) | ||
139 | return GNUNET_SYSERR; | ||
140 | GNUNET_memcpy (prk, | ||
141 | ret, | ||
142 | dlen); | ||
143 | return GNUNET_YES; | ||
144 | } | ||
145 | |||
146 | |||
147 | #if DEBUG_HKDF | ||
148 | static void | ||
149 | dump (const char *src, | ||
150 | const void *p, | ||
151 | unsigned int l) | ||
152 | { | ||
153 | printf ("\n%s: ", src); | ||
154 | for (unsigned int i = 0; i < l; i++) | ||
155 | { | ||
156 | printf ("%2x", (int) ((const unsigned char *) p)[i]); | ||
157 | } | ||
158 | printf ("\n"); | ||
159 | } | ||
160 | |||
161 | |||
162 | #endif | ||
163 | |||
164 | |||
165 | enum GNUNET_GenericReturnValue | ||
166 | GNUNET_CRYPTO_hkdf_v (void *result, | ||
167 | size_t out_len, | ||
168 | int xtr_algo, | ||
169 | int prf_algo, | ||
170 | const void *xts, | ||
171 | size_t xts_len, | ||
172 | const void *skm, | ||
173 | size_t skm_len, | ||
174 | va_list argp) | ||
175 | { | ||
176 | gcry_md_hd_t xtr; | ||
177 | gcry_md_hd_t prf; | ||
178 | const void *hc; | ||
179 | unsigned long i; | ||
180 | unsigned long t; | ||
181 | unsigned long d; | ||
182 | unsigned int k = gcry_md_get_algo_dlen (prf_algo); | ||
183 | unsigned int xtr_len = gcry_md_get_algo_dlen (xtr_algo); | ||
184 | char prk[xtr_len]; | ||
185 | int ret; | ||
186 | size_t ctx_len; | ||
187 | va_list args; | ||
188 | |||
189 | BENCHMARK_START (hkdf); | ||
190 | |||
191 | if (0 == k) | ||
192 | return GNUNET_SYSERR; | ||
193 | if (GPG_ERR_NO_ERROR != | ||
194 | gcry_md_open (&xtr, | ||
195 | xtr_algo, | ||
196 | GCRY_MD_FLAG_HMAC)) | ||
197 | return GNUNET_SYSERR; | ||
198 | if (GPG_ERR_NO_ERROR != | ||
199 | gcry_md_open (&prf, | ||
200 | prf_algo, | ||
201 | GCRY_MD_FLAG_HMAC)) | ||
202 | { | ||
203 | gcry_md_close (xtr); | ||
204 | return GNUNET_SYSERR; | ||
205 | } | ||
206 | va_copy (args, argp); | ||
207 | |||
208 | ctx_len = 0; | ||
209 | while (NULL != va_arg (args, void *)) | ||
210 | { | ||
211 | size_t nxt = va_arg (args, size_t); | ||
212 | if (nxt + ctx_len < nxt) | ||
213 | { | ||
214 | /* integer overflow */ | ||
215 | GNUNET_break (0); | ||
216 | va_end (args); | ||
217 | goto hkdf_error; | ||
218 | } | ||
219 | ctx_len += nxt; | ||
220 | } | ||
221 | |||
222 | va_end (args); | ||
223 | |||
224 | if ( (k + ctx_len < ctx_len) || | ||
225 | (k + ctx_len + 1 < ctx_len) ) | ||
226 | { | ||
227 | /* integer overflow */ | ||
228 | GNUNET_break (0); | ||
229 | goto hkdf_error; | ||
230 | } | ||
231 | |||
232 | memset (result, 0, out_len); | ||
233 | if (GNUNET_YES != | ||
234 | getPRK (xtr, xts, xts_len, skm, skm_len, prk)) | ||
235 | goto hkdf_error; | ||
236 | #if DEBUG_HKDF | ||
237 | dump ("PRK", prk, xtr_len); | ||
238 | #endif | ||
239 | |||
240 | t = out_len / k; | ||
241 | d = out_len % k; | ||
242 | |||
243 | /* K(1) */ | ||
244 | { | ||
245 | size_t plain_len = k + ctx_len + 1; | ||
246 | char *plain; | ||
247 | const void *ctx; | ||
248 | char *dst; | ||
249 | |||
250 | plain = GNUNET_malloc (plain_len); | ||
251 | dst = plain + k; | ||
252 | va_copy (args, argp); | ||
253 | while ((ctx = va_arg (args, void *))) | ||
254 | { | ||
255 | size_t len; | ||
256 | |||
257 | len = va_arg (args, size_t); | ||
258 | GNUNET_memcpy (dst, ctx, len); | ||
259 | dst += len; | ||
260 | } | ||
261 | va_end (args); | ||
262 | |||
263 | if (t > 0) | ||
264 | { | ||
265 | plain[k + ctx_len] = (char) 1; | ||
266 | #if DEBUG_HKDF | ||
267 | dump ("K(1)", plain, plain_len); | ||
268 | #endif | ||
269 | hc = doHMAC (prf, prk, xtr_len, &plain[k], ctx_len + 1); | ||
270 | if (hc == NULL) | ||
271 | { | ||
272 | GNUNET_free (plain); | ||
273 | goto hkdf_error; | ||
274 | } | ||
275 | GNUNET_memcpy (result, hc, k); | ||
276 | result += k; | ||
277 | } | ||
278 | |||
279 | /* K(i+1) */ | ||
280 | for (i = 1; i < t; i++) | ||
281 | { | ||
282 | GNUNET_memcpy (plain, result - k, k); | ||
283 | plain[k + ctx_len] = (char) (i + 1); | ||
284 | gcry_md_reset (prf); | ||
285 | #if DEBUG_HKDF | ||
286 | dump ("K(i+1)", plain, plain_len); | ||
287 | #endif | ||
288 | hc = doHMAC (prf, prk, xtr_len, plain, plain_len); | ||
289 | if (NULL == hc) | ||
290 | { | ||
291 | GNUNET_free (plain); | ||
292 | goto hkdf_error; | ||
293 | } | ||
294 | GNUNET_memcpy (result, hc, k); | ||
295 | result += k; | ||
296 | } | ||
297 | |||
298 | /* K(t):d */ | ||
299 | if (d > 0) | ||
300 | { | ||
301 | if (t > 0) | ||
302 | { | ||
303 | GNUNET_memcpy (plain, result - k, k); | ||
304 | i++; | ||
305 | } | ||
306 | plain[k + ctx_len] = (char) i; | ||
307 | gcry_md_reset (prf); | ||
308 | #if DEBUG_HKDF | ||
309 | dump ("K(t):d", plain, plain_len); | ||
310 | #endif | ||
311 | if (t > 0) | ||
312 | hc = doHMAC (prf, prk, xtr_len, plain, plain_len); | ||
313 | else | ||
314 | hc = doHMAC (prf, prk, xtr_len, plain + k, plain_len - k); | ||
315 | if (hc == NULL) | ||
316 | { | ||
317 | GNUNET_free (plain); | ||
318 | goto hkdf_error; | ||
319 | } | ||
320 | GNUNET_memcpy (result, hc, d); | ||
321 | } | ||
322 | #if DEBUG_HKDF | ||
323 | dump ("result", result - k, out_len); | ||
324 | #endif | ||
325 | |||
326 | ret = GNUNET_YES; | ||
327 | GNUNET_free (plain); | ||
328 | goto hkdf_ok; | ||
329 | } | ||
330 | hkdf_error: | ||
331 | ret = GNUNET_SYSERR; | ||
332 | hkdf_ok: | ||
333 | gcry_md_close (xtr); | ||
334 | gcry_md_close (prf); | ||
335 | BENCHMARK_END (hkdf); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | |||
340 | enum GNUNET_GenericReturnValue | ||
341 | GNUNET_CRYPTO_hkdf (void *result, | ||
342 | size_t out_len, | ||
343 | int xtr_algo, | ||
344 | int prf_algo, | ||
345 | const void *xts, | ||
346 | size_t xts_len, | ||
347 | const void *skm, | ||
348 | size_t skm_len, ...) | ||
349 | { | ||
350 | va_list argp; | ||
351 | enum GNUNET_GenericReturnValue ret; | ||
352 | |||
353 | va_start (argp, skm_len); | ||
354 | ret = | ||
355 | GNUNET_CRYPTO_hkdf_v (result, | ||
356 | out_len, | ||
357 | xtr_algo, | ||
358 | prf_algo, | ||
359 | xts, | ||
360 | xts_len, | ||
361 | skm, | ||
362 | skm_len, | ||
363 | argp); | ||
364 | va_end (argp); | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | |||
369 | /* end of crypto_hkdf.c */ | ||