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