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