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