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