]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/bind9/lib/dns/hmac_link.c
Fix remote denial of service vulnerability when parsing malformed
[FreeBSD/releng/9.3.git] / contrib / bind9 / lib / dns / hmac_link.c
1 /*
2  * Portions Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
3  * Portions Copyright (C) 1999-2002  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
10  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
12  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  *
17  * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
18  *
19  * Permission to use, copy, modify, and/or distribute this software for any
20  * purpose with or without fee is hereby granted, provided that the above
21  * copyright notice and this permission notice appear in all copies.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
24  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
26  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
28  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
29  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30  */
31
32 /*
33  * Principal Author: Brian Wellington
34  * $Id: hmac_link.c,v 1.19 2011/01/11 23:47:13 tbox Exp $
35  */
36
37 #include <config.h>
38
39 #include <isc/buffer.h>
40 #include <isc/hmacmd5.h>
41 #include <isc/hmacsha.h>
42 #include <isc/md5.h>
43 #include <isc/sha1.h>
44 #include <isc/mem.h>
45 #include <isc/safe.h>
46 #include <isc/string.h>
47 #include <isc/util.h>
48
49 #include <dst/result.h>
50
51 #include "dst_internal.h"
52 #include "dst_parse.h"
53
54 static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
55
56 struct dst_hmacmd5_key {
57         unsigned char key[ISC_MD5_BLOCK_LENGTH];
58 };
59
60 static isc_result_t
61 getkeybits(dst_key_t *key, struct dst_private_element *element) {
62
63         if (element->length != 2)
64                 return (DST_R_INVALIDPRIVATEKEY);
65
66         key->key_bits = (element->data[0] << 8) + element->data[1];
67
68         return (ISC_R_SUCCESS);
69 }
70
71 static isc_result_t
72 hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
73         isc_hmacmd5_t *hmacmd5ctx;
74         dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
75
76         hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
77         if (hmacmd5ctx == NULL)
78                 return (ISC_R_NOMEMORY);
79         isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_MD5_BLOCK_LENGTH);
80         dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
81         return (ISC_R_SUCCESS);
82 }
83
84 static void
85 hmacmd5_destroyctx(dst_context_t *dctx) {
86         isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
87
88         if (hmacmd5ctx != NULL) {
89                 isc_hmacmd5_invalidate(hmacmd5ctx);
90                 isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
91                 dctx->ctxdata.hmacmd5ctx = NULL;
92         }
93 }
94
95 static isc_result_t
96 hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
97         isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
98
99         isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
100         return (ISC_R_SUCCESS);
101 }
102
103 static isc_result_t
104 hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
105         isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
106         unsigned char *digest;
107
108         if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
109                 return (ISC_R_NOSPACE);
110         digest = isc_buffer_used(sig);
111         isc_hmacmd5_sign(hmacmd5ctx, digest);
112         isc_buffer_add(sig, ISC_MD5_DIGESTLENGTH);
113
114         return (ISC_R_SUCCESS);
115 }
116
117 static isc_result_t
118 hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
119         isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
120
121         if (sig->length > ISC_MD5_DIGESTLENGTH)
122                 return (DST_R_VERIFYFAILURE);
123
124         if (isc_hmacmd5_verify2(hmacmd5ctx, sig->base, sig->length))
125                 return (ISC_R_SUCCESS);
126         else
127                 return (DST_R_VERIFYFAILURE);
128 }
129
130 static isc_boolean_t
131 hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
132         dst_hmacmd5_key_t *hkey1, *hkey2;
133
134         hkey1 = key1->keydata.hmacmd5;
135         hkey2 = key2->keydata.hmacmd5;
136
137         if (hkey1 == NULL && hkey2 == NULL)
138                 return (ISC_TRUE);
139         else if (hkey1 == NULL || hkey2 == NULL)
140                 return (ISC_FALSE);
141
142         if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_MD5_BLOCK_LENGTH))
143                 return (ISC_TRUE);
144         else
145                 return (ISC_FALSE);
146 }
147
148 static isc_result_t
149 hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
150         isc_buffer_t b;
151         isc_result_t ret;
152         unsigned int bytes;
153         unsigned char data[ISC_MD5_BLOCK_LENGTH];
154
155         UNUSED(callback);
156
157         bytes = (key->key_size + 7) / 8;
158         if (bytes > ISC_MD5_BLOCK_LENGTH) {
159                 bytes = ISC_MD5_BLOCK_LENGTH;
160                 key->key_size = ISC_MD5_BLOCK_LENGTH * 8;
161         }
162
163         memset(data, 0, ISC_MD5_BLOCK_LENGTH);
164         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
165
166         if (ret != ISC_R_SUCCESS)
167                 return (ret);
168
169         isc_buffer_init(&b, data, bytes);
170         isc_buffer_add(&b, bytes);
171         ret = hmacmd5_fromdns(key, &b);
172         memset(data, 0, ISC_MD5_BLOCK_LENGTH);
173
174         return (ret);
175 }
176
177 static isc_boolean_t
178 hmacmd5_isprivate(const dst_key_t *key) {
179         UNUSED(key);
180         return (ISC_TRUE);
181 }
182
183 static void
184 hmacmd5_destroy(dst_key_t *key) {
185         dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
186
187         memset(hkey, 0, sizeof(dst_hmacmd5_key_t));
188         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacmd5_key_t));
189         key->keydata.hmacmd5 = NULL;
190 }
191
192 static isc_result_t
193 hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
194         dst_hmacmd5_key_t *hkey;
195         unsigned int bytes;
196
197         REQUIRE(key->keydata.hmacmd5 != NULL);
198
199         hkey = key->keydata.hmacmd5;
200
201         bytes = (key->key_size + 7) / 8;
202         if (isc_buffer_availablelength(data) < bytes)
203                 return (ISC_R_NOSPACE);
204         isc_buffer_putmem(data, hkey->key, bytes);
205
206         return (ISC_R_SUCCESS);
207 }
208
209 static isc_result_t
210 hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
211         dst_hmacmd5_key_t *hkey;
212         int keylen;
213         isc_region_t r;
214         isc_md5_t md5ctx;
215
216         isc_buffer_remainingregion(data, &r);
217         if (r.length == 0)
218                 return (ISC_R_SUCCESS);
219
220         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
221         if (hkey == NULL)
222                 return (ISC_R_NOMEMORY);
223
224         memset(hkey->key, 0, sizeof(hkey->key));
225
226         if (r.length > ISC_MD5_BLOCK_LENGTH) {
227                 isc_md5_init(&md5ctx);
228                 isc_md5_update(&md5ctx, r.base, r.length);
229                 isc_md5_final(&md5ctx, hkey->key);
230                 keylen = ISC_MD5_DIGESTLENGTH;
231         } else {
232                 memmove(hkey->key, r.base, r.length);
233                 keylen = r.length;
234         }
235
236         key->key_size = keylen * 8;
237         key->keydata.hmacmd5 = hkey;
238
239         isc_buffer_forward(data, r.length);
240
241         return (ISC_R_SUCCESS);
242 }
243
244 static isc_result_t
245 hmacmd5_tofile(const dst_key_t *key, const char *directory) {
246         int cnt = 0;
247         dst_hmacmd5_key_t *hkey;
248         dst_private_t priv;
249         int bytes = (key->key_size + 7) / 8;
250         unsigned char buf[2];
251
252         if (key->keydata.hmacmd5 == NULL)
253                 return (DST_R_NULLKEY);
254
255         hkey = key->keydata.hmacmd5;
256
257         priv.elements[cnt].tag = TAG_HMACMD5_KEY;
258         priv.elements[cnt].length = bytes;
259         priv.elements[cnt++].data = hkey->key;
260
261         buf[0] = (key->key_bits >> 8) & 0xffU;
262         buf[1] = key->key_bits & 0xffU;
263         priv.elements[cnt].tag = TAG_HMACMD5_BITS;
264         priv.elements[cnt].data = buf;
265         priv.elements[cnt++].length = 2;
266
267         priv.nelements = cnt;
268         return (dst__privstruct_writefile(key, &priv, directory));
269 }
270
271 static isc_result_t
272 hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
273         dst_private_t priv;
274         isc_result_t result, tresult;
275         isc_buffer_t b;
276         isc_mem_t *mctx = key->mctx;
277         unsigned int i;
278
279         UNUSED(pub);
280         /* read private key file */
281         result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx,
282                                        &priv);
283         if (result != ISC_R_SUCCESS)
284                 return (result);
285
286         key->key_bits = 0;
287         for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
288                 switch (priv.elements[i].tag) {
289                 case TAG_HMACMD5_KEY:
290                         isc_buffer_init(&b, priv.elements[i].data,
291                                         priv.elements[i].length);
292                         isc_buffer_add(&b, priv.elements[i].length);
293                         tresult = hmacmd5_fromdns(key, &b);
294                         if (tresult != ISC_R_SUCCESS)
295                                 result = tresult;
296                         break;
297                 case TAG_HMACMD5_BITS:
298                         tresult = getkeybits(key, &priv.elements[i]);
299                         if (tresult != ISC_R_SUCCESS)
300                                 result = tresult;
301                         break;
302                 default:
303                         result = DST_R_INVALIDPRIVATEKEY;
304                         break;
305                 }
306         }
307         dst__privstruct_free(&priv, mctx);
308         memset(&priv, 0, sizeof(priv));
309         return (result);
310 }
311
312 static dst_func_t hmacmd5_functions = {
313         hmacmd5_createctx,
314         hmacmd5_destroyctx,
315         hmacmd5_adddata,
316         hmacmd5_sign,
317         hmacmd5_verify,
318         NULL, /*%< verify2 */
319         NULL, /*%< computesecret */
320         hmacmd5_compare,
321         NULL, /*%< paramcompare */
322         hmacmd5_generate,
323         hmacmd5_isprivate,
324         hmacmd5_destroy,
325         hmacmd5_todns,
326         hmacmd5_fromdns,
327         hmacmd5_tofile,
328         hmacmd5_parse,
329         NULL, /*%< cleanup */
330         NULL, /*%< fromlabel */
331         NULL, /*%< dump */
332         NULL, /*%< restore */
333 };
334
335 isc_result_t
336 dst__hmacmd5_init(dst_func_t **funcp) {
337         REQUIRE(funcp != NULL);
338         if (*funcp == NULL)
339                 *funcp = &hmacmd5_functions;
340         return (ISC_R_SUCCESS);
341 }
342
343 static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
344
345 struct dst_hmacsha1_key {
346         unsigned char key[ISC_SHA1_BLOCK_LENGTH];
347 };
348
349 static isc_result_t
350 hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
351         isc_hmacsha1_t *hmacsha1ctx;
352         dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
353
354         hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
355         if (hmacsha1ctx == NULL)
356                 return (ISC_R_NOMEMORY);
357         isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
358         dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
359         return (ISC_R_SUCCESS);
360 }
361
362 static void
363 hmacsha1_destroyctx(dst_context_t *dctx) {
364         isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
365
366         if (hmacsha1ctx != NULL) {
367                 isc_hmacsha1_invalidate(hmacsha1ctx);
368                 isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
369                 dctx->ctxdata.hmacsha1ctx = NULL;
370         }
371 }
372
373 static isc_result_t
374 hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
375         isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
376
377         isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
378         return (ISC_R_SUCCESS);
379 }
380
381 static isc_result_t
382 hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
383         isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
384         unsigned char *digest;
385
386         if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
387                 return (ISC_R_NOSPACE);
388         digest = isc_buffer_used(sig);
389         isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
390         isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
391
392         return (ISC_R_SUCCESS);
393 }
394
395 static isc_result_t
396 hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
397         isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
398
399         if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
400                 return (DST_R_VERIFYFAILURE);
401
402         if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
403                 return (ISC_R_SUCCESS);
404         else
405                 return (DST_R_VERIFYFAILURE);
406 }
407
408 static isc_boolean_t
409 hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
410         dst_hmacsha1_key_t *hkey1, *hkey2;
411
412         hkey1 = key1->keydata.hmacsha1;
413         hkey2 = key2->keydata.hmacsha1;
414
415         if (hkey1 == NULL && hkey2 == NULL)
416                 return (ISC_TRUE);
417         else if (hkey1 == NULL || hkey2 == NULL)
418                 return (ISC_FALSE);
419
420         if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
421                 return (ISC_TRUE);
422         else
423                 return (ISC_FALSE);
424 }
425
426 static isc_result_t
427 hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
428         isc_buffer_t b;
429         isc_result_t ret;
430         unsigned int bytes;
431         unsigned char data[ISC_SHA1_BLOCK_LENGTH];
432
433         UNUSED(callback);
434
435         bytes = (key->key_size + 7) / 8;
436         if (bytes > ISC_SHA1_BLOCK_LENGTH) {
437                 bytes = ISC_SHA1_BLOCK_LENGTH;
438                 key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
439         }
440
441         memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
442         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
443
444         if (ret != ISC_R_SUCCESS)
445                 return (ret);
446
447         isc_buffer_init(&b, data, bytes);
448         isc_buffer_add(&b, bytes);
449         ret = hmacsha1_fromdns(key, &b);
450         memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
451
452         return (ret);
453 }
454
455 static isc_boolean_t
456 hmacsha1_isprivate(const dst_key_t *key) {
457         UNUSED(key);
458         return (ISC_TRUE);
459 }
460
461 static void
462 hmacsha1_destroy(dst_key_t *key) {
463         dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
464
465         memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
466         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
467         key->keydata.hmacsha1 = NULL;
468 }
469
470 static isc_result_t
471 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
472         dst_hmacsha1_key_t *hkey;
473         unsigned int bytes;
474
475         REQUIRE(key->keydata.hmacsha1 != NULL);
476
477         hkey = key->keydata.hmacsha1;
478
479         bytes = (key->key_size + 7) / 8;
480         if (isc_buffer_availablelength(data) < bytes)
481                 return (ISC_R_NOSPACE);
482         isc_buffer_putmem(data, hkey->key, bytes);
483
484         return (ISC_R_SUCCESS);
485 }
486
487 static isc_result_t
488 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
489         dst_hmacsha1_key_t *hkey;
490         int keylen;
491         isc_region_t r;
492         isc_sha1_t sha1ctx;
493
494         isc_buffer_remainingregion(data, &r);
495         if (r.length == 0)
496                 return (ISC_R_SUCCESS);
497
498         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
499         if (hkey == NULL)
500                 return (ISC_R_NOMEMORY);
501
502         memset(hkey->key, 0, sizeof(hkey->key));
503
504         if (r.length > ISC_SHA1_BLOCK_LENGTH) {
505                 isc_sha1_init(&sha1ctx);
506                 isc_sha1_update(&sha1ctx, r.base, r.length);
507                 isc_sha1_final(&sha1ctx, hkey->key);
508                 keylen = ISC_SHA1_DIGESTLENGTH;
509         } else {
510                 memmove(hkey->key, r.base, r.length);
511                 keylen = r.length;
512         }
513
514         key->key_size = keylen * 8;
515         key->keydata.hmacsha1 = hkey;
516
517         isc_buffer_forward(data, r.length);
518
519         return (ISC_R_SUCCESS);
520 }
521
522 static isc_result_t
523 hmacsha1_tofile(const dst_key_t *key, const char *directory) {
524         int cnt = 0;
525         dst_hmacsha1_key_t *hkey;
526         dst_private_t priv;
527         int bytes = (key->key_size + 7) / 8;
528         unsigned char buf[2];
529
530         if (key->keydata.hmacsha1 == NULL)
531                 return (DST_R_NULLKEY);
532
533         hkey = key->keydata.hmacsha1;
534
535         priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
536         priv.elements[cnt].length = bytes;
537         priv.elements[cnt++].data = hkey->key;
538
539         buf[0] = (key->key_bits >> 8) & 0xffU;
540         buf[1] = key->key_bits & 0xffU;
541         priv.elements[cnt].tag = TAG_HMACSHA1_BITS;
542         priv.elements[cnt].data = buf;
543         priv.elements[cnt++].length = 2;
544
545         priv.nelements = cnt;
546         return (dst__privstruct_writefile(key, &priv, directory));
547 }
548
549 static isc_result_t
550 hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
551         dst_private_t priv;
552         isc_result_t result, tresult;
553         isc_buffer_t b;
554         isc_mem_t *mctx = key->mctx;
555         unsigned int i;
556
557         UNUSED(pub);
558         /* read private key file */
559         result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
560                                        &priv);
561         if (result != ISC_R_SUCCESS)
562                 return (result);
563
564         key->key_bits = 0;
565         for (i = 0; i < priv.nelements; i++) {
566                 switch (priv.elements[i].tag) {
567                 case TAG_HMACSHA1_KEY:
568                         isc_buffer_init(&b, priv.elements[i].data,
569                                         priv.elements[i].length);
570                         isc_buffer_add(&b, priv.elements[i].length);
571                         tresult = hmacsha1_fromdns(key, &b);
572                         if (tresult != ISC_R_SUCCESS)
573                                 result = tresult;
574                         break;
575                 case TAG_HMACSHA1_BITS:
576                         tresult = getkeybits(key, &priv.elements[i]);
577                         if (tresult != ISC_R_SUCCESS)
578                                 result = tresult;
579                         break;
580                 default:
581                         result = DST_R_INVALIDPRIVATEKEY;
582                         break;
583                 }
584         }
585         dst__privstruct_free(&priv, mctx);
586         memset(&priv, 0, sizeof(priv));
587         return (result);
588 }
589
590 static dst_func_t hmacsha1_functions = {
591         hmacsha1_createctx,
592         hmacsha1_destroyctx,
593         hmacsha1_adddata,
594         hmacsha1_sign,
595         hmacsha1_verify,
596         NULL, /* verify2 */
597         NULL, /* computesecret */
598         hmacsha1_compare,
599         NULL, /* paramcompare */
600         hmacsha1_generate,
601         hmacsha1_isprivate,
602         hmacsha1_destroy,
603         hmacsha1_todns,
604         hmacsha1_fromdns,
605         hmacsha1_tofile,
606         hmacsha1_parse,
607         NULL, /* cleanup */
608         NULL, /* fromlabel */
609         NULL, /* dump */
610         NULL, /* restore */
611 };
612
613 isc_result_t
614 dst__hmacsha1_init(dst_func_t **funcp) {
615         REQUIRE(funcp != NULL);
616         if (*funcp == NULL)
617                 *funcp = &hmacsha1_functions;
618         return (ISC_R_SUCCESS);
619 }
620
621 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
622
623 struct dst_hmacsha224_key {
624         unsigned char key[ISC_SHA224_BLOCK_LENGTH];
625 };
626
627 static isc_result_t
628 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
629         isc_hmacsha224_t *hmacsha224ctx;
630         dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
631
632         hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
633         if (hmacsha224ctx == NULL)
634                 return (ISC_R_NOMEMORY);
635         isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
636         dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
637         return (ISC_R_SUCCESS);
638 }
639
640 static void
641 hmacsha224_destroyctx(dst_context_t *dctx) {
642         isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
643
644         if (hmacsha224ctx != NULL) {
645                 isc_hmacsha224_invalidate(hmacsha224ctx);
646                 isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
647                 dctx->ctxdata.hmacsha224ctx = NULL;
648         }
649 }
650
651 static isc_result_t
652 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
653         isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
654
655         isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
656         return (ISC_R_SUCCESS);
657 }
658
659 static isc_result_t
660 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
661         isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
662         unsigned char *digest;
663
664         if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
665                 return (ISC_R_NOSPACE);
666         digest = isc_buffer_used(sig);
667         isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
668         isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
669
670         return (ISC_R_SUCCESS);
671 }
672
673 static isc_result_t
674 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
675         isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
676
677         if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
678                 return (DST_R_VERIFYFAILURE);
679
680         if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
681                 return (ISC_R_SUCCESS);
682         else
683                 return (DST_R_VERIFYFAILURE);
684 }
685
686 static isc_boolean_t
687 hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
688         dst_hmacsha224_key_t *hkey1, *hkey2;
689
690         hkey1 = key1->keydata.hmacsha224;
691         hkey2 = key2->keydata.hmacsha224;
692
693         if (hkey1 == NULL && hkey2 == NULL)
694                 return (ISC_TRUE);
695         else if (hkey1 == NULL || hkey2 == NULL)
696                 return (ISC_FALSE);
697
698         if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH))
699                 return (ISC_TRUE);
700         else
701                 return (ISC_FALSE);
702 }
703
704 static isc_result_t
705 hmacsha224_generate(dst_key_t *key, int pseudorandom_ok,
706                     void (*callback)(int))
707 {
708         isc_buffer_t b;
709         isc_result_t ret;
710         unsigned int bytes;
711         unsigned char data[ISC_SHA224_BLOCK_LENGTH];
712
713         UNUSED(callback);
714
715         bytes = (key->key_size + 7) / 8;
716         if (bytes > ISC_SHA224_BLOCK_LENGTH) {
717                 bytes = ISC_SHA224_BLOCK_LENGTH;
718                 key->key_size = ISC_SHA224_BLOCK_LENGTH * 8;
719         }
720
721         memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
722         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
723
724         if (ret != ISC_R_SUCCESS)
725                 return (ret);
726
727         isc_buffer_init(&b, data, bytes);
728         isc_buffer_add(&b, bytes);
729         ret = hmacsha224_fromdns(key, &b);
730         memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
731
732         return (ret);
733 }
734
735 static isc_boolean_t
736 hmacsha224_isprivate(const dst_key_t *key) {
737         UNUSED(key);
738         return (ISC_TRUE);
739 }
740
741 static void
742 hmacsha224_destroy(dst_key_t *key) {
743         dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
744
745         memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
746         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
747         key->keydata.hmacsha224 = NULL;
748 }
749
750 static isc_result_t
751 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
752         dst_hmacsha224_key_t *hkey;
753         unsigned int bytes;
754
755         REQUIRE(key->keydata.hmacsha224 != NULL);
756
757         hkey = key->keydata.hmacsha224;
758
759         bytes = (key->key_size + 7) / 8;
760         if (isc_buffer_availablelength(data) < bytes)
761                 return (ISC_R_NOSPACE);
762         isc_buffer_putmem(data, hkey->key, bytes);
763
764         return (ISC_R_SUCCESS);
765 }
766
767 static isc_result_t
768 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
769         dst_hmacsha224_key_t *hkey;
770         int keylen;
771         isc_region_t r;
772         isc_sha224_t sha224ctx;
773
774         isc_buffer_remainingregion(data, &r);
775         if (r.length == 0)
776                 return (ISC_R_SUCCESS);
777
778         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
779         if (hkey == NULL)
780                 return (ISC_R_NOMEMORY);
781
782         memset(hkey->key, 0, sizeof(hkey->key));
783
784         if (r.length > ISC_SHA224_BLOCK_LENGTH) {
785                 isc_sha224_init(&sha224ctx);
786                 isc_sha224_update(&sha224ctx, r.base, r.length);
787                 isc_sha224_final(hkey->key, &sha224ctx);
788                 keylen = ISC_SHA224_DIGESTLENGTH;
789         } else {
790                 memmove(hkey->key, r.base, r.length);
791                 keylen = r.length;
792         }
793
794         key->key_size = keylen * 8;
795         key->keydata.hmacsha224 = hkey;
796
797         isc_buffer_forward(data, r.length);
798
799         return (ISC_R_SUCCESS);
800 }
801
802 static isc_result_t
803 hmacsha224_tofile(const dst_key_t *key, const char *directory) {
804         int cnt = 0;
805         dst_hmacsha224_key_t *hkey;
806         dst_private_t priv;
807         int bytes = (key->key_size + 7) / 8;
808         unsigned char buf[2];
809
810         if (key->keydata.hmacsha224 == NULL)
811                 return (DST_R_NULLKEY);
812
813         hkey = key->keydata.hmacsha224;
814
815         priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
816         priv.elements[cnt].length = bytes;
817         priv.elements[cnt++].data = hkey->key;
818
819         buf[0] = (key->key_bits >> 8) & 0xffU;
820         buf[1] = key->key_bits & 0xffU;
821         priv.elements[cnt].tag = TAG_HMACSHA224_BITS;
822         priv.elements[cnt].data = buf;
823         priv.elements[cnt++].length = 2;
824
825         priv.nelements = cnt;
826         return (dst__privstruct_writefile(key, &priv, directory));
827 }
828
829 static isc_result_t
830 hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
831         dst_private_t priv;
832         isc_result_t result, tresult;
833         isc_buffer_t b;
834         isc_mem_t *mctx = key->mctx;
835         unsigned int i;
836
837         UNUSED(pub);
838         /* read private key file */
839         result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
840                                        &priv);
841         if (result != ISC_R_SUCCESS)
842                 return (result);
843
844         key->key_bits = 0;
845         for (i = 0; i < priv.nelements; i++) {
846                 switch (priv.elements[i].tag) {
847                 case TAG_HMACSHA224_KEY:
848                         isc_buffer_init(&b, priv.elements[i].data,
849                                         priv.elements[i].length);
850                         isc_buffer_add(&b, priv.elements[i].length);
851                         tresult = hmacsha224_fromdns(key, &b);
852                         if (tresult != ISC_R_SUCCESS)
853                                 result = tresult;
854                         break;
855                 case TAG_HMACSHA224_BITS:
856                         tresult = getkeybits(key, &priv.elements[i]);
857                         if (tresult != ISC_R_SUCCESS)
858                                 result = tresult;
859                         break;
860                 default:
861                         result = DST_R_INVALIDPRIVATEKEY;
862                         break;
863                 }
864         }
865         dst__privstruct_free(&priv, mctx);
866         memset(&priv, 0, sizeof(priv));
867         return (result);
868 }
869
870 static dst_func_t hmacsha224_functions = {
871         hmacsha224_createctx,
872         hmacsha224_destroyctx,
873         hmacsha224_adddata,
874         hmacsha224_sign,
875         hmacsha224_verify,
876         NULL, /* verify2 */
877         NULL, /* computesecret */
878         hmacsha224_compare,
879         NULL, /* paramcompare */
880         hmacsha224_generate,
881         hmacsha224_isprivate,
882         hmacsha224_destroy,
883         hmacsha224_todns,
884         hmacsha224_fromdns,
885         hmacsha224_tofile,
886         hmacsha224_parse,
887         NULL, /* cleanup */
888         NULL, /* fromlabel */
889         NULL, /* dump */
890         NULL, /* restore */
891 };
892
893 isc_result_t
894 dst__hmacsha224_init(dst_func_t **funcp) {
895         REQUIRE(funcp != NULL);
896         if (*funcp == NULL)
897                 *funcp = &hmacsha224_functions;
898         return (ISC_R_SUCCESS);
899 }
900
901 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
902
903 struct dst_hmacsha256_key {
904         unsigned char key[ISC_SHA256_BLOCK_LENGTH];
905 };
906
907 static isc_result_t
908 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
909         isc_hmacsha256_t *hmacsha256ctx;
910         dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
911
912         hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
913         if (hmacsha256ctx == NULL)
914                 return (ISC_R_NOMEMORY);
915         isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
916         dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
917         return (ISC_R_SUCCESS);
918 }
919
920 static void
921 hmacsha256_destroyctx(dst_context_t *dctx) {
922         isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
923
924         if (hmacsha256ctx != NULL) {
925                 isc_hmacsha256_invalidate(hmacsha256ctx);
926                 isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
927                 dctx->ctxdata.hmacsha256ctx = NULL;
928         }
929 }
930
931 static isc_result_t
932 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
933         isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
934
935         isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
936         return (ISC_R_SUCCESS);
937 }
938
939 static isc_result_t
940 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
941         isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
942         unsigned char *digest;
943
944         if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
945                 return (ISC_R_NOSPACE);
946         digest = isc_buffer_used(sig);
947         isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
948         isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
949
950         return (ISC_R_SUCCESS);
951 }
952
953 static isc_result_t
954 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
955         isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
956
957         if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
958                 return (DST_R_VERIFYFAILURE);
959
960         if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
961                 return (ISC_R_SUCCESS);
962         else
963                 return (DST_R_VERIFYFAILURE);
964 }
965
966 static isc_boolean_t
967 hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
968         dst_hmacsha256_key_t *hkey1, *hkey2;
969
970         hkey1 = key1->keydata.hmacsha256;
971         hkey2 = key2->keydata.hmacsha256;
972
973         if (hkey1 == NULL && hkey2 == NULL)
974                 return (ISC_TRUE);
975         else if (hkey1 == NULL || hkey2 == NULL)
976                 return (ISC_FALSE);
977
978         if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH))
979                 return (ISC_TRUE);
980         else
981                 return (ISC_FALSE);
982 }
983
984 static isc_result_t
985 hmacsha256_generate(dst_key_t *key, int pseudorandom_ok,
986                     void (*callback)(int))
987 {
988         isc_buffer_t b;
989         isc_result_t ret;
990         unsigned int bytes;
991         unsigned char data[ISC_SHA256_BLOCK_LENGTH];
992
993         UNUSED(callback);
994
995         bytes = (key->key_size + 7) / 8;
996         if (bytes > ISC_SHA256_BLOCK_LENGTH) {
997                 bytes = ISC_SHA256_BLOCK_LENGTH;
998                 key->key_size = ISC_SHA256_BLOCK_LENGTH * 8;
999         }
1000
1001         memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1002         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1003
1004         if (ret != ISC_R_SUCCESS)
1005                 return (ret);
1006
1007         isc_buffer_init(&b, data, bytes);
1008         isc_buffer_add(&b, bytes);
1009         ret = hmacsha256_fromdns(key, &b);
1010         memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1011
1012         return (ret);
1013 }
1014
1015 static isc_boolean_t
1016 hmacsha256_isprivate(const dst_key_t *key) {
1017         UNUSED(key);
1018         return (ISC_TRUE);
1019 }
1020
1021 static void
1022 hmacsha256_destroy(dst_key_t *key) {
1023         dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
1024
1025         memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
1026         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
1027         key->keydata.hmacsha256 = NULL;
1028 }
1029
1030 static isc_result_t
1031 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
1032         dst_hmacsha256_key_t *hkey;
1033         unsigned int bytes;
1034
1035         REQUIRE(key->keydata.hmacsha256 != NULL);
1036
1037         hkey = key->keydata.hmacsha256;
1038
1039         bytes = (key->key_size + 7) / 8;
1040         if (isc_buffer_availablelength(data) < bytes)
1041                 return (ISC_R_NOSPACE);
1042         isc_buffer_putmem(data, hkey->key, bytes);
1043
1044         return (ISC_R_SUCCESS);
1045 }
1046
1047 static isc_result_t
1048 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
1049         dst_hmacsha256_key_t *hkey;
1050         int keylen;
1051         isc_region_t r;
1052         isc_sha256_t sha256ctx;
1053
1054         isc_buffer_remainingregion(data, &r);
1055         if (r.length == 0)
1056                 return (ISC_R_SUCCESS);
1057
1058         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
1059         if (hkey == NULL)
1060                 return (ISC_R_NOMEMORY);
1061
1062         memset(hkey->key, 0, sizeof(hkey->key));
1063
1064         if (r.length > ISC_SHA256_BLOCK_LENGTH) {
1065                 isc_sha256_init(&sha256ctx);
1066                 isc_sha256_update(&sha256ctx, r.base, r.length);
1067                 isc_sha256_final(hkey->key, &sha256ctx);
1068                 keylen = ISC_SHA256_DIGESTLENGTH;
1069         } else {
1070                 memmove(hkey->key, r.base, r.length);
1071                 keylen = r.length;
1072         }
1073
1074         key->key_size = keylen * 8;
1075         key->keydata.hmacsha256 = hkey;
1076
1077         isc_buffer_forward(data, r.length);
1078
1079         return (ISC_R_SUCCESS);
1080 }
1081
1082 static isc_result_t
1083 hmacsha256_tofile(const dst_key_t *key, const char *directory) {
1084         int cnt = 0;
1085         dst_hmacsha256_key_t *hkey;
1086         dst_private_t priv;
1087         int bytes = (key->key_size + 7) / 8;
1088         unsigned char buf[2];
1089
1090         if (key->keydata.hmacsha256 == NULL)
1091                 return (DST_R_NULLKEY);
1092
1093         hkey = key->keydata.hmacsha256;
1094
1095         priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
1096         priv.elements[cnt].length = bytes;
1097         priv.elements[cnt++].data = hkey->key;
1098
1099         buf[0] = (key->key_bits >> 8) & 0xffU;
1100         buf[1] = key->key_bits & 0xffU;
1101         priv.elements[cnt].tag = TAG_HMACSHA256_BITS;
1102         priv.elements[cnt].data = buf;
1103         priv.elements[cnt++].length = 2;
1104
1105         priv.nelements = cnt;
1106         return (dst__privstruct_writefile(key, &priv, directory));
1107 }
1108
1109 static isc_result_t
1110 hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1111         dst_private_t priv;
1112         isc_result_t result, tresult;
1113         isc_buffer_t b;
1114         isc_mem_t *mctx = key->mctx;
1115         unsigned int i;
1116
1117         UNUSED(pub);
1118         /* read private key file */
1119         result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
1120                                        &priv);
1121         if (result != ISC_R_SUCCESS)
1122                 return (result);
1123
1124         key->key_bits = 0;
1125         for (i = 0; i < priv.nelements; i++) {
1126                 switch (priv.elements[i].tag) {
1127                 case TAG_HMACSHA256_KEY:
1128                         isc_buffer_init(&b, priv.elements[i].data,
1129                                         priv.elements[i].length);
1130                         isc_buffer_add(&b, priv.elements[i].length);
1131                         tresult = hmacsha256_fromdns(key, &b);
1132                         if (tresult != ISC_R_SUCCESS)
1133                                 result = tresult;
1134                         break;
1135                 case TAG_HMACSHA256_BITS:
1136                         tresult = getkeybits(key, &priv.elements[i]);
1137                         if (tresult != ISC_R_SUCCESS)
1138                                 result = tresult;
1139                         break;
1140                 default:
1141                         result = DST_R_INVALIDPRIVATEKEY;
1142                         break;
1143                 }
1144         }
1145         dst__privstruct_free(&priv, mctx);
1146         memset(&priv, 0, sizeof(priv));
1147         return (result);
1148 }
1149
1150 static dst_func_t hmacsha256_functions = {
1151         hmacsha256_createctx,
1152         hmacsha256_destroyctx,
1153         hmacsha256_adddata,
1154         hmacsha256_sign,
1155         hmacsha256_verify,
1156         NULL, /* verify2 */
1157         NULL, /* computesecret */
1158         hmacsha256_compare,
1159         NULL, /* paramcompare */
1160         hmacsha256_generate,
1161         hmacsha256_isprivate,
1162         hmacsha256_destroy,
1163         hmacsha256_todns,
1164         hmacsha256_fromdns,
1165         hmacsha256_tofile,
1166         hmacsha256_parse,
1167         NULL, /* cleanup */
1168         NULL, /* fromlabel */
1169         NULL, /* dump */
1170         NULL, /* restore */
1171 };
1172
1173 isc_result_t
1174 dst__hmacsha256_init(dst_func_t **funcp) {
1175         REQUIRE(funcp != NULL);
1176         if (*funcp == NULL)
1177                 *funcp = &hmacsha256_functions;
1178         return (ISC_R_SUCCESS);
1179 }
1180
1181 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
1182
1183 struct dst_hmacsha384_key {
1184         unsigned char key[ISC_SHA384_BLOCK_LENGTH];
1185 };
1186
1187 static isc_result_t
1188 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
1189         isc_hmacsha384_t *hmacsha384ctx;
1190         dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1191
1192         hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
1193         if (hmacsha384ctx == NULL)
1194                 return (ISC_R_NOMEMORY);
1195         isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
1196         dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
1197         return (ISC_R_SUCCESS);
1198 }
1199
1200 static void
1201 hmacsha384_destroyctx(dst_context_t *dctx) {
1202         isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1203
1204         if (hmacsha384ctx != NULL) {
1205                 isc_hmacsha384_invalidate(hmacsha384ctx);
1206                 isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
1207                 dctx->ctxdata.hmacsha384ctx = NULL;
1208         }
1209 }
1210
1211 static isc_result_t
1212 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
1213         isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1214
1215         isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
1216         return (ISC_R_SUCCESS);
1217 }
1218
1219 static isc_result_t
1220 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1221         isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1222         unsigned char *digest;
1223
1224         if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
1225                 return (ISC_R_NOSPACE);
1226         digest = isc_buffer_used(sig);
1227         isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
1228         isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
1229
1230         return (ISC_R_SUCCESS);
1231 }
1232
1233 static isc_result_t
1234 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
1235         isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1236
1237         if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
1238                 return (DST_R_VERIFYFAILURE);
1239
1240         if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
1241                 return (ISC_R_SUCCESS);
1242         else
1243                 return (DST_R_VERIFYFAILURE);
1244 }
1245
1246 static isc_boolean_t
1247 hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
1248         dst_hmacsha384_key_t *hkey1, *hkey2;
1249
1250         hkey1 = key1->keydata.hmacsha384;
1251         hkey2 = key2->keydata.hmacsha384;
1252
1253         if (hkey1 == NULL && hkey2 == NULL)
1254                 return (ISC_TRUE);
1255         else if (hkey1 == NULL || hkey2 == NULL)
1256                 return (ISC_FALSE);
1257
1258         if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH))
1259                 return (ISC_TRUE);
1260         else
1261                 return (ISC_FALSE);
1262 }
1263
1264 static isc_result_t
1265 hmacsha384_generate(dst_key_t *key, int pseudorandom_ok,
1266                     void (*callback)(int))
1267 {
1268         isc_buffer_t b;
1269         isc_result_t ret;
1270         unsigned int bytes;
1271         unsigned char data[ISC_SHA384_BLOCK_LENGTH];
1272
1273         UNUSED(callback);
1274
1275         bytes = (key->key_size + 7) / 8;
1276         if (bytes > ISC_SHA384_BLOCK_LENGTH) {
1277                 bytes = ISC_SHA384_BLOCK_LENGTH;
1278                 key->key_size = ISC_SHA384_BLOCK_LENGTH * 8;
1279         }
1280
1281         memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1282         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1283
1284         if (ret != ISC_R_SUCCESS)
1285                 return (ret);
1286
1287         isc_buffer_init(&b, data, bytes);
1288         isc_buffer_add(&b, bytes);
1289         ret = hmacsha384_fromdns(key, &b);
1290         memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1291
1292         return (ret);
1293 }
1294
1295 static isc_boolean_t
1296 hmacsha384_isprivate(const dst_key_t *key) {
1297         UNUSED(key);
1298         return (ISC_TRUE);
1299 }
1300
1301 static void
1302 hmacsha384_destroy(dst_key_t *key) {
1303         dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1304
1305         memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
1306         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
1307         key->keydata.hmacsha384 = NULL;
1308 }
1309
1310 static isc_result_t
1311 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
1312         dst_hmacsha384_key_t *hkey;
1313         unsigned int bytes;
1314
1315         REQUIRE(key->keydata.hmacsha384 != NULL);
1316
1317         hkey = key->keydata.hmacsha384;
1318
1319         bytes = (key->key_size + 7) / 8;
1320         if (isc_buffer_availablelength(data) < bytes)
1321                 return (ISC_R_NOSPACE);
1322         isc_buffer_putmem(data, hkey->key, bytes);
1323
1324         return (ISC_R_SUCCESS);
1325 }
1326
1327 static isc_result_t
1328 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
1329         dst_hmacsha384_key_t *hkey;
1330         int keylen;
1331         isc_region_t r;
1332         isc_sha384_t sha384ctx;
1333
1334         isc_buffer_remainingregion(data, &r);
1335         if (r.length == 0)
1336                 return (ISC_R_SUCCESS);
1337
1338         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
1339         if (hkey == NULL)
1340                 return (ISC_R_NOMEMORY);
1341
1342         memset(hkey->key, 0, sizeof(hkey->key));
1343
1344         if (r.length > ISC_SHA384_BLOCK_LENGTH) {
1345                 isc_sha384_init(&sha384ctx);
1346                 isc_sha384_update(&sha384ctx, r.base, r.length);
1347                 isc_sha384_final(hkey->key, &sha384ctx);
1348                 keylen = ISC_SHA384_DIGESTLENGTH;
1349         } else {
1350                 memmove(hkey->key, r.base, r.length);
1351                 keylen = r.length;
1352         }
1353
1354         key->key_size = keylen * 8;
1355         key->keydata.hmacsha384 = hkey;
1356
1357         isc_buffer_forward(data, r.length);
1358
1359         return (ISC_R_SUCCESS);
1360 }
1361
1362 static isc_result_t
1363 hmacsha384_tofile(const dst_key_t *key, const char *directory) {
1364         int cnt = 0;
1365         dst_hmacsha384_key_t *hkey;
1366         dst_private_t priv;
1367         int bytes = (key->key_size + 7) / 8;
1368         unsigned char buf[2];
1369
1370         if (key->keydata.hmacsha384 == NULL)
1371                 return (DST_R_NULLKEY);
1372
1373         hkey = key->keydata.hmacsha384;
1374
1375         priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
1376         priv.elements[cnt].length = bytes;
1377         priv.elements[cnt++].data = hkey->key;
1378
1379         buf[0] = (key->key_bits >> 8) & 0xffU;
1380         buf[1] = key->key_bits & 0xffU;
1381         priv.elements[cnt].tag = TAG_HMACSHA384_BITS;
1382         priv.elements[cnt].data = buf;
1383         priv.elements[cnt++].length = 2;
1384
1385         priv.nelements = cnt;
1386         return (dst__privstruct_writefile(key, &priv, directory));
1387 }
1388
1389 static isc_result_t
1390 hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1391         dst_private_t priv;
1392         isc_result_t result, tresult;
1393         isc_buffer_t b;
1394         isc_mem_t *mctx = key->mctx;
1395         unsigned int i;
1396
1397         UNUSED(pub);
1398         /* read private key file */
1399         result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
1400                                        &priv);
1401         if (result != ISC_R_SUCCESS)
1402                 return (result);
1403
1404         key->key_bits = 0;
1405         for (i = 0; i < priv.nelements; i++) {
1406                 switch (priv.elements[i].tag) {
1407                 case TAG_HMACSHA384_KEY:
1408                         isc_buffer_init(&b, priv.elements[i].data,
1409                                         priv.elements[i].length);
1410                         isc_buffer_add(&b, priv.elements[i].length);
1411                         tresult = hmacsha384_fromdns(key, &b);
1412                         if (tresult != ISC_R_SUCCESS)
1413                                 result = tresult;
1414                         break;
1415                 case TAG_HMACSHA384_BITS:
1416                         tresult = getkeybits(key, &priv.elements[i]);
1417                         if (tresult != ISC_R_SUCCESS)
1418                                 result = tresult;
1419                         break;
1420                 default:
1421                         result = DST_R_INVALIDPRIVATEKEY;
1422                         break;
1423                 }
1424         }
1425         dst__privstruct_free(&priv, mctx);
1426         memset(&priv, 0, sizeof(priv));
1427         return (result);
1428 }
1429
1430 static dst_func_t hmacsha384_functions = {
1431         hmacsha384_createctx,
1432         hmacsha384_destroyctx,
1433         hmacsha384_adddata,
1434         hmacsha384_sign,
1435         hmacsha384_verify,
1436         NULL, /* verify2 */
1437         NULL, /* computesecret */
1438         hmacsha384_compare,
1439         NULL, /* paramcompare */
1440         hmacsha384_generate,
1441         hmacsha384_isprivate,
1442         hmacsha384_destroy,
1443         hmacsha384_todns,
1444         hmacsha384_fromdns,
1445         hmacsha384_tofile,
1446         hmacsha384_parse,
1447         NULL, /* cleanup */
1448         NULL, /* fromlabel */
1449         NULL, /* dump */
1450         NULL, /* restore */
1451 };
1452
1453 isc_result_t
1454 dst__hmacsha384_init(dst_func_t **funcp) {
1455         REQUIRE(funcp != NULL);
1456         if (*funcp == NULL)
1457                 *funcp = &hmacsha384_functions;
1458         return (ISC_R_SUCCESS);
1459 }
1460
1461 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
1462
1463 struct dst_hmacsha512_key {
1464         unsigned char key[ISC_SHA512_BLOCK_LENGTH];
1465 };
1466
1467 static isc_result_t
1468 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
1469         isc_hmacsha512_t *hmacsha512ctx;
1470         dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1471
1472         hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
1473         if (hmacsha512ctx == NULL)
1474                 return (ISC_R_NOMEMORY);
1475         isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
1476         dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
1477         return (ISC_R_SUCCESS);
1478 }
1479
1480 static void
1481 hmacsha512_destroyctx(dst_context_t *dctx) {
1482         isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1483
1484         if (hmacsha512ctx != NULL) {
1485                 isc_hmacsha512_invalidate(hmacsha512ctx);
1486                 isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
1487                 dctx->ctxdata.hmacsha512ctx = NULL;
1488         }
1489 }
1490
1491 static isc_result_t
1492 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
1493         isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1494
1495         isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
1496         return (ISC_R_SUCCESS);
1497 }
1498
1499 static isc_result_t
1500 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1501         isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1502         unsigned char *digest;
1503
1504         if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
1505                 return (ISC_R_NOSPACE);
1506         digest = isc_buffer_used(sig);
1507         isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
1508         isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
1509
1510         return (ISC_R_SUCCESS);
1511 }
1512
1513 static isc_result_t
1514 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
1515         isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1516
1517         if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
1518                 return (DST_R_VERIFYFAILURE);
1519
1520         if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
1521                 return (ISC_R_SUCCESS);
1522         else
1523                 return (DST_R_VERIFYFAILURE);
1524 }
1525
1526 static isc_boolean_t
1527 hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
1528         dst_hmacsha512_key_t *hkey1, *hkey2;
1529
1530         hkey1 = key1->keydata.hmacsha512;
1531         hkey2 = key2->keydata.hmacsha512;
1532
1533         if (hkey1 == NULL && hkey2 == NULL)
1534                 return (ISC_TRUE);
1535         else if (hkey1 == NULL || hkey2 == NULL)
1536                 return (ISC_FALSE);
1537
1538         if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH))
1539                 return (ISC_TRUE);
1540         else
1541                 return (ISC_FALSE);
1542 }
1543
1544 static isc_result_t
1545 hmacsha512_generate(dst_key_t *key, int pseudorandom_ok,
1546                     void (*callback)(int))
1547 {
1548         isc_buffer_t b;
1549         isc_result_t ret;
1550         unsigned int bytes;
1551         unsigned char data[ISC_SHA512_BLOCK_LENGTH];
1552
1553         UNUSED(callback);
1554
1555         bytes = (key->key_size + 7) / 8;
1556         if (bytes > ISC_SHA512_BLOCK_LENGTH) {
1557                 bytes = ISC_SHA512_BLOCK_LENGTH;
1558                 key->key_size = ISC_SHA512_BLOCK_LENGTH * 8;
1559         }
1560
1561         memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1562         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1563
1564         if (ret != ISC_R_SUCCESS)
1565                 return (ret);
1566
1567         isc_buffer_init(&b, data, bytes);
1568         isc_buffer_add(&b, bytes);
1569         ret = hmacsha512_fromdns(key, &b);
1570         memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1571
1572         return (ret);
1573 }
1574
1575 static isc_boolean_t
1576 hmacsha512_isprivate(const dst_key_t *key) {
1577         UNUSED(key);
1578         return (ISC_TRUE);
1579 }
1580
1581 static void
1582 hmacsha512_destroy(dst_key_t *key) {
1583         dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1584
1585         memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
1586         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
1587         key->keydata.hmacsha512 = NULL;
1588 }
1589
1590 static isc_result_t
1591 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
1592         dst_hmacsha512_key_t *hkey;
1593         unsigned int bytes;
1594
1595         REQUIRE(key->keydata.hmacsha512 != NULL);
1596
1597         hkey = key->keydata.hmacsha512;
1598
1599         bytes = (key->key_size + 7) / 8;
1600         if (isc_buffer_availablelength(data) < bytes)
1601                 return (ISC_R_NOSPACE);
1602         isc_buffer_putmem(data, hkey->key, bytes);
1603
1604         return (ISC_R_SUCCESS);
1605 }
1606
1607 static isc_result_t
1608 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
1609         dst_hmacsha512_key_t *hkey;
1610         int keylen;
1611         isc_region_t r;
1612         isc_sha512_t sha512ctx;
1613
1614         isc_buffer_remainingregion(data, &r);
1615         if (r.length == 0)
1616                 return (ISC_R_SUCCESS);
1617
1618         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
1619         if (hkey == NULL)
1620                 return (ISC_R_NOMEMORY);
1621
1622         memset(hkey->key, 0, sizeof(hkey->key));
1623
1624         if (r.length > ISC_SHA512_BLOCK_LENGTH) {
1625                 isc_sha512_init(&sha512ctx);
1626                 isc_sha512_update(&sha512ctx, r.base, r.length);
1627                 isc_sha512_final(hkey->key, &sha512ctx);
1628                 keylen = ISC_SHA512_DIGESTLENGTH;
1629         } else {
1630                 memmove(hkey->key, r.base, r.length);
1631                 keylen = r.length;
1632         }
1633
1634         key->key_size = keylen * 8;
1635         key->keydata.hmacsha512 = hkey;
1636
1637         isc_buffer_forward(data, r.length);
1638
1639         return (ISC_R_SUCCESS);
1640 }
1641
1642 static isc_result_t
1643 hmacsha512_tofile(const dst_key_t *key, const char *directory) {
1644         int cnt = 0;
1645         dst_hmacsha512_key_t *hkey;
1646         dst_private_t priv;
1647         int bytes = (key->key_size + 7) / 8;
1648         unsigned char buf[2];
1649
1650         if (key->keydata.hmacsha512 == NULL)
1651                 return (DST_R_NULLKEY);
1652
1653         hkey = key->keydata.hmacsha512;
1654
1655         priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
1656         priv.elements[cnt].length = bytes;
1657         priv.elements[cnt++].data = hkey->key;
1658
1659         buf[0] = (key->key_bits >> 8) & 0xffU;
1660         buf[1] = key->key_bits & 0xffU;
1661         priv.elements[cnt].tag = TAG_HMACSHA512_BITS;
1662         priv.elements[cnt].data = buf;
1663         priv.elements[cnt++].length = 2;
1664
1665         priv.nelements = cnt;
1666         return (dst__privstruct_writefile(key, &priv, directory));
1667 }
1668
1669 static isc_result_t
1670 hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1671         dst_private_t priv;
1672         isc_result_t result, tresult;
1673         isc_buffer_t b;
1674         isc_mem_t *mctx = key->mctx;
1675         unsigned int i;
1676
1677         UNUSED(pub);
1678         /* read private key file */
1679         result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
1680                                        &priv);
1681         if (result != ISC_R_SUCCESS)
1682                 return (result);
1683
1684         key->key_bits = 0;
1685         for (i = 0; i < priv.nelements; i++) {
1686                 switch (priv.elements[i].tag) {
1687                 case TAG_HMACSHA512_KEY:
1688                         isc_buffer_init(&b, priv.elements[i].data,
1689                                         priv.elements[i].length);
1690                         isc_buffer_add(&b, priv.elements[i].length);
1691                         tresult = hmacsha512_fromdns(key, &b);
1692                         if (tresult != ISC_R_SUCCESS)
1693                                 result = tresult;
1694                         break;
1695                 case TAG_HMACSHA512_BITS:
1696                         tresult = getkeybits(key, &priv.elements[i]);
1697                         if (tresult != ISC_R_SUCCESS)
1698                                 result = tresult;
1699                         break;
1700                 default:
1701                         result = DST_R_INVALIDPRIVATEKEY;
1702                         break;
1703                 }
1704         }
1705         dst__privstruct_free(&priv, mctx);
1706         memset(&priv, 0, sizeof(priv));
1707         return (result);
1708 }
1709
1710 static dst_func_t hmacsha512_functions = {
1711         hmacsha512_createctx,
1712         hmacsha512_destroyctx,
1713         hmacsha512_adddata,
1714         hmacsha512_sign,
1715         hmacsha512_verify,
1716         NULL, /* verify2 */
1717         NULL, /* computesecret */
1718         hmacsha512_compare,
1719         NULL, /* paramcompare */
1720         hmacsha512_generate,
1721         hmacsha512_isprivate,
1722         hmacsha512_destroy,
1723         hmacsha512_todns,
1724         hmacsha512_fromdns,
1725         hmacsha512_tofile,
1726         hmacsha512_parse,
1727         NULL, /* cleanup */
1728         NULL, /* fromlabel */
1729         NULL, /* dump */
1730         NULL, /* restore */
1731 };
1732
1733 isc_result_t
1734 dst__hmacsha512_init(dst_func_t **funcp) {
1735         REQUIRE(funcp != NULL);
1736         if (*funcp == NULL)
1737                 *funcp = &hmacsha512_functions;
1738         return (ISC_R_SUCCESS);
1739 }
1740
1741 /*! \file */