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