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