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