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 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 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 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 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 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 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 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 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 180 hmacmd5_isprivate(const dst_key_t *key) { 181 UNUSED(key); 182 return (ISC_TRUE); 183 } 184 185 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 465 hmacsha1_isprivate(const dst_key_t *key) { 466 UNUSED(key); 467 return (ISC_TRUE); 468 } 469 470 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 752 hmacsha224_isprivate(const dst_key_t *key) { 753 UNUSED(key); 754 return (ISC_TRUE); 755 } 756 757 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 1039 hmacsha256_isprivate(const dst_key_t *key) { 1040 UNUSED(key); 1041 return (ISC_TRUE); 1042 } 1043 1044 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 1326 hmacsha384_isprivate(const dst_key_t *key) { 1327 UNUSED(key); 1328 return (ISC_TRUE); 1329 } 1330 1331 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 1613 hmacsha512_isprivate(const dst_key_t *key) { 1614 UNUSED(key); 1615 return (ISC_TRUE); 1616 } 1617 1618 static void 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 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 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 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 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 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