diff options
Diffstat (limited to 'src/util/crypto_hkdf.c')
-rw-r--r-- | src/util/crypto_hkdf.c | 341 |
1 files changed, 0 insertions, 341 deletions
diff --git a/src/util/crypto_hkdf.c b/src/util/crypto_hkdf.c deleted file mode 100644 index 7270b87b6..000000000 --- a/src/util/crypto_hkdf.c +++ /dev/null | |||
@@ -1,341 +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, const void *key, size_t key_len, const void *buf, | ||
78 | size_t buf_len) | ||
79 | { | ||
80 | if (GPG_ERR_NO_ERROR != gcry_md_setkey (mac, key, key_len)) | ||
81 | { | ||
82 | GNUNET_break (0); | ||
83 | return NULL; | ||
84 | } | ||
85 | gcry_md_write (mac, buf, buf_len); | ||
86 | |||
87 | return (const void *) gcry_md_read (mac, 0); | ||
88 | } | ||
89 | |||
90 | |||
91 | /** | ||
92 | * @brief Generate pseudo-random key | ||
93 | * @param mac gcrypt HMAC handle | ||
94 | * @param xts salt | ||
95 | * @param xts_len length of the @a xts salt | ||
96 | * @param skm source key material | ||
97 | * @param skm_len length of @a skm | ||
98 | * @param prk result buffer (allocated by caller; at least gcry_md_dlen() bytes) | ||
99 | * @return #GNUNET_YES on success | ||
100 | */ | ||
101 | static int | ||
102 | getPRK (gcry_md_hd_t mac, const void *xts, size_t xts_len, const void *skm, | ||
103 | size_t skm_len, void *prk) | ||
104 | { | ||
105 | const void *ret; | ||
106 | |||
107 | ret = doHMAC (mac, xts, xts_len, skm, skm_len); | ||
108 | if (ret == NULL) | ||
109 | return GNUNET_SYSERR; | ||
110 | GNUNET_memcpy (prk, ret, gcry_md_get_algo_dlen (gcry_md_get_algo (mac))); | ||
111 | |||
112 | return GNUNET_YES; | ||
113 | } | ||
114 | |||
115 | |||
116 | #if DEBUG_HKDF | ||
117 | static void | ||
118 | dump (const char *src, const void *p, unsigned int l) | ||
119 | { | ||
120 | unsigned int i; | ||
121 | |||
122 | printf ("\n%s: ", src); | ||
123 | for (i = 0; i < l; i++) | ||
124 | { | ||
125 | printf ("%2x", (int) ((const unsigned char *) p)[i]); | ||
126 | } | ||
127 | printf ("\n"); | ||
128 | } | ||
129 | |||
130 | |||
131 | #endif | ||
132 | |||
133 | |||
134 | /** | ||
135 | * @brief Derive key | ||
136 | * @param result buffer for the derived key, allocated by caller | ||
137 | * @param out_len desired length of the derived key | ||
138 | * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... | ||
139 | * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... | ||
140 | * @param xts salt | ||
141 | * @param xts_len length of @a xts | ||
142 | * @param skm source key material | ||
143 | * @param skm_len length of @a skm | ||
144 | * @param argp va_list of void * & size_t pairs for context chunks | ||
145 | * @return #GNUNET_YES on success | ||
146 | */ | ||
147 | int | ||
148 | GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo, | ||
149 | const void *xts, size_t xts_len, const void *skm, | ||
150 | size_t skm_len, va_list argp) | ||
151 | { | ||
152 | gcry_md_hd_t xtr; | ||
153 | gcry_md_hd_t prf; | ||
154 | const void *hc; | ||
155 | unsigned long i; | ||
156 | unsigned long t; | ||
157 | unsigned long d; | ||
158 | unsigned int k = gcry_md_get_algo_dlen (prf_algo); | ||
159 | unsigned int xtr_len = gcry_md_get_algo_dlen (xtr_algo); | ||
160 | char prk[xtr_len]; | ||
161 | int ret; | ||
162 | size_t ctx_len; | ||
163 | va_list args; | ||
164 | |||
165 | BENCHMARK_START (hkdf); | ||
166 | |||
167 | if (0 == k) | ||
168 | return GNUNET_SYSERR; | ||
169 | if (GPG_ERR_NO_ERROR != | ||
170 | gcry_md_open (&xtr, xtr_algo, GCRY_MD_FLAG_HMAC)) | ||
171 | return GNUNET_SYSERR; | ||
172 | if (GPG_ERR_NO_ERROR != | ||
173 | gcry_md_open (&prf, prf_algo, GCRY_MD_FLAG_HMAC)) | ||
174 | { | ||
175 | gcry_md_close (xtr); | ||
176 | return GNUNET_SYSERR; | ||
177 | } | ||
178 | va_copy (args, argp); | ||
179 | |||
180 | ctx_len = 0; | ||
181 | while (NULL != va_arg (args, void *)) | ||
182 | { | ||
183 | size_t nxt = va_arg (args, size_t); | ||
184 | if (nxt + ctx_len < nxt) | ||
185 | { | ||
186 | /* integer overflow */ | ||
187 | GNUNET_break (0); | ||
188 | va_end (args); | ||
189 | goto hkdf_error; | ||
190 | } | ||
191 | ctx_len += nxt; | ||
192 | } | ||
193 | |||
194 | va_end (args); | ||
195 | |||
196 | if ( (k + ctx_len < ctx_len) || | ||
197 | (k + ctx_len + 1 < ctx_len) ) | ||
198 | { | ||
199 | /* integer overflow */ | ||
200 | GNUNET_break (0); | ||
201 | goto hkdf_error; | ||
202 | } | ||
203 | |||
204 | memset (result, 0, out_len); | ||
205 | if (getPRK (xtr, xts, xts_len, skm, skm_len, prk) != GNUNET_YES) | ||
206 | goto hkdf_error; | ||
207 | #if DEBUG_HKDF | ||
208 | dump ("PRK", prk, xtr_len); | ||
209 | #endif | ||
210 | |||
211 | t = out_len / k; | ||
212 | d = out_len % k; | ||
213 | |||
214 | /* K(1) */ | ||
215 | { | ||
216 | size_t plain_len = k + ctx_len + 1; | ||
217 | char *plain; | ||
218 | const void *ctx; | ||
219 | char *dst; | ||
220 | |||
221 | plain = GNUNET_malloc (plain_len); | ||
222 | dst = plain + k; | ||
223 | va_copy (args, argp); | ||
224 | while ((ctx = va_arg (args, void *))) | ||
225 | { | ||
226 | size_t len; | ||
227 | |||
228 | len = va_arg (args, size_t); | ||
229 | GNUNET_memcpy (dst, ctx, len); | ||
230 | dst += len; | ||
231 | } | ||
232 | va_end (args); | ||
233 | |||
234 | if (t > 0) | ||
235 | { | ||
236 | plain[k + ctx_len] = (char) 1; | ||
237 | #if DEBUG_HKDF | ||
238 | dump ("K(1)", plain, plain_len); | ||
239 | #endif | ||
240 | hc = doHMAC (prf, prk, xtr_len, &plain[k], ctx_len + 1); | ||
241 | if (hc == NULL) | ||
242 | { | ||
243 | GNUNET_free (plain); | ||
244 | goto hkdf_error; | ||
245 | } | ||
246 | GNUNET_memcpy (result, hc, k); | ||
247 | result += k; | ||
248 | } | ||
249 | |||
250 | /* K(i+1) */ | ||
251 | for (i = 1; i < t; i++) | ||
252 | { | ||
253 | GNUNET_memcpy (plain, result - k, k); | ||
254 | plain[k + ctx_len] = (char) (i + 1); | ||
255 | gcry_md_reset (prf); | ||
256 | #if DEBUG_HKDF | ||
257 | dump ("K(i+1)", plain, plain_len); | ||
258 | #endif | ||
259 | hc = doHMAC (prf, prk, xtr_len, plain, plain_len); | ||
260 | if (hc == NULL) | ||
261 | { | ||
262 | GNUNET_free (plain); | ||
263 | goto hkdf_error; | ||
264 | } | ||
265 | GNUNET_memcpy (result, hc, k); | ||
266 | result += k; | ||
267 | } | ||
268 | |||
269 | /* K(t):d */ | ||
270 | if (d > 0) | ||
271 | { | ||
272 | if (t > 0) | ||
273 | { | ||
274 | GNUNET_memcpy (plain, result - k, k); | ||
275 | i++; | ||
276 | } | ||
277 | plain[k + ctx_len] = (char) i; | ||
278 | gcry_md_reset (prf); | ||
279 | #if DEBUG_HKDF | ||
280 | dump ("K(t):d", plain, plain_len); | ||
281 | #endif | ||
282 | if (t > 0) | ||
283 | hc = doHMAC (prf, prk, xtr_len, plain, plain_len); | ||
284 | else | ||
285 | hc = doHMAC (prf, prk, xtr_len, plain + k, plain_len - k); | ||
286 | if (hc == NULL) | ||
287 | { | ||
288 | GNUNET_free (plain); | ||
289 | goto hkdf_error; | ||
290 | } | ||
291 | GNUNET_memcpy (result, hc, d); | ||
292 | } | ||
293 | #if DEBUG_HKDF | ||
294 | dump ("result", result - k, out_len); | ||
295 | #endif | ||
296 | |||
297 | ret = GNUNET_YES; | ||
298 | GNUNET_free (plain); | ||
299 | goto hkdf_ok; | ||
300 | } | ||
301 | hkdf_error: | ||
302 | ret = GNUNET_SYSERR; | ||
303 | hkdf_ok: | ||
304 | gcry_md_close (xtr); | ||
305 | gcry_md_close (prf); | ||
306 | BENCHMARK_END (hkdf); | ||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | |||
311 | /** | ||
312 | * @brief Derive key | ||
313 | * @param result buffer for the derived key, allocated by caller | ||
314 | * @param out_len desired length of the derived key | ||
315 | * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... | ||
316 | * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... | ||
317 | * @param xts salt | ||
318 | * @param xts_len length of @a xts | ||
319 | * @param skm source key material | ||
320 | * @param skm_len length of @a skm | ||
321 | * @return #GNUNET_YES on success | ||
322 | */ | ||
323 | int | ||
324 | GNUNET_CRYPTO_hkdf (void *result, size_t out_len, int xtr_algo, int prf_algo, | ||
325 | const void *xts, size_t xts_len, const void *skm, | ||
326 | size_t skm_len, ...) | ||
327 | { | ||
328 | va_list argp; | ||
329 | int ret; | ||
330 | |||
331 | va_start (argp, skm_len); | ||
332 | ret = | ||
333 | GNUNET_CRYPTO_hkdf_v (result, out_len, xtr_algo, prf_algo, xts, xts_len, | ||
334 | skm, skm_len, argp); | ||
335 | va_end (argp); | ||
336 | |||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | |||
341 | /* end of crypto_hkdf.c */ | ||