]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/dns/hmac_link.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / dns / hmac_link.c
1 /*
2  * Portions Copyright (C) 2004-2011  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/string.h>
46 #include <isc/util.h>
47
48 #include <dst/result.h>
49
50 #include "dst_internal.h"
51 #include "dst_parse.h"
52
53 static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
54
55 struct dst_hmacmd5_key {
56         unsigned char key[ISC_MD5_BLOCK_LENGTH];
57 };
58
59 static isc_result_t
60 getkeybits(dst_key_t *key, struct dst_private_element *element) {
61
62         if (element->length != 2)
63                 return (DST_R_INVALIDPRIVATEKEY);
64
65         key->key_bits = (element->data[0] << 8) + element->data[1];
66
67         return (ISC_R_SUCCESS);
68 }
69
70 static isc_result_t
71 hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
72         isc_hmacmd5_t *hmacmd5ctx;
73         dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
74
75         hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
76         if (hmacmd5ctx == NULL)
77                 return (ISC_R_NOMEMORY);
78         isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
79         dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
80         return (ISC_R_SUCCESS);
81 }
82
83 static void
84 hmacmd5_destroyctx(dst_context_t *dctx) {
85         isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
86
87         if (hmacmd5ctx != NULL) {
88                 isc_hmacmd5_invalidate(hmacmd5ctx);
89                 isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
90                 dctx->ctxdata.hmacmd5ctx = NULL;
91         }
92 }
93
94 static isc_result_t
95 hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
96         isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
97
98         isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
99         return (ISC_R_SUCCESS);
100 }
101
102 static isc_result_t
103 hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
104         isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
105         unsigned char *digest;
106
107         if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
108                 return (ISC_R_NOSPACE);
109         digest = isc_buffer_used(sig);
110         isc_hmacmd5_sign(hmacmd5ctx, digest);
111         isc_buffer_add(sig, ISC_MD5_DIGESTLENGTH);
112
113         return (ISC_R_SUCCESS);
114 }
115
116 static isc_result_t
117 hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
118         isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
119
120         if (sig->length > ISC_MD5_DIGESTLENGTH)
121                 return (DST_R_VERIFYFAILURE);
122
123         if (isc_hmacmd5_verify2(hmacmd5ctx, sig->base, sig->length))
124                 return (ISC_R_SUCCESS);
125         else
126                 return (DST_R_VERIFYFAILURE);
127 }
128
129 static isc_boolean_t
130 hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
131         dst_hmacmd5_key_t *hkey1, *hkey2;
132
133         hkey1 = key1->keydata.hmacmd5;
134         hkey2 = key2->keydata.hmacmd5;
135
136         if (hkey1 == NULL && hkey2 == NULL)
137                 return (ISC_TRUE);
138         else if (hkey1 == NULL || hkey2 == NULL)
139                 return (ISC_FALSE);
140
141         if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH) == 0)
142                 return (ISC_TRUE);
143         else
144                 return (ISC_FALSE);
145 }
146
147 static isc_result_t
148 hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
149         isc_buffer_t b;
150         isc_result_t ret;
151         unsigned int bytes;
152         unsigned char data[ISC_SHA1_BLOCK_LENGTH];
153
154         UNUSED(callback);
155
156         bytes = (key->key_size + 7) / 8;
157         if (bytes > ISC_SHA1_BLOCK_LENGTH) {
158                 bytes = ISC_SHA1_BLOCK_LENGTH;
159                 key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
160         }
161
162         memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
163         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
164
165         if (ret != ISC_R_SUCCESS)
166                 return (ret);
167
168         isc_buffer_init(&b, data, bytes);
169         isc_buffer_add(&b, bytes);
170         ret = hmacmd5_fromdns(key, &b);
171         memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
172
173         return (ret);
174 }
175
176 static isc_boolean_t
177 hmacmd5_isprivate(const dst_key_t *key) {
178         UNUSED(key);
179         return (ISC_TRUE);
180 }
181
182 static void
183 hmacmd5_destroy(dst_key_t *key) {
184         dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
185
186         memset(hkey, 0, sizeof(dst_hmacmd5_key_t));
187         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacmd5_key_t));
188         key->keydata.hmacmd5 = NULL;
189 }
190
191 static isc_result_t
192 hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
193         dst_hmacmd5_key_t *hkey;
194         unsigned int bytes;
195
196         REQUIRE(key->keydata.hmacmd5 != NULL);
197
198         hkey = key->keydata.hmacmd5;
199
200         bytes = (key->key_size + 7) / 8;
201         if (isc_buffer_availablelength(data) < bytes)
202                 return (ISC_R_NOSPACE);
203         isc_buffer_putmem(data, hkey->key, bytes);
204
205         return (ISC_R_SUCCESS);
206 }
207
208 static isc_result_t
209 hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
210         dst_hmacmd5_key_t *hkey;
211         int keylen;
212         isc_region_t r;
213         isc_md5_t md5ctx;
214
215         isc_buffer_remainingregion(data, &r);
216         if (r.length == 0)
217                 return (ISC_R_SUCCESS);
218
219         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
220         if (hkey == NULL)
221                 return (ISC_R_NOMEMORY);
222
223         memset(hkey->key, 0, sizeof(hkey->key));
224
225         if (r.length > ISC_SHA1_BLOCK_LENGTH) {
226                 isc_md5_init(&md5ctx);
227                 isc_md5_update(&md5ctx, r.base, r.length);
228                 isc_md5_final(&md5ctx, hkey->key);
229                 keylen = ISC_MD5_DIGESTLENGTH;
230         }
231         else {
232                 memcpy(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, /*%< computesecret */
317         hmacmd5_compare,
318         NULL, /*%< paramcompare */
319         hmacmd5_generate,
320         hmacmd5_isprivate,
321         hmacmd5_destroy,
322         hmacmd5_todns,
323         hmacmd5_fromdns,
324         hmacmd5_tofile,
325         hmacmd5_parse,
326         NULL, /*%< cleanup */
327         NULL, /*%< fromlabel */
328         NULL, /*%< dump */
329         NULL, /*%< restore */
330 };
331
332 isc_result_t
333 dst__hmacmd5_init(dst_func_t **funcp) {
334         REQUIRE(funcp != NULL);
335         if (*funcp == NULL)
336                 *funcp = &hmacmd5_functions;
337         return (ISC_R_SUCCESS);
338 }
339
340 static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
341
342 struct dst_hmacsha1_key {
343         unsigned char key[ISC_SHA1_BLOCK_LENGTH];
344 };
345
346 static isc_result_t
347 hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
348         isc_hmacsha1_t *hmacsha1ctx;
349         dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
350
351         hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
352         if (hmacsha1ctx == NULL)
353                 return (ISC_R_NOMEMORY);
354         isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
355         dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
356         return (ISC_R_SUCCESS);
357 }
358
359 static void
360 hmacsha1_destroyctx(dst_context_t *dctx) {
361         isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
362
363         if (hmacsha1ctx != NULL) {
364                 isc_hmacsha1_invalidate(hmacsha1ctx);
365                 isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
366                 dctx->ctxdata.hmacsha1ctx = NULL;
367         }
368 }
369
370 static isc_result_t
371 hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
372         isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
373
374         isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
375         return (ISC_R_SUCCESS);
376 }
377
378 static isc_result_t
379 hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
380         isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
381         unsigned char *digest;
382
383         if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
384                 return (ISC_R_NOSPACE);
385         digest = isc_buffer_used(sig);
386         isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
387         isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
388
389         return (ISC_R_SUCCESS);
390 }
391
392 static isc_result_t
393 hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
394         isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
395
396         if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
397                 return (DST_R_VERIFYFAILURE);
398
399         if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
400                 return (ISC_R_SUCCESS);
401         else
402                 return (DST_R_VERIFYFAILURE);
403 }
404
405 static isc_boolean_t
406 hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
407         dst_hmacsha1_key_t *hkey1, *hkey2;
408
409         hkey1 = key1->keydata.hmacsha1;
410         hkey2 = key2->keydata.hmacsha1;
411
412         if (hkey1 == NULL && hkey2 == NULL)
413                 return (ISC_TRUE);
414         else if (hkey1 == NULL || hkey2 == NULL)
415                 return (ISC_FALSE);
416
417         if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH) == 0)
418                 return (ISC_TRUE);
419         else
420                 return (ISC_FALSE);
421 }
422
423 static isc_result_t
424 hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
425         isc_buffer_t b;
426         isc_result_t ret;
427         unsigned int bytes;
428         unsigned char data[ISC_SHA1_BLOCK_LENGTH];
429
430         UNUSED(callback);
431
432         bytes = (key->key_size + 7) / 8;
433         if (bytes > ISC_SHA1_BLOCK_LENGTH) {
434                 bytes = ISC_SHA1_BLOCK_LENGTH;
435                 key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
436         }
437
438         memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
439         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
440
441         if (ret != ISC_R_SUCCESS)
442                 return (ret);
443
444         isc_buffer_init(&b, data, bytes);
445         isc_buffer_add(&b, bytes);
446         ret = hmacsha1_fromdns(key, &b);
447         memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
448
449         return (ret);
450 }
451
452 static isc_boolean_t
453 hmacsha1_isprivate(const dst_key_t *key) {
454         UNUSED(key);
455         return (ISC_TRUE);
456 }
457
458 static void
459 hmacsha1_destroy(dst_key_t *key) {
460         dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
461
462         memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
463         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
464         key->keydata.hmacsha1 = NULL;
465 }
466
467 static isc_result_t
468 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
469         dst_hmacsha1_key_t *hkey;
470         unsigned int bytes;
471
472         REQUIRE(key->keydata.hmacsha1 != NULL);
473
474         hkey = key->keydata.hmacsha1;
475
476         bytes = (key->key_size + 7) / 8;
477         if (isc_buffer_availablelength(data) < bytes)
478                 return (ISC_R_NOSPACE);
479         isc_buffer_putmem(data, hkey->key, bytes);
480
481         return (ISC_R_SUCCESS);
482 }
483
484 static isc_result_t
485 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
486         dst_hmacsha1_key_t *hkey;
487         int keylen;
488         isc_region_t r;
489         isc_sha1_t sha1ctx;
490
491         isc_buffer_remainingregion(data, &r);
492         if (r.length == 0)
493                 return (ISC_R_SUCCESS);
494
495         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
496         if (hkey == NULL)
497                 return (ISC_R_NOMEMORY);
498
499         memset(hkey->key, 0, sizeof(hkey->key));
500
501         if (r.length > ISC_SHA1_BLOCK_LENGTH) {
502                 isc_sha1_init(&sha1ctx);
503                 isc_sha1_update(&sha1ctx, r.base, r.length);
504                 isc_sha1_final(&sha1ctx, hkey->key);
505                 keylen = ISC_SHA1_DIGESTLENGTH;
506         }
507         else {
508                 memcpy(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, /* computesecret */
593         hmacsha1_compare,
594         NULL, /* paramcompare */
595         hmacsha1_generate,
596         hmacsha1_isprivate,
597         hmacsha1_destroy,
598         hmacsha1_todns,
599         hmacsha1_fromdns,
600         hmacsha1_tofile,
601         hmacsha1_parse,
602         NULL, /* cleanup */
603         NULL, /* fromlabel */
604         NULL, /* dump */
605         NULL, /* restore */
606 };
607
608 isc_result_t
609 dst__hmacsha1_init(dst_func_t **funcp) {
610         REQUIRE(funcp != NULL);
611         if (*funcp == NULL)
612                 *funcp = &hmacsha1_functions;
613         return (ISC_R_SUCCESS);
614 }
615
616 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
617
618 struct dst_hmacsha224_key {
619         unsigned char key[ISC_SHA224_BLOCK_LENGTH];
620 };
621
622 static isc_result_t
623 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
624         isc_hmacsha224_t *hmacsha224ctx;
625         dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
626
627         hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
628         if (hmacsha224ctx == NULL)
629                 return (ISC_R_NOMEMORY);
630         isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
631         dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
632         return (ISC_R_SUCCESS);
633 }
634
635 static void
636 hmacsha224_destroyctx(dst_context_t *dctx) {
637         isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
638
639         if (hmacsha224ctx != NULL) {
640                 isc_hmacsha224_invalidate(hmacsha224ctx);
641                 isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
642                 dctx->ctxdata.hmacsha224ctx = NULL;
643         }
644 }
645
646 static isc_result_t
647 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
648         isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
649
650         isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
651         return (ISC_R_SUCCESS);
652 }
653
654 static isc_result_t
655 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
656         isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
657         unsigned char *digest;
658
659         if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
660                 return (ISC_R_NOSPACE);
661         digest = isc_buffer_used(sig);
662         isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
663         isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
664
665         return (ISC_R_SUCCESS);
666 }
667
668 static isc_result_t
669 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
670         isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
671
672         if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
673                 return (DST_R_VERIFYFAILURE);
674
675         if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
676                 return (ISC_R_SUCCESS);
677         else
678                 return (DST_R_VERIFYFAILURE);
679 }
680
681 static isc_boolean_t
682 hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
683         dst_hmacsha224_key_t *hkey1, *hkey2;
684
685         hkey1 = key1->keydata.hmacsha224;
686         hkey2 = key2->keydata.hmacsha224;
687
688         if (hkey1 == NULL && hkey2 == NULL)
689                 return (ISC_TRUE);
690         else if (hkey1 == NULL || hkey2 == NULL)
691                 return (ISC_FALSE);
692
693         if (memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH) == 0)
694                 return (ISC_TRUE);
695         else
696                 return (ISC_FALSE);
697 }
698
699 static isc_result_t
700 hmacsha224_generate(dst_key_t *key, int pseudorandom_ok,
701                     void (*callback)(int))
702 {
703         isc_buffer_t b;
704         isc_result_t ret;
705         unsigned int bytes;
706         unsigned char data[ISC_SHA224_BLOCK_LENGTH];
707
708         UNUSED(callback);
709
710         bytes = (key->key_size + 7) / 8;
711         if (bytes > ISC_SHA224_BLOCK_LENGTH) {
712                 bytes = ISC_SHA224_BLOCK_LENGTH;
713                 key->key_size = ISC_SHA224_BLOCK_LENGTH * 8;
714         }
715
716         memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
717         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
718
719         if (ret != ISC_R_SUCCESS)
720                 return (ret);
721
722         isc_buffer_init(&b, data, bytes);
723         isc_buffer_add(&b, bytes);
724         ret = hmacsha224_fromdns(key, &b);
725         memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
726
727         return (ret);
728 }
729
730 static isc_boolean_t
731 hmacsha224_isprivate(const dst_key_t *key) {
732         UNUSED(key);
733         return (ISC_TRUE);
734 }
735
736 static void
737 hmacsha224_destroy(dst_key_t *key) {
738         dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
739
740         memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
741         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
742         key->keydata.hmacsha224 = NULL;
743 }
744
745 static isc_result_t
746 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
747         dst_hmacsha224_key_t *hkey;
748         unsigned int bytes;
749
750         REQUIRE(key->keydata.hmacsha224 != NULL);
751
752         hkey = key->keydata.hmacsha224;
753
754         bytes = (key->key_size + 7) / 8;
755         if (isc_buffer_availablelength(data) < bytes)
756                 return (ISC_R_NOSPACE);
757         isc_buffer_putmem(data, hkey->key, bytes);
758
759         return (ISC_R_SUCCESS);
760 }
761
762 static isc_result_t
763 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
764         dst_hmacsha224_key_t *hkey;
765         int keylen;
766         isc_region_t r;
767         isc_sha224_t sha224ctx;
768
769         isc_buffer_remainingregion(data, &r);
770         if (r.length == 0)
771                 return (ISC_R_SUCCESS);
772
773         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
774         if (hkey == NULL)
775                 return (ISC_R_NOMEMORY);
776
777         memset(hkey->key, 0, sizeof(hkey->key));
778
779         if (r.length > ISC_SHA224_BLOCK_LENGTH) {
780                 isc_sha224_init(&sha224ctx);
781                 isc_sha224_update(&sha224ctx, r.base, r.length);
782                 isc_sha224_final(hkey->key, &sha224ctx);
783                 keylen = ISC_SHA224_DIGESTLENGTH;
784         }
785         else {
786                 memcpy(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, /* computesecret */
871         hmacsha224_compare,
872         NULL, /* paramcompare */
873         hmacsha224_generate,
874         hmacsha224_isprivate,
875         hmacsha224_destroy,
876         hmacsha224_todns,
877         hmacsha224_fromdns,
878         hmacsha224_tofile,
879         hmacsha224_parse,
880         NULL, /* cleanup */
881         NULL, /* fromlabel */
882         NULL, /* dump */
883         NULL, /* restore */
884 };
885
886 isc_result_t
887 dst__hmacsha224_init(dst_func_t **funcp) {
888         REQUIRE(funcp != NULL);
889         if (*funcp == NULL)
890                 *funcp = &hmacsha224_functions;
891         return (ISC_R_SUCCESS);
892 }
893
894 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
895
896 struct dst_hmacsha256_key {
897         unsigned char key[ISC_SHA256_BLOCK_LENGTH];
898 };
899
900 static isc_result_t
901 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
902         isc_hmacsha256_t *hmacsha256ctx;
903         dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
904
905         hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
906         if (hmacsha256ctx == NULL)
907                 return (ISC_R_NOMEMORY);
908         isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
909         dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
910         return (ISC_R_SUCCESS);
911 }
912
913 static void
914 hmacsha256_destroyctx(dst_context_t *dctx) {
915         isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
916
917         if (hmacsha256ctx != NULL) {
918                 isc_hmacsha256_invalidate(hmacsha256ctx);
919                 isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
920                 dctx->ctxdata.hmacsha256ctx = NULL;
921         }
922 }
923
924 static isc_result_t
925 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
926         isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
927
928         isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
929         return (ISC_R_SUCCESS);
930 }
931
932 static isc_result_t
933 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
934         isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
935         unsigned char *digest;
936
937         if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
938                 return (ISC_R_NOSPACE);
939         digest = isc_buffer_used(sig);
940         isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
941         isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
942
943         return (ISC_R_SUCCESS);
944 }
945
946 static isc_result_t
947 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
948         isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
949
950         if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
951                 return (DST_R_VERIFYFAILURE);
952
953         if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
954                 return (ISC_R_SUCCESS);
955         else
956                 return (DST_R_VERIFYFAILURE);
957 }
958
959 static isc_boolean_t
960 hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
961         dst_hmacsha256_key_t *hkey1, *hkey2;
962
963         hkey1 = key1->keydata.hmacsha256;
964         hkey2 = key2->keydata.hmacsha256;
965
966         if (hkey1 == NULL && hkey2 == NULL)
967                 return (ISC_TRUE);
968         else if (hkey1 == NULL || hkey2 == NULL)
969                 return (ISC_FALSE);
970
971         if (memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH) == 0)
972                 return (ISC_TRUE);
973         else
974                 return (ISC_FALSE);
975 }
976
977 static isc_result_t
978 hmacsha256_generate(dst_key_t *key, int pseudorandom_ok,
979                     void (*callback)(int))
980 {
981         isc_buffer_t b;
982         isc_result_t ret;
983         unsigned int bytes;
984         unsigned char data[ISC_SHA256_BLOCK_LENGTH];
985
986         UNUSED(callback);
987
988         bytes = (key->key_size + 7) / 8;
989         if (bytes > ISC_SHA256_BLOCK_LENGTH) {
990                 bytes = ISC_SHA256_BLOCK_LENGTH;
991                 key->key_size = ISC_SHA256_BLOCK_LENGTH * 8;
992         }
993
994         memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
995         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
996
997         if (ret != ISC_R_SUCCESS)
998                 return (ret);
999
1000         isc_buffer_init(&b, data, bytes);
1001         isc_buffer_add(&b, bytes);
1002         ret = hmacsha256_fromdns(key, &b);
1003         memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1004
1005         return (ret);
1006 }
1007
1008 static isc_boolean_t
1009 hmacsha256_isprivate(const dst_key_t *key) {
1010         UNUSED(key);
1011         return (ISC_TRUE);
1012 }
1013
1014 static void
1015 hmacsha256_destroy(dst_key_t *key) {
1016         dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
1017
1018         memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
1019         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
1020         key->keydata.hmacsha256 = NULL;
1021 }
1022
1023 static isc_result_t
1024 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
1025         dst_hmacsha256_key_t *hkey;
1026         unsigned int bytes;
1027
1028         REQUIRE(key->keydata.hmacsha256 != NULL);
1029
1030         hkey = key->keydata.hmacsha256;
1031
1032         bytes = (key->key_size + 7) / 8;
1033         if (isc_buffer_availablelength(data) < bytes)
1034                 return (ISC_R_NOSPACE);
1035         isc_buffer_putmem(data, hkey->key, bytes);
1036
1037         return (ISC_R_SUCCESS);
1038 }
1039
1040 static isc_result_t
1041 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
1042         dst_hmacsha256_key_t *hkey;
1043         int keylen;
1044         isc_region_t r;
1045         isc_sha256_t sha256ctx;
1046
1047         isc_buffer_remainingregion(data, &r);
1048         if (r.length == 0)
1049                 return (ISC_R_SUCCESS);
1050
1051         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
1052         if (hkey == NULL)
1053                 return (ISC_R_NOMEMORY);
1054
1055         memset(hkey->key, 0, sizeof(hkey->key));
1056
1057         if (r.length > ISC_SHA256_BLOCK_LENGTH) {
1058                 isc_sha256_init(&sha256ctx);
1059                 isc_sha256_update(&sha256ctx, r.base, r.length);
1060                 isc_sha256_final(hkey->key, &sha256ctx);
1061                 keylen = ISC_SHA256_DIGESTLENGTH;
1062         }
1063         else {
1064                 memcpy(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, /* computesecret */
1149         hmacsha256_compare,
1150         NULL, /* paramcompare */
1151         hmacsha256_generate,
1152         hmacsha256_isprivate,
1153         hmacsha256_destroy,
1154         hmacsha256_todns,
1155         hmacsha256_fromdns,
1156         hmacsha256_tofile,
1157         hmacsha256_parse,
1158         NULL, /* cleanup */
1159         NULL, /* fromlabel */
1160         NULL, /* dump */
1161         NULL, /* restore */
1162 };
1163
1164 isc_result_t
1165 dst__hmacsha256_init(dst_func_t **funcp) {
1166         REQUIRE(funcp != NULL);
1167         if (*funcp == NULL)
1168                 *funcp = &hmacsha256_functions;
1169         return (ISC_R_SUCCESS);
1170 }
1171
1172 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
1173
1174 struct dst_hmacsha384_key {
1175         unsigned char key[ISC_SHA384_BLOCK_LENGTH];
1176 };
1177
1178 static isc_result_t
1179 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
1180         isc_hmacsha384_t *hmacsha384ctx;
1181         dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1182
1183         hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
1184         if (hmacsha384ctx == NULL)
1185                 return (ISC_R_NOMEMORY);
1186         isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
1187         dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
1188         return (ISC_R_SUCCESS);
1189 }
1190
1191 static void
1192 hmacsha384_destroyctx(dst_context_t *dctx) {
1193         isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1194
1195         if (hmacsha384ctx != NULL) {
1196                 isc_hmacsha384_invalidate(hmacsha384ctx);
1197                 isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
1198                 dctx->ctxdata.hmacsha384ctx = NULL;
1199         }
1200 }
1201
1202 static isc_result_t
1203 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
1204         isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1205
1206         isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
1207         return (ISC_R_SUCCESS);
1208 }
1209
1210 static isc_result_t
1211 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1212         isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1213         unsigned char *digest;
1214
1215         if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
1216                 return (ISC_R_NOSPACE);
1217         digest = isc_buffer_used(sig);
1218         isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
1219         isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
1220
1221         return (ISC_R_SUCCESS);
1222 }
1223
1224 static isc_result_t
1225 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
1226         isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1227
1228         if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
1229                 return (DST_R_VERIFYFAILURE);
1230
1231         if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
1232                 return (ISC_R_SUCCESS);
1233         else
1234                 return (DST_R_VERIFYFAILURE);
1235 }
1236
1237 static isc_boolean_t
1238 hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
1239         dst_hmacsha384_key_t *hkey1, *hkey2;
1240
1241         hkey1 = key1->keydata.hmacsha384;
1242         hkey2 = key2->keydata.hmacsha384;
1243
1244         if (hkey1 == NULL && hkey2 == NULL)
1245                 return (ISC_TRUE);
1246         else if (hkey1 == NULL || hkey2 == NULL)
1247                 return (ISC_FALSE);
1248
1249         if (memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH) == 0)
1250                 return (ISC_TRUE);
1251         else
1252                 return (ISC_FALSE);
1253 }
1254
1255 static isc_result_t
1256 hmacsha384_generate(dst_key_t *key, int pseudorandom_ok,
1257                     void (*callback)(int))
1258 {
1259         isc_buffer_t b;
1260         isc_result_t ret;
1261         unsigned int bytes;
1262         unsigned char data[ISC_SHA384_BLOCK_LENGTH];
1263
1264         UNUSED(callback);
1265
1266         bytes = (key->key_size + 7) / 8;
1267         if (bytes > ISC_SHA384_BLOCK_LENGTH) {
1268                 bytes = ISC_SHA384_BLOCK_LENGTH;
1269                 key->key_size = ISC_SHA384_BLOCK_LENGTH * 8;
1270         }
1271
1272         memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1273         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1274
1275         if (ret != ISC_R_SUCCESS)
1276                 return (ret);
1277
1278         isc_buffer_init(&b, data, bytes);
1279         isc_buffer_add(&b, bytes);
1280         ret = hmacsha384_fromdns(key, &b);
1281         memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1282
1283         return (ret);
1284 }
1285
1286 static isc_boolean_t
1287 hmacsha384_isprivate(const dst_key_t *key) {
1288         UNUSED(key);
1289         return (ISC_TRUE);
1290 }
1291
1292 static void
1293 hmacsha384_destroy(dst_key_t *key) {
1294         dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1295
1296         memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
1297         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
1298         key->keydata.hmacsha384 = NULL;
1299 }
1300
1301 static isc_result_t
1302 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
1303         dst_hmacsha384_key_t *hkey;
1304         unsigned int bytes;
1305
1306         REQUIRE(key->keydata.hmacsha384 != NULL);
1307
1308         hkey = key->keydata.hmacsha384;
1309
1310         bytes = (key->key_size + 7) / 8;
1311         if (isc_buffer_availablelength(data) < bytes)
1312                 return (ISC_R_NOSPACE);
1313         isc_buffer_putmem(data, hkey->key, bytes);
1314
1315         return (ISC_R_SUCCESS);
1316 }
1317
1318 static isc_result_t
1319 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
1320         dst_hmacsha384_key_t *hkey;
1321         int keylen;
1322         isc_region_t r;
1323         isc_sha384_t sha384ctx;
1324
1325         isc_buffer_remainingregion(data, &r);
1326         if (r.length == 0)
1327                 return (ISC_R_SUCCESS);
1328
1329         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
1330         if (hkey == NULL)
1331                 return (ISC_R_NOMEMORY);
1332
1333         memset(hkey->key, 0, sizeof(hkey->key));
1334
1335         if (r.length > ISC_SHA384_BLOCK_LENGTH) {
1336                 isc_sha384_init(&sha384ctx);
1337                 isc_sha384_update(&sha384ctx, r.base, r.length);
1338                 isc_sha384_final(hkey->key, &sha384ctx);
1339                 keylen = ISC_SHA384_DIGESTLENGTH;
1340         }
1341         else {
1342                 memcpy(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, /* computesecret */
1427         hmacsha384_compare,
1428         NULL, /* paramcompare */
1429         hmacsha384_generate,
1430         hmacsha384_isprivate,
1431         hmacsha384_destroy,
1432         hmacsha384_todns,
1433         hmacsha384_fromdns,
1434         hmacsha384_tofile,
1435         hmacsha384_parse,
1436         NULL, /* cleanup */
1437         NULL, /* fromlabel */
1438         NULL, /* dump */
1439         NULL, /* restore */
1440 };
1441
1442 isc_result_t
1443 dst__hmacsha384_init(dst_func_t **funcp) {
1444         REQUIRE(funcp != NULL);
1445         if (*funcp == NULL)
1446                 *funcp = &hmacsha384_functions;
1447         return (ISC_R_SUCCESS);
1448 }
1449
1450 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
1451
1452 struct dst_hmacsha512_key {
1453         unsigned char key[ISC_SHA512_BLOCK_LENGTH];
1454 };
1455
1456 static isc_result_t
1457 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
1458         isc_hmacsha512_t *hmacsha512ctx;
1459         dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1460
1461         hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
1462         if (hmacsha512ctx == NULL)
1463                 return (ISC_R_NOMEMORY);
1464         isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
1465         dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
1466         return (ISC_R_SUCCESS);
1467 }
1468
1469 static void
1470 hmacsha512_destroyctx(dst_context_t *dctx) {
1471         isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1472
1473         if (hmacsha512ctx != NULL) {
1474                 isc_hmacsha512_invalidate(hmacsha512ctx);
1475                 isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
1476                 dctx->ctxdata.hmacsha512ctx = NULL;
1477         }
1478 }
1479
1480 static isc_result_t
1481 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
1482         isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1483
1484         isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
1485         return (ISC_R_SUCCESS);
1486 }
1487
1488 static isc_result_t
1489 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1490         isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1491         unsigned char *digest;
1492
1493         if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
1494                 return (ISC_R_NOSPACE);
1495         digest = isc_buffer_used(sig);
1496         isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
1497         isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
1498
1499         return (ISC_R_SUCCESS);
1500 }
1501
1502 static isc_result_t
1503 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
1504         isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1505
1506         if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
1507                 return (DST_R_VERIFYFAILURE);
1508
1509         if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
1510                 return (ISC_R_SUCCESS);
1511         else
1512                 return (DST_R_VERIFYFAILURE);
1513 }
1514
1515 static isc_boolean_t
1516 hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
1517         dst_hmacsha512_key_t *hkey1, *hkey2;
1518
1519         hkey1 = key1->keydata.hmacsha512;
1520         hkey2 = key2->keydata.hmacsha512;
1521
1522         if (hkey1 == NULL && hkey2 == NULL)
1523                 return (ISC_TRUE);
1524         else if (hkey1 == NULL || hkey2 == NULL)
1525                 return (ISC_FALSE);
1526
1527         if (memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH) == 0)
1528                 return (ISC_TRUE);
1529         else
1530                 return (ISC_FALSE);
1531 }
1532
1533 static isc_result_t
1534 hmacsha512_generate(dst_key_t *key, int pseudorandom_ok,
1535                     void (*callback)(int))
1536 {
1537         isc_buffer_t b;
1538         isc_result_t ret;
1539         unsigned int bytes;
1540         unsigned char data[ISC_SHA512_BLOCK_LENGTH];
1541
1542         UNUSED(callback);
1543
1544         bytes = (key->key_size + 7) / 8;
1545         if (bytes > ISC_SHA512_BLOCK_LENGTH) {
1546                 bytes = ISC_SHA512_BLOCK_LENGTH;
1547                 key->key_size = ISC_SHA512_BLOCK_LENGTH * 8;
1548         }
1549
1550         memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1551         ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1552
1553         if (ret != ISC_R_SUCCESS)
1554                 return (ret);
1555
1556         isc_buffer_init(&b, data, bytes);
1557         isc_buffer_add(&b, bytes);
1558         ret = hmacsha512_fromdns(key, &b);
1559         memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1560
1561         return (ret);
1562 }
1563
1564 static isc_boolean_t
1565 hmacsha512_isprivate(const dst_key_t *key) {
1566         UNUSED(key);
1567         return (ISC_TRUE);
1568 }
1569
1570 static void
1571 hmacsha512_destroy(dst_key_t *key) {
1572         dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1573
1574         memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
1575         isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
1576         key->keydata.hmacsha512 = NULL;
1577 }
1578
1579 static isc_result_t
1580 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
1581         dst_hmacsha512_key_t *hkey;
1582         unsigned int bytes;
1583
1584         REQUIRE(key->keydata.hmacsha512 != NULL);
1585
1586         hkey = key->keydata.hmacsha512;
1587
1588         bytes = (key->key_size + 7) / 8;
1589         if (isc_buffer_availablelength(data) < bytes)
1590                 return (ISC_R_NOSPACE);
1591         isc_buffer_putmem(data, hkey->key, bytes);
1592
1593         return (ISC_R_SUCCESS);
1594 }
1595
1596 static isc_result_t
1597 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
1598         dst_hmacsha512_key_t *hkey;
1599         int keylen;
1600         isc_region_t r;
1601         isc_sha512_t sha512ctx;
1602
1603         isc_buffer_remainingregion(data, &r);
1604         if (r.length == 0)
1605                 return (ISC_R_SUCCESS);
1606
1607         hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
1608         if (hkey == NULL)
1609                 return (ISC_R_NOMEMORY);
1610
1611         memset(hkey->key, 0, sizeof(hkey->key));
1612
1613         if (r.length > ISC_SHA512_BLOCK_LENGTH) {
1614                 isc_sha512_init(&sha512ctx);
1615                 isc_sha512_update(&sha512ctx, r.base, r.length);
1616                 isc_sha512_final(hkey->key, &sha512ctx);
1617                 keylen = ISC_SHA512_DIGESTLENGTH;
1618         }
1619         else {
1620                 memcpy(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, /* computesecret */
1705         hmacsha512_compare,
1706         NULL, /* paramcompare */
1707         hmacsha512_generate,
1708         hmacsha512_isprivate,
1709         hmacsha512_destroy,
1710         hmacsha512_todns,
1711         hmacsha512_fromdns,
1712         hmacsha512_tofile,
1713         hmacsha512_parse,
1714         NULL, /* cleanup */
1715         NULL, /* fromlabel */
1716         NULL, /* dump */
1717         NULL, /* restore */
1718 };
1719
1720 isc_result_t
1721 dst__hmacsha512_init(dst_func_t **funcp) {
1722         REQUIRE(funcp != NULL);
1723         if (*funcp == NULL)
1724                 *funcp = &hmacsha512_functions;
1725         return (ISC_R_SUCCESS);
1726 }
1727
1728 /*! \file */