aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_hkdf.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 13:37:38 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 13:37:38 +0200
commit9ef4abad615bea12d13be542b8ae5fbeb2dfee32 (patch)
tree8875a687e004d331c9ea6a1d511a328c72b88113 /src/util/crypto_hkdf.c
parente95236b3ed78cd597c15f34b89385295702b627f (diff)
downloadgnunet-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.c369
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 */
77static const void *
78doHMAC (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 */
107static enum GNUNET_GenericReturnValue
108getPRK (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
148static void
149dump (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
165enum GNUNET_GenericReturnValue
166GNUNET_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 }
330hkdf_error:
331 ret = GNUNET_SYSERR;
332hkdf_ok:
333 gcry_md_close (xtr);
334 gcry_md_close (prf);
335 BENCHMARK_END (hkdf);
336 return ret;
337}
338
339
340enum GNUNET_GenericReturnValue
341GNUNET_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 */