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