1 /*
2 * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
11 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
14 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 *
16 * See the COPYRIGHT file distributed with this work for additional
17 * information regarding copyright ownership.
18 *
19 * Portions Copyright (C) Network Associates, Inc.
20 *
21 * Permission to use, copy, modify, and/or distribute this software for any
22 * purpose with or without fee is hereby granted, provided that the above
23 * copyright notice and this permission notice appear in all copies.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
26 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
28 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 */
33
34 /*
35 * Principal Author: Brian Wellington
36 * $Id: hmac_link.c,v 1.9 2020/02/25 18:10:17 florian Exp $
37 */
38
39 #include <string.h>
40
41 #include <isc/buffer.h>
42 #include <isc/hmacsha.h>
43 #include <isc/sha1.h>
44 #include <isc/util.h>
45
46 #include <dst/result.h>
47
48 #include "dst_internal.h"
49
50 static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
51
52 struct dst_hmacsha1_key {
53 unsigned char key[ISC_SHA1_BLOCK_LENGTH];
54 };
55
56 static isc_result_t
hmacsha1_createctx(dst_key_t * key,dst_context_t * dctx)57 hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
58 isc_hmacsha1_t *hmacsha1ctx;
59 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
60
61 hmacsha1ctx = malloc(sizeof(isc_hmacsha1_t));
62 if (hmacsha1ctx == NULL)
63 return (ISC_R_NOMEMORY);
64 isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
65 dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
66 return (ISC_R_SUCCESS);
67 }
68
69 static void
hmacsha1_destroyctx(dst_context_t * dctx)70 hmacsha1_destroyctx(dst_context_t *dctx) {
71 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
72
73 if (hmacsha1ctx != NULL) {
74 isc_hmacsha1_invalidate(hmacsha1ctx);
75 free(hmacsha1ctx);
76 dctx->ctxdata.hmacsha1ctx = NULL;
77 }
78 }
79
80 static isc_result_t
hmacsha1_adddata(dst_context_t * dctx,const isc_region_t * data)81 hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
82 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
83
84 isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
85 return (ISC_R_SUCCESS);
86 }
87
88 static isc_result_t
hmacsha1_sign(dst_context_t * dctx,isc_buffer_t * sig)89 hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
90 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
91 unsigned char *digest;
92
93 if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
94 return (ISC_R_NOSPACE);
95 digest = isc_buffer_used(sig);
96 isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
97 isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
98
99 return (ISC_R_SUCCESS);
100 }
101
102 static isc_result_t
hmacsha1_verify(dst_context_t * dctx,const isc_region_t * sig)103 hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
104 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
105
106 if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
107 return (DST_R_VERIFYFAILURE);
108
109 if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
110 return (ISC_R_SUCCESS);
111 else
112 return (DST_R_VERIFYFAILURE);
113 }
114
115 static void
hmacsha1_destroy(dst_key_t * key)116 hmacsha1_destroy(dst_key_t *key) {
117 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
118
119 freezero(hkey, sizeof(*hkey));
120 key->keydata.hmacsha1 = NULL;
121 }
122
123 static isc_result_t
hmacsha1_todns(const dst_key_t * key,isc_buffer_t * data)124 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
125 dst_hmacsha1_key_t *hkey;
126 unsigned int bytes;
127
128 REQUIRE(key->keydata.hmacsha1 != NULL);
129
130 hkey = key->keydata.hmacsha1;
131
132 bytes = (key->key_size + 7) / 8;
133 if (isc_buffer_availablelength(data) < bytes)
134 return (ISC_R_NOSPACE);
135 isc_buffer_putmem(data, hkey->key, bytes);
136
137 return (ISC_R_SUCCESS);
138 }
139
140 static isc_result_t
hmacsha1_fromdns(dst_key_t * key,isc_buffer_t * data)141 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
142 dst_hmacsha1_key_t *hkey;
143 int keylen;
144 isc_region_t r;
145 isc_sha1_t sha1ctx;
146
147 isc_buffer_remainingregion(data, &r);
148 if (r.length == 0)
149 return (ISC_R_SUCCESS);
150
151 hkey = malloc(sizeof(dst_hmacsha1_key_t));
152 if (hkey == NULL)
153 return (ISC_R_NOMEMORY);
154
155 memset(hkey->key, 0, sizeof(hkey->key));
156
157 if (r.length > ISC_SHA1_BLOCK_LENGTH) {
158 isc_sha1_init(&sha1ctx);
159 isc_sha1_update(&sha1ctx, r.base, r.length);
160 isc_sha1_final(&sha1ctx, hkey->key);
161 keylen = ISC_SHA1_DIGESTLENGTH;
162 } else {
163 memmove(hkey->key, r.base, r.length);
164 keylen = r.length;
165 }
166
167 key->key_size = keylen * 8;
168 key->keydata.hmacsha1 = hkey;
169
170 isc_buffer_forward(data, r.length);
171
172 return (ISC_R_SUCCESS);
173 }
174
175 static dst_func_t hmacsha1_functions = {
176 hmacsha1_createctx,
177 hmacsha1_destroyctx,
178 hmacsha1_adddata,
179 hmacsha1_sign,
180 hmacsha1_verify,
181 hmacsha1_destroy,
182 hmacsha1_todns,
183 hmacsha1_fromdns,
184 };
185
186 isc_result_t
dst__hmacsha1_init(dst_func_t ** funcp)187 dst__hmacsha1_init(dst_func_t **funcp) {
188 REQUIRE(funcp != NULL);
189 if (*funcp == NULL)
190 *funcp = &hmacsha1_functions;
191 return (ISC_R_SUCCESS);
192 }
193
194 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
195
196 struct dst_hmacsha224_key {
197 unsigned char key[ISC_SHA224_BLOCK_LENGTH];
198 };
199
200 static isc_result_t
hmacsha224_createctx(dst_key_t * key,dst_context_t * dctx)201 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
202 isc_hmacsha224_t *hmacsha224ctx;
203 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
204
205 hmacsha224ctx = malloc(sizeof(isc_hmacsha224_t));
206 if (hmacsha224ctx == NULL)
207 return (ISC_R_NOMEMORY);
208 isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
209 dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
210 return (ISC_R_SUCCESS);
211 }
212
213 static void
hmacsha224_destroyctx(dst_context_t * dctx)214 hmacsha224_destroyctx(dst_context_t *dctx) {
215 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
216
217 if (hmacsha224ctx != NULL) {
218 isc_hmacsha224_invalidate(hmacsha224ctx);
219 free(hmacsha224ctx);
220 dctx->ctxdata.hmacsha224ctx = NULL;
221 }
222 }
223
224 static isc_result_t
hmacsha224_adddata(dst_context_t * dctx,const isc_region_t * data)225 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
226 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
227
228 isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
229 return (ISC_R_SUCCESS);
230 }
231
232 static isc_result_t
hmacsha224_sign(dst_context_t * dctx,isc_buffer_t * sig)233 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
234 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
235 unsigned char *digest;
236
237 if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
238 return (ISC_R_NOSPACE);
239 digest = isc_buffer_used(sig);
240 isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
241 isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
242
243 return (ISC_R_SUCCESS);
244 }
245
246 static isc_result_t
hmacsha224_verify(dst_context_t * dctx,const isc_region_t * sig)247 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
248 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
249
250 if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
251 return (DST_R_VERIFYFAILURE);
252
253 if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
254 return (ISC_R_SUCCESS);
255 else
256 return (DST_R_VERIFYFAILURE);
257 }
258
259 static void
hmacsha224_destroy(dst_key_t * key)260 hmacsha224_destroy(dst_key_t *key) {
261 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
262
263 freezero(hkey, sizeof(*hkey));
264 key->keydata.hmacsha224 = NULL;
265 }
266
267 static isc_result_t
hmacsha224_todns(const dst_key_t * key,isc_buffer_t * data)268 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
269 dst_hmacsha224_key_t *hkey;
270 unsigned int bytes;
271
272 REQUIRE(key->keydata.hmacsha224 != NULL);
273
274 hkey = key->keydata.hmacsha224;
275
276 bytes = (key->key_size + 7) / 8;
277 if (isc_buffer_availablelength(data) < bytes)
278 return (ISC_R_NOSPACE);
279 isc_buffer_putmem(data, hkey->key, bytes);
280
281 return (ISC_R_SUCCESS);
282 }
283
284 static isc_result_t
hmacsha224_fromdns(dst_key_t * key,isc_buffer_t * data)285 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
286 dst_hmacsha224_key_t *hkey;
287 int keylen;
288 isc_region_t r;
289 isc_sha224_t sha224ctx;
290
291 isc_buffer_remainingregion(data, &r);
292 if (r.length == 0)
293 return (ISC_R_SUCCESS);
294
295 hkey = malloc(sizeof(dst_hmacsha224_key_t));
296 if (hkey == NULL)
297 return (ISC_R_NOMEMORY);
298
299 memset(hkey->key, 0, sizeof(hkey->key));
300
301 if (r.length > ISC_SHA224_BLOCK_LENGTH) {
302 isc_sha224_init(&sha224ctx);
303 isc_sha224_update(&sha224ctx, r.base, r.length);
304 isc_sha224_final(hkey->key, &sha224ctx);
305 keylen = ISC_SHA224_DIGESTLENGTH;
306 } else {
307 memmove(hkey->key, r.base, r.length);
308 keylen = r.length;
309 }
310
311 key->key_size = keylen * 8;
312 key->keydata.hmacsha224 = hkey;
313
314 isc_buffer_forward(data, r.length);
315
316 return (ISC_R_SUCCESS);
317 }
318
319 static dst_func_t hmacsha224_functions = {
320 hmacsha224_createctx,
321 hmacsha224_destroyctx,
322 hmacsha224_adddata,
323 hmacsha224_sign,
324 hmacsha224_verify,
325 hmacsha224_destroy,
326 hmacsha224_todns,
327 hmacsha224_fromdns,
328 };
329
330 isc_result_t
dst__hmacsha224_init(dst_func_t ** funcp)331 dst__hmacsha224_init(dst_func_t **funcp) {
332 REQUIRE(funcp != NULL);
333 if (*funcp == NULL)
334 *funcp = &hmacsha224_functions;
335 return (ISC_R_SUCCESS);
336 }
337
338 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
339
340 struct dst_hmacsha256_key {
341 unsigned char key[ISC_SHA256_BLOCK_LENGTH];
342 };
343
344 static isc_result_t
hmacsha256_createctx(dst_key_t * key,dst_context_t * dctx)345 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
346 isc_hmacsha256_t *hmacsha256ctx;
347 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
348
349 hmacsha256ctx = malloc(sizeof(isc_hmacsha256_t));
350 if (hmacsha256ctx == NULL)
351 return (ISC_R_NOMEMORY);
352 isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
353 dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
354 return (ISC_R_SUCCESS);
355 }
356
357 static void
hmacsha256_destroyctx(dst_context_t * dctx)358 hmacsha256_destroyctx(dst_context_t *dctx) {
359 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
360
361 if (hmacsha256ctx != NULL) {
362 isc_hmacsha256_invalidate(hmacsha256ctx);
363 free(hmacsha256ctx);
364 dctx->ctxdata.hmacsha256ctx = NULL;
365 }
366 }
367
368 static isc_result_t
hmacsha256_adddata(dst_context_t * dctx,const isc_region_t * data)369 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
370 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
371
372 isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
373 return (ISC_R_SUCCESS);
374 }
375
376 static isc_result_t
hmacsha256_sign(dst_context_t * dctx,isc_buffer_t * sig)377 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
378 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
379 unsigned char *digest;
380
381 if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
382 return (ISC_R_NOSPACE);
383 digest = isc_buffer_used(sig);
384 isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
385 isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
386
387 return (ISC_R_SUCCESS);
388 }
389
390 static isc_result_t
hmacsha256_verify(dst_context_t * dctx,const isc_region_t * sig)391 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
392 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
393
394 if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
395 return (DST_R_VERIFYFAILURE);
396
397 if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
398 return (ISC_R_SUCCESS);
399 else
400 return (DST_R_VERIFYFAILURE);
401 }
402
403 static void
hmacsha256_destroy(dst_key_t * key)404 hmacsha256_destroy(dst_key_t *key) {
405 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
406
407 freezero(hkey, sizeof(*hkey));
408 key->keydata.hmacsha256 = NULL;
409 }
410
411 static isc_result_t
hmacsha256_todns(const dst_key_t * key,isc_buffer_t * data)412 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
413 dst_hmacsha256_key_t *hkey;
414 unsigned int bytes;
415
416 REQUIRE(key->keydata.hmacsha256 != NULL);
417
418 hkey = key->keydata.hmacsha256;
419
420 bytes = (key->key_size + 7) / 8;
421 if (isc_buffer_availablelength(data) < bytes)
422 return (ISC_R_NOSPACE);
423 isc_buffer_putmem(data, hkey->key, bytes);
424
425 return (ISC_R_SUCCESS);
426 }
427
428 static isc_result_t
hmacsha256_fromdns(dst_key_t * key,isc_buffer_t * data)429 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
430 dst_hmacsha256_key_t *hkey;
431 int keylen;
432 isc_region_t r;
433 isc_sha256_t sha256ctx;
434
435 isc_buffer_remainingregion(data, &r);
436 if (r.length == 0)
437 return (ISC_R_SUCCESS);
438
439 hkey = malloc(sizeof(dst_hmacsha256_key_t));
440 if (hkey == NULL)
441 return (ISC_R_NOMEMORY);
442
443 memset(hkey->key, 0, sizeof(hkey->key));
444
445 if (r.length > ISC_SHA256_BLOCK_LENGTH) {
446 isc_sha256_init(&sha256ctx);
447 isc_sha256_update(&sha256ctx, r.base, r.length);
448 isc_sha256_final(hkey->key, &sha256ctx);
449 keylen = ISC_SHA256_DIGESTLENGTH;
450 } else {
451 memmove(hkey->key, r.base, r.length);
452 keylen = r.length;
453 }
454
455 key->key_size = keylen * 8;
456 key->keydata.hmacsha256 = hkey;
457
458 isc_buffer_forward(data, r.length);
459
460 return (ISC_R_SUCCESS);
461 }
462
463 static dst_func_t hmacsha256_functions = {
464 hmacsha256_createctx,
465 hmacsha256_destroyctx,
466 hmacsha256_adddata,
467 hmacsha256_sign,
468 hmacsha256_verify,
469 hmacsha256_destroy,
470 hmacsha256_todns,
471 hmacsha256_fromdns,
472 };
473
474 isc_result_t
dst__hmacsha256_init(dst_func_t ** funcp)475 dst__hmacsha256_init(dst_func_t **funcp) {
476 REQUIRE(funcp != NULL);
477 if (*funcp == NULL)
478 *funcp = &hmacsha256_functions;
479 return (ISC_R_SUCCESS);
480 }
481
482 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
483
484 struct dst_hmacsha384_key {
485 unsigned char key[ISC_SHA384_BLOCK_LENGTH];
486 };
487
488 static isc_result_t
hmacsha384_createctx(dst_key_t * key,dst_context_t * dctx)489 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
490 isc_hmacsha384_t *hmacsha384ctx;
491 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
492
493 hmacsha384ctx = malloc(sizeof(isc_hmacsha384_t));
494 if (hmacsha384ctx == NULL)
495 return (ISC_R_NOMEMORY);
496 isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
497 dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
498 return (ISC_R_SUCCESS);
499 }
500
501 static void
hmacsha384_destroyctx(dst_context_t * dctx)502 hmacsha384_destroyctx(dst_context_t *dctx) {
503 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
504
505 if (hmacsha384ctx != NULL) {
506 isc_hmacsha384_invalidate(hmacsha384ctx);
507 free(hmacsha384ctx);
508 dctx->ctxdata.hmacsha384ctx = NULL;
509 }
510 }
511
512 static isc_result_t
hmacsha384_adddata(dst_context_t * dctx,const isc_region_t * data)513 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
514 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
515
516 isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
517 return (ISC_R_SUCCESS);
518 }
519
520 static isc_result_t
hmacsha384_sign(dst_context_t * dctx,isc_buffer_t * sig)521 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
522 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
523 unsigned char *digest;
524
525 if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
526 return (ISC_R_NOSPACE);
527 digest = isc_buffer_used(sig);
528 isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
529 isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
530
531 return (ISC_R_SUCCESS);
532 }
533
534 static isc_result_t
hmacsha384_verify(dst_context_t * dctx,const isc_region_t * sig)535 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
536 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
537
538 if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
539 return (DST_R_VERIFYFAILURE);
540
541 if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
542 return (ISC_R_SUCCESS);
543 else
544 return (DST_R_VERIFYFAILURE);
545 }
546
547 static void
hmacsha384_destroy(dst_key_t * key)548 hmacsha384_destroy(dst_key_t *key) {
549 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
550
551 freezero(hkey, sizeof(*hkey));
552 key->keydata.hmacsha384 = NULL;
553 }
554
555 static isc_result_t
hmacsha384_todns(const dst_key_t * key,isc_buffer_t * data)556 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
557 dst_hmacsha384_key_t *hkey;
558 unsigned int bytes;
559
560 REQUIRE(key->keydata.hmacsha384 != NULL);
561
562 hkey = key->keydata.hmacsha384;
563
564 bytes = (key->key_size + 7) / 8;
565 if (isc_buffer_availablelength(data) < bytes)
566 return (ISC_R_NOSPACE);
567 isc_buffer_putmem(data, hkey->key, bytes);
568
569 return (ISC_R_SUCCESS);
570 }
571
572 static isc_result_t
hmacsha384_fromdns(dst_key_t * key,isc_buffer_t * data)573 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
574 dst_hmacsha384_key_t *hkey;
575 int keylen;
576 isc_region_t r;
577 isc_sha384_t sha384ctx;
578
579 isc_buffer_remainingregion(data, &r);
580 if (r.length == 0)
581 return (ISC_R_SUCCESS);
582
583 hkey = malloc(sizeof(dst_hmacsha384_key_t));
584 if (hkey == NULL)
585 return (ISC_R_NOMEMORY);
586
587 memset(hkey->key, 0, sizeof(hkey->key));
588
589 if (r.length > ISC_SHA384_BLOCK_LENGTH) {
590 isc_sha384_init(&sha384ctx);
591 isc_sha384_update(&sha384ctx, r.base, r.length);
592 isc_sha384_final(hkey->key, &sha384ctx);
593 keylen = ISC_SHA384_DIGESTLENGTH;
594 } else {
595 memmove(hkey->key, r.base, r.length);
596 keylen = r.length;
597 }
598
599 key->key_size = keylen * 8;
600 key->keydata.hmacsha384 = hkey;
601
602 isc_buffer_forward(data, r.length);
603
604 return (ISC_R_SUCCESS);
605 }
606
607 static dst_func_t hmacsha384_functions = {
608 hmacsha384_createctx,
609 hmacsha384_destroyctx,
610 hmacsha384_adddata,
611 hmacsha384_sign,
612 hmacsha384_verify,
613 hmacsha384_destroy,
614 hmacsha384_todns,
615 hmacsha384_fromdns,
616 };
617
618 isc_result_t
dst__hmacsha384_init(dst_func_t ** funcp)619 dst__hmacsha384_init(dst_func_t **funcp) {
620 REQUIRE(funcp != NULL);
621 if (*funcp == NULL)
622 *funcp = &hmacsha384_functions;
623 return (ISC_R_SUCCESS);
624 }
625
626 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
627
628 struct dst_hmacsha512_key {
629 unsigned char key[ISC_SHA512_BLOCK_LENGTH];
630 };
631
632 static isc_result_t
hmacsha512_createctx(dst_key_t * key,dst_context_t * dctx)633 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
634 isc_hmacsha512_t *hmacsha512ctx;
635 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
636
637 hmacsha512ctx = malloc(sizeof(isc_hmacsha512_t));
638 if (hmacsha512ctx == NULL)
639 return (ISC_R_NOMEMORY);
640 isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
641 dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
642 return (ISC_R_SUCCESS);
643 }
644
645 static void
hmacsha512_destroyctx(dst_context_t * dctx)646 hmacsha512_destroyctx(dst_context_t *dctx) {
647 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
648
649 if (hmacsha512ctx != NULL) {
650 isc_hmacsha512_invalidate(hmacsha512ctx);
651 free(hmacsha512ctx);
652 dctx->ctxdata.hmacsha512ctx = NULL;
653 }
654 }
655
656 static isc_result_t
hmacsha512_adddata(dst_context_t * dctx,const isc_region_t * data)657 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
658 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
659
660 isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
661 return (ISC_R_SUCCESS);
662 }
663
664 static isc_result_t
hmacsha512_sign(dst_context_t * dctx,isc_buffer_t * sig)665 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
666 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
667 unsigned char *digest;
668
669 if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
670 return (ISC_R_NOSPACE);
671 digest = isc_buffer_used(sig);
672 isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
673 isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
674
675 return (ISC_R_SUCCESS);
676 }
677
678 static isc_result_t
hmacsha512_verify(dst_context_t * dctx,const isc_region_t * sig)679 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
680 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
681
682 if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
683 return (DST_R_VERIFYFAILURE);
684
685 if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
686 return (ISC_R_SUCCESS);
687 else
688 return (DST_R_VERIFYFAILURE);
689 }
690
691 static void
hmacsha512_destroy(dst_key_t * key)692 hmacsha512_destroy(dst_key_t *key) {
693 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
694
695 freezero(hkey, sizeof(*hkey));
696 key->keydata.hmacsha512 = NULL;
697 }
698
699 static isc_result_t
hmacsha512_todns(const dst_key_t * key,isc_buffer_t * data)700 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
701 dst_hmacsha512_key_t *hkey;
702 unsigned int bytes;
703
704 REQUIRE(key->keydata.hmacsha512 != NULL);
705
706 hkey = key->keydata.hmacsha512;
707
708 bytes = (key->key_size + 7) / 8;
709 if (isc_buffer_availablelength(data) < bytes)
710 return (ISC_R_NOSPACE);
711 isc_buffer_putmem(data, hkey->key, bytes);
712
713 return (ISC_R_SUCCESS);
714 }
715
716 static isc_result_t
hmacsha512_fromdns(dst_key_t * key,isc_buffer_t * data)717 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
718 dst_hmacsha512_key_t *hkey;
719 int keylen;
720 isc_region_t r;
721 isc_sha512_t sha512ctx;
722
723 isc_buffer_remainingregion(data, &r);
724 if (r.length == 0)
725 return (ISC_R_SUCCESS);
726
727 hkey = malloc(sizeof(dst_hmacsha512_key_t));
728 if (hkey == NULL)
729 return (ISC_R_NOMEMORY);
730
731 memset(hkey->key, 0, sizeof(hkey->key));
732
733 if (r.length > ISC_SHA512_BLOCK_LENGTH) {
734 isc_sha512_init(&sha512ctx);
735 isc_sha512_update(&sha512ctx, r.base, r.length);
736 isc_sha512_final(hkey->key, &sha512ctx);
737 keylen = ISC_SHA512_DIGESTLENGTH;
738 } else {
739 memmove(hkey->key, r.base, r.length);
740 keylen = r.length;
741 }
742
743 key->key_size = keylen * 8;
744 key->keydata.hmacsha512 = hkey;
745
746 isc_buffer_forward(data, r.length);
747
748 return (ISC_R_SUCCESS);
749 }
750
751 static dst_func_t hmacsha512_functions = {
752 hmacsha512_createctx,
753 hmacsha512_destroyctx,
754 hmacsha512_adddata,
755 hmacsha512_sign,
756 hmacsha512_verify,
757 hmacsha512_destroy,
758 hmacsha512_todns,
759 hmacsha512_fromdns,
760 };
761
762 isc_result_t
dst__hmacsha512_init(dst_func_t ** funcp)763 dst__hmacsha512_init(dst_func_t **funcp) {
764 REQUIRE(funcp != NULL);
765 if (*funcp == NULL)
766 *funcp = &hmacsha512_functions;
767 return (ISC_R_SUCCESS);
768 }
769
770 /*! \file */
771