1/* $NetBSD: t_dst.c,v 1.5 2012/12/04 23:38:39 spz Exp $ */ 2 3/* 4 * Copyright (C) 2004, 2005, 2007-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 1999-2001 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 DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20/* Id: t_dst.c,v 1.60 2011/03/17 23:47:29 tbox Exp */ 21 22#include <config.h> 23 24#include <sys/types.h> /* Required for dirent.h */ 25#include <sys/stat.h> 26 27#include <dirent.h> /* XXX */ 28#include <errno.h> 29#include <fcntl.h> 30#include <limits.h> 31#include <stdlib.h> 32 33#include <unistd.h> /* XXX */ 34 35#include <isc/buffer.h> 36#include <isc/dir.h> 37#include <isc/entropy.h> 38#include <isc/file.h> 39#include <isc/mem.h> 40#include <isc/region.h> 41#include <isc/string.h> 42#include <isc/util.h> 43 44#include <dns/fixedname.h> 45#include <dns/name.h> 46 47#include <dst/dst.h> 48#include <dst/result.h> 49 50#include <tests/t_api.h> 51 52#ifndef PATH_MAX 53#define PATH_MAX 256 54#endif 55 56/* 57 * Adapted from the original dst_test.c program. 58 * XXXDCL should use isc_dir_*. 59 */ 60 61static void 62cleandir(char *path) { 63 DIR *dirp; 64 struct dirent *pe; 65 char fullname[PATH_MAX + 1]; 66 67 dirp = opendir(path); 68 if (dirp == NULL) { 69 t_info("opendir(%s) failed %d\n", path, errno); 70 return; 71 } 72 73 while ((pe = readdir(dirp)) != NULL) { 74 if (! strcmp(pe->d_name, ".")) 75 continue; 76 if (! strcmp(pe->d_name, "..")) 77 continue; 78 strcpy(fullname, path); 79 strcat(fullname, "/"); 80 strcat(fullname, pe->d_name); 81 if (remove(fullname)) 82 t_info("remove(%s) failed %d\n", fullname, errno); 83 84 } 85 (void)closedir(dirp); 86 if (rmdir(path)) 87 t_info("rmdir(%s) failed %d\n", path, errno); 88 89 return; 90} 91 92static void 93use(dst_key_t *key, isc_mem_t *mctx, isc_result_t exp_result, int *nfails) { 94 95 isc_result_t ret; 96 const char *data = "This is some data"; 97 unsigned char sig[512]; 98 isc_buffer_t databuf, sigbuf; 99 isc_region_t datareg, sigreg; 100 dst_context_t *ctx = NULL; 101 102 isc_buffer_init(&sigbuf, sig, sizeof(sig)); 103 isc_buffer_init(&databuf, data, strlen(data)); 104 isc_buffer_add(&databuf, strlen(data)); 105 isc_buffer_usedregion(&databuf, &datareg); 106 107 ret = dst_context_create(key, mctx, &ctx); 108 if (ret != exp_result) { 109 t_info("dst_context_create(%d) returned (%s) expected (%s)\n", 110 dst_key_alg(key), dst_result_totext(ret), 111 dst_result_totext(exp_result)); 112 ++*nfails; 113 return; 114 } 115 if (exp_result != ISC_R_SUCCESS) 116 return; 117 ret = dst_context_adddata(ctx, &datareg); 118 if (ret != ISC_R_SUCCESS) { 119 t_info("dst_context_adddata(%d) returned (%s)\n", 120 dst_key_alg(key), dst_result_totext(ret)); 121 ++*nfails; 122 dst_context_destroy(&ctx); 123 return; 124 } 125 ret = dst_context_sign(ctx, &sigbuf); 126 if (ret != ISC_R_SUCCESS) { 127 t_info("dst_context_sign(%d) returned (%s)\n", 128 dst_key_alg(key), dst_result_totext(ret)); 129 ++*nfails; 130 dst_context_destroy(&ctx); 131 return; 132 } 133 dst_context_destroy(&ctx); 134 135 isc_buffer_remainingregion(&sigbuf, &sigreg); 136 ret = dst_context_create(key, mctx, &ctx); 137 if (ret != ISC_R_SUCCESS) { 138 t_info("dst_context_create(%d) returned (%s)\n", 139 dst_key_alg(key), dst_result_totext(ret)); 140 ++*nfails; 141 return; 142 } 143 ret = dst_context_adddata(ctx, &datareg); 144 if (ret != ISC_R_SUCCESS) { 145 t_info("dst_context_adddata(%d) returned (%s)\n", 146 dst_key_alg(key), dst_result_totext(ret)); 147 ++*nfails; 148 dst_context_destroy(&ctx); 149 return; 150 } 151 ret = dst_context_verify(ctx, &sigreg); 152 if (ret != exp_result) { 153 t_info("dst_context_verify(%d) returned (%s) expected (%s)\n", 154 dst_key_alg(key), dst_result_totext(ret), 155 dst_result_totext(exp_result)); 156 ++*nfails; 157 dst_context_destroy(&ctx); 158 return; 159 } 160 dst_context_destroy(&ctx); 161} 162 163static void 164dh(dns_name_t *name1, int id1, dns_name_t *name2, int id2, isc_mem_t *mctx, 165 isc_result_t exp_result, int *nfails, int *nprobs) 166{ 167 dst_key_t *key1 = NULL, *key2 = NULL; 168 isc_result_t ret; 169 char current[PATH_MAX + 1]; 170 char tmp[PATH_MAX + 1]; 171 char *p; 172 int alg = DST_ALG_DH; 173 int type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY; 174 unsigned char array1[1024], array2[1024]; 175 isc_buffer_t b1, b2; 176 isc_region_t r1, r2; 177 178 UNUSED(exp_result); 179 180 p = getcwd(current, PATH_MAX);; 181 if (p == NULL) { 182 t_info("getcwd failed %d\n", errno); 183 ++*nprobs; 184 goto cleanup; 185 } 186 187 ret = dst_key_fromfile(name1, id1, alg, type, current, mctx, &key1); 188 if (ret != ISC_R_SUCCESS) { 189 t_info("dst_key_fromfile(%d) returned: %s\n", 190 alg, dst_result_totext(ret)); 191 ++*nfails; 192 goto cleanup; 193 } 194 195 ret = dst_key_fromfile(name2, id2, alg, type, current, mctx, &key2); 196 if (ret != ISC_R_SUCCESS) { 197 t_info("dst_key_fromfile(%d) returned: %s\n", 198 alg, dst_result_totext(ret)); 199 ++*nfails; 200 goto cleanup; 201 } 202 203 ret = isc_file_mktemplate("/tmp/", tmp, sizeof(tmp)); 204 if (ret != ISC_R_SUCCESS) { 205 t_info("isc_file_mktemplate failed %s\n", 206 isc_result_totext(ret)); 207 ++*nprobs; 208 goto cleanup; 209 } 210 211 ret = isc_dir_createunique(tmp); 212 if (ret != ISC_R_SUCCESS) { 213 t_info("isc_dir_createunique failed %s\n", 214 isc_result_totext(ret)); 215 ++*nprobs; 216 goto cleanup; 217 } 218 219 ret = dst_key_tofile(key1, type, tmp); 220 if (ret != 0) { 221 t_info("dst_key_tofile(%d) returned: %s\n", 222 alg, dst_result_totext(ret)); 223 ++*nfails; 224 goto cleanup; 225 } 226 227 ret = dst_key_tofile(key2, type, tmp); 228 if (ret != 0) { 229 t_info("dst_key_tofile(%d) returned: %s\n", 230 alg, dst_result_totext(ret)); 231 ++*nfails; 232 goto cleanup; 233 } 234 235 cleandir(tmp); 236 237 isc_buffer_init(&b1, array1, sizeof(array1)); 238 ret = dst_key_computesecret(key1, key2, &b1); 239 if (ret != 0) { 240 t_info("dst_computesecret() returned: %s\n", 241 dst_result_totext(ret)); 242 ++*nfails; 243 goto cleanup; 244 } 245 246 isc_buffer_init(&b2, array2, sizeof(array2)); 247 ret = dst_key_computesecret(key2, key1, &b2); 248 if (ret != 0) { 249 t_info("dst_computesecret() returned: %s\n", 250 dst_result_totext(ret)); 251 ++*nfails; 252 goto cleanup; 253 } 254 255 isc_buffer_usedregion(&b1, &r1); 256 isc_buffer_usedregion(&b2, &r2); 257 if (r1.length != r2.length || memcmp(r1.base, r2.base, r1.length) != 0) 258 { 259 t_info("computed secrets don't match\n"); 260 ++*nfails; 261 goto cleanup; 262 } 263 264 cleanup: 265 if (key1 != NULL) 266 dst_key_free(&key1); 267 if (key2 != NULL) 268 dst_key_free(&key2); 269} 270 271static void 272io(dns_name_t *name, isc_uint16_t id, isc_uint16_t alg, int type, 273 isc_mem_t *mctx, isc_result_t exp_result, int *nfails, int *nprobs) 274{ 275 dst_key_t *key = NULL; 276 isc_result_t ret; 277 char current[PATH_MAX + 1]; 278 char tmp[PATH_MAX + 1]; 279 char *p; 280 281 p = getcwd(current, PATH_MAX);; 282 if (p == NULL) { 283 t_info("getcwd failed %d\n", errno); 284 ++*nprobs; 285 goto failure; 286 } 287 288 ret = dst_key_fromfile(name, id, alg, type, current, mctx, &key); 289 if (ret != ISC_R_SUCCESS) { 290 t_info("dst_key_fromfile(%d) returned: %s\n", 291 alg, dst_result_totext(ret)); 292 ++*nfails; 293 goto failure; 294 } 295 296 if (dst_key_id(key) != id) { 297 t_info("key ID incorrect\n"); 298 ++*nfails; 299 goto failure; 300 } 301 302 if (dst_key_alg(key) != alg) { 303 t_info("key algorithm incorrect\n"); 304 ++*nfails; 305 goto failure; 306 } 307 308 if (dst_key_getttl(key) != 0) { 309 t_info("initial key TTL incorrect\n"); 310 ++*nfails; 311 goto failure; 312 } 313 314 ret = isc_file_mktemplate("/tmp/", tmp, sizeof(tmp)); 315 if (ret != ISC_R_SUCCESS) { 316 t_info("isc_file_mktemplate failed %s\n", 317 isc_result_totext(ret)); 318 ++*nprobs; 319 goto failure; 320 } 321 322 ret = isc_dir_createunique(tmp); 323 if (ret != ISC_R_SUCCESS) { 324 t_info("mkdir failed %d\n", errno); 325 ++*nprobs; 326 goto failure; 327 } 328 329 ret = dst_key_tofile(key, type, tmp); 330 if (ret != 0) { 331 t_info("dst_key_tofile(%d) returned: %s\n", 332 alg, dst_result_totext(ret)); 333 ++*nfails; 334 goto failure; 335 } 336 337 if (dst_key_alg(key) != DST_ALG_DH) 338 use(key, mctx, exp_result, nfails); 339 340 /* 341 * Skip the rest of this test if we weren't expecting 342 * the read to be successful. 343 */ 344 if (exp_result != ISC_R_SUCCESS) 345 goto cleanup; 346 347 dst_key_setttl(key, 3600); 348 ret = dst_key_tofile(key, type, tmp); 349 if (ret != 0) { 350 t_info("dst_key_tofile(%d) returned: %s\n", 351 alg, dst_result_totext(ret)); 352 ++*nfails; 353 goto failure; 354 } 355 356 /* Reread key to confirm TTL was changed */ 357 dst_key_free(&key); 358 ret = dst_key_fromfile(name, id, alg, type, tmp, mctx, &key); 359 if (ret != ISC_R_SUCCESS) { 360 t_info("dst_key_fromfile(%d) returned: %s\n", 361 alg, dst_result_totext(ret)); 362 ++*nfails; 363 goto failure; 364 } 365 366 if (dst_key_getttl(key) != 3600) { 367 t_info("modified key TTL incorrect\n"); 368 ++*nfails; 369 goto failure; 370 } 371 372 cleanup: 373 cleandir(tmp); 374 375 failure: 376 dst_key_free(&key); 377} 378 379static void 380generate(int alg, isc_mem_t *mctx, int size, int *nfails) { 381 isc_result_t ret; 382 dst_key_t *key = NULL; 383 384 ret = dst_key_generate(dns_rootname, alg, size, 0, 0, 0, 385 dns_rdataclass_in, mctx, &key); 386 if (ret != ISC_R_SUCCESS) { 387 t_info("dst_key_generate(%d) returned: %s\n", alg, 388 dst_result_totext(ret)); 389 ++*nfails; 390 goto cleanup; 391 } 392 393 if (alg != DST_ALG_DH) 394 use(key, mctx, ISC_R_SUCCESS, nfails); 395 cleanup: 396 if (key != NULL) 397 dst_key_free(&key); 398} 399 400#define DBUFSIZ 25 401 402static const char *a1 = 403 "the dst module provides the capability to " 404 "generate, store and retrieve public and private keys, " 405 "sign and verify data using the RSA, DSA and MD5 algorithms, " 406 "and compute Diffie-Hellman shared secrets."; 407static void 408t1(void) { 409 isc_mem_t *mctx; 410 isc_entropy_t *ectx; 411 int nfails; 412 int nprobs; 413 int result; 414 isc_result_t isc_result; 415 dns_fixedname_t fname; 416 dns_name_t *name; 417 isc_buffer_t b; 418 419 t_assert("dst", 1, T_REQUIRED, "%s", a1); 420 421 nfails = 0; 422 nprobs = 0; 423 mctx = NULL; 424 isc_result = isc_mem_create(0, 0, &mctx); 425 if (isc_result != ISC_R_SUCCESS) { 426 t_info("isc_mem_create failed %s\n", 427 isc_result_totext(isc_result)); 428 t_result(T_UNRESOLVED); 429 return; 430 } 431 ectx = NULL; 432 isc_result = isc_entropy_create(mctx, &ectx); 433 if (isc_result != ISC_R_SUCCESS) { 434 t_info("isc_entropy_create failed %s\n", 435 isc_result_totext(isc_result)); 436 t_result(T_UNRESOLVED); 437 return; 438 } 439 isc_result = isc_entropy_createfilesource(ectx, "randomfile"); 440 if (isc_result != ISC_R_SUCCESS) { 441 t_info("isc_entropy_create failed %s\n", 442 isc_result_totext(isc_result)); 443 t_result(T_UNRESOLVED); 444 return; 445 } 446 isc_result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING); 447 if (isc_result != ISC_R_SUCCESS) { 448 t_info("dst_lib_init failed %s\n", 449 isc_result_totext(isc_result)); 450 t_result(T_UNRESOLVED); 451 return; 452 } 453 454 if (!dst_algorithm_supported(DST_ALG_RSAMD5)) { 455 dst_lib_destroy(); 456 t_info("library built without crypto support\n"); 457 t_result(T_UNTESTED); 458 return; 459 } 460 461 t_info("testing use of stored keys [1]\n"); 462 463 dns_fixedname_init(&fname); 464 name = dns_fixedname_name(&fname); 465 isc_buffer_init(&b, "test.", 5); 466 isc_buffer_add(&b, 5); 467 isc_result = dns_name_fromtext(name, &b, NULL, 0, NULL); 468 if (isc_result != ISC_R_SUCCESS) { 469 t_info("dns_name_fromtext failed %s\n", 470 isc_result_totext(isc_result)); 471 t_result(T_UNRESOLVED); 472 return; 473 } 474 io(name, 23616, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, 475 mctx, ISC_R_SUCCESS, &nfails, &nprobs); 476 t_info("testing use of stored keys [2]\n"); 477 io(name, 54622, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, 478 mctx, ISC_R_SUCCESS, &nfails, &nprobs); 479 480 t_info("testing use of stored keys [3]\n"); 481 io(name, 49667, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, 482 mctx, DST_R_NULLKEY, &nfails, &nprobs); 483 t_info("testing use of stored keys [4]\n"); 484 io(name, 2, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, 485 mctx, DST_R_NULLKEY, &nfails, &nprobs); 486 487 isc_buffer_init(&b, "dh.", 3); 488 isc_buffer_add(&b, 3); 489 isc_result = dns_name_fromtext(name, &b, NULL, 0, NULL); 490 if (isc_result != ISC_R_SUCCESS) { 491 t_info("dns_name_fromtext failed %s\n", 492 isc_result_totext(isc_result)); 493 t_result(T_UNRESOLVED); 494 return; 495 } 496 497 dh(name, 18602, name, 48957, mctx, ISC_R_SUCCESS, &nfails, &nprobs); 498 499 t_info("testing use of generated keys\n"); 500 generate(DST_ALG_RSAMD5, mctx, 512, &nfails); 501 generate(DST_ALG_DSA, mctx, 512, &nfails); 502 generate(DST_ALG_DH, mctx, 512, &nfails); 503 /* 504 * This one uses a constant. 505 */ 506 generate(DST_ALG_DH, mctx, 768, &nfails); 507 generate(DST_ALG_HMACMD5, mctx, 512, &nfails); 508 509 dst_lib_destroy(); 510 511 isc_entropy_detach(&ectx); 512 513 isc_mem_destroy(&mctx); 514 515 result = T_UNRESOLVED; 516 if ((nfails == 0) && (nprobs == 0)) 517 result = T_PASS; 518 else if (nfails) 519 result = T_FAIL; 520 t_result(result); 521 522} 523 524#define T_SIGMAX 512 525 526#undef NEWSIG /* Define NEWSIG to generate the original signature file. */ 527 528#ifdef NEWSIG 529 530/* 531 * Write a sig in buf to file at path. 532 */ 533static int 534sig_tofile(char *path, isc_buffer_t *buf) { 535 int rval; 536 int fd; 537 int len; 538 int nprobs; 539 int cnt; 540 unsigned char c; 541 unsigned char val; 542 543 cnt = 0; 544 nprobs = 0; 545 len = buf->used - buf->current; 546 547 t_info("buf: current %d used %d len %d\n", 548 buf->current, buf->used, len); 549 550 fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRWXU|S_IRWXO|S_IRWXG); 551 if (fd < 0) { 552 t_info("open %s failed %d\n", path, errno); 553 return(1); 554 } 555 556 while (len) { 557 c = (unsigned char) isc_buffer_getuint8(buf); 558 val = ((c >> 4 ) & 0x0f); 559 if ((0 <= val) && (val <= 9)) 560 val = '0' + val; 561 else 562 val = 'A' + val - 10; 563 rval = write(fd, &val, 1); 564 if (rval != 1) { 565 ++nprobs; 566 t_info("write failed %d %d\n", rval, errno); 567 break; 568 } 569 val = (c & 0x0f); 570 if ((0 <= val) && (val <= 9)) 571 val = '0' + val; 572 else 573 val = 'A' + val - 10; 574 rval = write(fd, &val, 1); 575 if (rval != 1) { 576 ++nprobs; 577 t_info("write failed %d %d\n", rval, errno); 578 break; 579 } 580 --len; 581 ++cnt; 582 if ((cnt % 16) == 0) { 583 val = '\n'; 584 rval = write(fd, &val, 1); 585 if (rval != 1) { 586 ++nprobs; 587 t_info("write failed %d %d\n", rval, errno); 588 break; 589 } 590 } 591 } 592 val = '\n'; 593 rval = write(fd, &val, 1); 594 if (rval != 1) { 595 ++nprobs; 596 t_info("write failed %d %d\n", rval, errno); 597 } 598 (void) close(fd); 599 return(nprobs); 600} 601 602#endif /* NEWSIG */ 603 604/* 605 * Read sig in file at path to buf. 606 */ 607static int 608sig_fromfile(char *path, isc_buffer_t *iscbuf) { 609 int rval; 610 int len; 611 int fd; 612 unsigned char val; 613 struct stat sb; 614 char *p; 615 char *buf; 616 617 rval = stat(path, &sb); 618 if (rval != 0) { 619 t_info("stat %s failed, errno == %d\n", path, errno); 620 return(1); 621 } 622 623 buf = (char *) malloc((sb.st_size + 1) * sizeof(unsigned char)); 624 if (buf == NULL) { 625 t_info("malloc failed, errno == %d\n", errno); 626 return(1); 627 } 628 629 fd = open(path, O_RDONLY); 630 if (fd < 0) { 631 t_info("open failed, errno == %d\n", errno); 632 (void) free(buf); 633 return(1); 634 } 635 636 len = sb.st_size; 637 p = buf; 638 while (len) { 639 rval = read(fd, p, len); 640 if (rval > 0) { 641 len -= rval; 642 p += rval; 643 } 644 else { 645 t_info("read failed %d, errno == %d\n", rval, errno); 646 (void) free(buf); 647 (void) close(fd); 648 return(1); 649 } 650 } 651 close(fd); 652 653 p = buf; 654 len = sb.st_size; 655 while(len) { 656 if (*p == '\n') { 657 ++p; 658 --len; 659 continue; 660 } 661 if (('0' <= *p) && (*p <= '9')) 662 val = *p - '0'; 663 else 664 val = *p - 'A' + 10; 665 ++p; 666 val <<= 4; 667 --len; 668 if (('0' <= *p) && (*p <= '9')) 669 val |= (*p - '0'); 670 else 671 val |= (*p - 'A' + 10); 672 ++p; 673 --len; 674 isc_buffer_putuint8(iscbuf, val); 675 } 676 (void) free(buf); 677 return(0); 678} 679 680static void 681t2_sigchk(char *datapath, char *sigpath, char *keyname, 682 int id, int alg, int type, 683 isc_mem_t *mctx, char *expected_result, 684 int *nfails, int *nprobs) 685{ 686 int rval; 687 int len; 688 int fd; 689 int exp_res; 690 dst_key_t *key = NULL; 691 unsigned char sig[T_SIGMAX]; 692 unsigned char *p; 693 unsigned char *data; 694 struct stat sb; 695 isc_result_t isc_result; 696 isc_buffer_t databuf; 697 isc_buffer_t sigbuf; 698 isc_region_t datareg; 699 isc_region_t sigreg; 700 dns_fixedname_t fname; 701 dns_name_t *name; 702 isc_buffer_t b; 703 dst_context_t *ctx = NULL; 704 705 /* 706 * Read data from file in a form usable by dst_verify. 707 */ 708 rval = stat(datapath, &sb); 709 if (rval != 0) { 710 t_info("t2_sigchk: stat (%s) failed %d\n", datapath, errno); 711 ++*nprobs; 712 return; 713 } 714 715 data = (unsigned char *) malloc(sb.st_size * sizeof(char)); 716 if (data == NULL) { 717 t_info("t2_sigchk: malloc failed %d\n", errno); 718 ++*nprobs; 719 return; 720 } 721 722 fd = open(datapath, O_RDONLY); 723 if (fd < 0) { 724 t_info("t2_sigchk: open failed %d\n", errno); 725 (void) free(data); 726 ++*nprobs; 727 return; 728 } 729 730 p = data; 731 len = sb.st_size; 732 do { 733 rval = read(fd, p, len); 734 if (rval > 0) { 735 len -= rval; 736 p += rval; 737 } 738 } while (len); 739 (void) close(fd); 740 741 /* 742 * Read key from file in a form usable by dst_verify. 743 */ 744 dns_fixedname_init(&fname); 745 name = dns_fixedname_name(&fname); 746 isc_buffer_init(&b, keyname, strlen(keyname)); 747 isc_buffer_add(&b, strlen(keyname)); 748 isc_result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 749 if (isc_result != ISC_R_SUCCESS) { 750 t_info("dns_name_fromtext failed %s\n", 751 isc_result_totext(isc_result)); 752 (void) free(data); 753 ++*nprobs; 754 return; 755 } 756 isc_result = dst_key_fromfile(name, id, alg, type, NULL, mctx, &key); 757 if (isc_result != ISC_R_SUCCESS) { 758 t_info("dst_key_fromfile failed %s\n", 759 isc_result_totext(isc_result)); 760 (void) free(data); 761 ++*nprobs; 762 return; 763 } 764 765 isc_buffer_init(&databuf, data, sb.st_size); 766 isc_buffer_add(&databuf, sb.st_size); 767 isc_buffer_usedregion(&databuf, &datareg); 768 769#ifdef NEWSIG 770 771 /* 772 * If we're generating a signature for the first time, 773 * sign the data and save the signature to a file 774 */ 775 776 memset(sig, 0, sizeof(sig)); 777 isc_buffer_init(&sigbuf, sig, sizeof(sig)); 778 779 isc_result = dst_context_create(key, mctx, &ctx); 780 if (isc_result != ISC_R_SUCCESS) { 781 t_info("dst_context_create(%d) failed %s\n", 782 dst_result_totext(isc_result)); 783 (void) free(data); 784 dst_key_free(&key); 785 ++*nprobs; 786 return; 787 } 788 isc_result = dst_context_adddata(ctx, &datareg); 789 if (isc_result != ISC_R_SUCCESS) { 790 t_info("dst_context_adddata(%d) failed %s\n", 791 dst_result_totext(isc_result)); 792 (void) free(data); 793 dst_key_free(&key); 794 dst_context_destroy(&ctx); 795 ++*nprobs; 796 return; 797 } 798 isc_result = dst_context_sign(ctx, &sigbuf); 799 if (isc_result != ISC_R_SUCCESS) { 800 t_info("dst_sign(%d) failed %s\n", 801 dst_result_totext(isc_result)); 802 (void) free(data); 803 dst_key_free(&key); 804 dst_context_destroy(&ctx); 805 ++*nprobs; 806 return; 807 } 808 dst_context_destroy(&ctx); 809 810 rval = sig_tofile(sigpath, &sigbuf); 811 if (rval != 0) { 812 t_info("sig_tofile failed\n"); 813 ++*nprobs; 814 (void) free(data); 815 dst_key_free(&key); 816 return; 817 } 818 819#endif /* NEWSIG */ 820 821 memset(sig, 0, sizeof(sig)); 822 isc_buffer_init(&sigbuf, sig, sizeof(sig)); 823 824 /* 825 * Read precomputed signature from file in a form usable by dst_verify. 826 */ 827 rval = sig_fromfile(sigpath, &sigbuf); 828 if (rval != 0) { 829 t_info("sig_fromfile failed\n"); 830 (void) free(data); 831 dst_key_free(&key); 832 ++*nprobs; 833 return; 834 } 835 836 /* 837 * Verify that the key signed the data. 838 */ 839 isc_buffer_remainingregion(&sigbuf, &sigreg); 840 841 exp_res = 0; 842 if (strstr(expected_result, "!")) 843 exp_res = 1; 844 845 isc_result = dst_context_create(key, mctx, &ctx); 846 if (isc_result != ISC_R_SUCCESS) { 847 t_info("dst_context_create returned %s\n", 848 isc_result_totext(isc_result)); 849 (void) free(data); 850 dst_key_free(&key); 851 ++*nfails; 852 return; 853 } 854 isc_result = dst_context_adddata(ctx, &datareg); 855 if (isc_result != ISC_R_SUCCESS) { 856 t_info("dst_context_adddata returned %s\n", 857 isc_result_totext(isc_result)); 858 (void) free(data); 859 dst_context_destroy(&ctx); 860 dst_key_free(&key); 861 ++*nfails; 862 return; 863 } 864 isc_result = dst_context_verify(ctx, &sigreg); 865 if ( ((exp_res == 0) && (isc_result != ISC_R_SUCCESS)) || 866 ((exp_res != 0) && (isc_result == ISC_R_SUCCESS))) { 867 868 t_info("dst_context_verify returned %s, expected %s\n", 869 isc_result_totext(isc_result), 870 expected_result); 871 ++*nfails; 872 } 873 874 (void) free(data); 875 dst_context_destroy(&ctx); 876 dst_key_free(&key); 877 return; 878} 879 880/* 881 * The astute observer will note that t1() signs then verifies data 882 * during the test but that t2() verifies data that has been 883 * signed at some earlier time, possibly with an entire different 884 * version or implementation of the DSA and RSA algorithms 885 */ 886static const char *a2 = 887 "the dst module provides the capability to " 888 "verify data signed with the RSA and DSA algorithms"; 889 890/* 891 * av == datafile, sigpath, keyname, keyid, alg, exp_result. 892 */ 893static int 894t2_vfy(char **av) { 895 char *datapath; 896 char *sigpath; 897 char *keyname; 898 char *key; 899 int keyid; 900 char *alg; 901 int algid; 902 char *exp_result; 903 int nfails; 904 int nprobs; 905 isc_mem_t *mctx; 906 isc_entropy_t *ectx; 907 isc_result_t isc_result; 908 int result; 909 910 datapath = *av++; 911 sigpath = *av++; 912 keyname = *av++; 913 key = *av++; 914 keyid = atoi(key); 915 alg = *av++; 916 exp_result = *av++; 917 nfails = 0; 918 nprobs = 0; 919 920 if (! strcasecmp(alg, "DST_ALG_DSA")) 921 algid = DST_ALG_DSA; 922 else if (! strcasecmp(alg, "DST_ALG_RSAMD5")) 923 algid = DST_ALG_RSAMD5; 924 else { 925 t_info("Unknown algorithm %s\n", alg); 926 return(T_UNRESOLVED); 927 } 928 929 mctx = NULL; 930 isc_result = isc_mem_create(0, 0, &mctx); 931 if (isc_result != ISC_R_SUCCESS) { 932 t_info("isc_mem_create failed %s\n", 933 isc_result_totext(isc_result)); 934 return(T_UNRESOLVED); 935 } 936 ectx = NULL; 937 isc_result = isc_entropy_create(mctx, &ectx); 938 if (isc_result != ISC_R_SUCCESS) { 939 t_info("isc_entropy_create failed %s\n", 940 isc_result_totext(isc_result)); 941 return(T_UNRESOLVED); 942 } 943 isc_result = isc_entropy_createfilesource(ectx, "randomfile"); 944 if (isc_result != ISC_R_SUCCESS) { 945 t_info("isc_entropy_create failed %s\n", 946 isc_result_totext(isc_result)); 947 return(T_UNRESOLVED); 948 } 949 isc_result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING); 950 if (isc_result != ISC_R_SUCCESS) { 951 t_info("dst_lib_init failed %s\n", 952 isc_result_totext(isc_result)); 953 return(T_UNRESOLVED); 954 } 955 956 if (!dst_algorithm_supported(DST_ALG_RSAMD5)) { 957 dst_lib_destroy(); 958 t_info("library built without crypto support\n"); 959 return (T_UNTESTED); 960 } 961 962 t_info("testing %s, %s, %s, %s, %s, %s\n", 963 datapath, sigpath, keyname, key, alg, exp_result); 964 t2_sigchk(datapath, sigpath, keyname, keyid, 965 algid, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, 966 mctx, exp_result, 967 &nfails, &nprobs); 968 969 dst_lib_destroy(); 970 971 isc_entropy_detach(&ectx); 972 973 isc_mem_destroy(&mctx); 974 975 result = T_UNRESOLVED; 976 if (nfails) 977 result = T_FAIL; 978 else if ((nfails == 0) && (nprobs == 0)) 979 result = T_PASS; 980 981 return(result); 982} 983 984static void 985t2(void) { 986 int result; 987 t_assert("dst", 2, T_REQUIRED, "%s", a2); 988 result = t_eval("dst_2_data", t2_vfy, 6); 989 t_result(result); 990} 991 992testspec_t T_testlist[] = { 993 { t1, "basic dst module verification" }, 994 { t2, "signature ineffability" }, 995 { NULL, NULL } 996}; 997 998