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