1 /* pkcs1v2.c - Test OAEP and PSS padding
2 * Copyright (C) 2011 Free Software Foundation, Inc.
3 *
4 * This file is part of Libgcrypt.
5 *
6 * Libgcrypt is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * Libgcrypt is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27
28 #ifdef _GCRYPT_IN_LIBGCRYPT
29 # include "../src/gcrypt-int.h"
30 #else
31 # include <gcrypt.h>
32 #endif
33
34
35 #define PGM "pkcs1v2"
36 #include "t-common.h"
37
38
39 static void
show_sexp(const char * prefix,gcry_sexp_t a)40 show_sexp (const char *prefix, gcry_sexp_t a)
41 {
42 char *buf;
43 size_t size;
44
45 if (prefix)
46 fputs (prefix, stderr);
47 size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
48 buf = gcry_xmalloc (size);
49
50 gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
51 fprintf (stderr, "%.*s", (int)size, buf);
52 gcry_free (buf);
53 }
54
55
56 /* Convert STRING consisting of hex characters into its binary
57 representation and return it as an allocated buffer. The valid
58 length of the buffer is returned at R_LENGTH. The string is
59 delimited by end of string. The function returns NULL on
60 error. */
61 static void *
data_from_hex(const char * string,size_t * r_length)62 data_from_hex (const char *string, size_t *r_length)
63 {
64 const char *s;
65 unsigned char *buffer;
66 size_t length;
67
68 buffer = gcry_xmalloc (strlen(string)/2+1);
69 length = 0;
70 for (s=string; *s; s +=2 )
71 {
72 if (!hexdigitp (s) || !hexdigitp (s+1))
73 die ("error parsing hex string `%s'\n", string);
74 ((unsigned char*)buffer)[length++] = xtoi_2 (s);
75 }
76 *r_length = length;
77 return buffer;
78 }
79
80
81 static int
extract_cmp_data(gcry_sexp_t sexp,const char * name,const char * expected,const char * description)82 extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected,
83 const char *description)
84 {
85 gcry_sexp_t l1;
86 const void *a;
87 size_t alen;
88 void *b;
89 size_t blen;
90 int rc = 0;
91
92 l1 = gcry_sexp_find_token (sexp, name, 0);
93 a = gcry_sexp_nth_data (l1, 1, &alen);
94 b = data_from_hex (expected, &blen);
95 if (!a)
96 {
97 info ("%s: parameter \"%s\" missing in key\n", description, name);
98 rc = 1;
99 }
100 else if ( alen != blen || memcmp (a, b, alen) )
101 {
102 info ("%s: parameter \"%s\" does not match expected value\n",
103 description, name);
104 rc = 1;
105 }
106 gcry_free (b);
107 gcry_sexp_release (l1);
108 return rc;
109 }
110
111
112 /* Check against the OAEP test vectors from
113 ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1d2-vec.zip . */
114 static void
check_oaep(void)115 check_oaep (void)
116 {
117 #include "pkcs1v2-oaep.h"
118 gpg_error_t err;
119 int tno, mno;
120
121 for (tno = 0; tno < DIM (tbl); tno++)
122 {
123 void *rsa_n, *rsa_e, *rsa_d;
124 size_t rsa_n_len, rsa_e_len, rsa_d_len;
125 gcry_sexp_t sec_key, pub_key;
126
127 if (verbose > 1)
128 info ("(%s)\n", tbl[tno].desc);
129
130 rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len);
131 rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len);
132 rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len);
133 err = gcry_sexp_build (&sec_key, NULL,
134 "(private-key (rsa (n %b)(e %b)(d %b)))",
135 (int)rsa_n_len, rsa_n,
136 (int)rsa_e_len, rsa_e,
137 (int)rsa_d_len, rsa_d);
138 if (err)
139 die ("constructing private key failed: %s\n", gpg_strerror (err));
140 err = gcry_sexp_build (&pub_key, NULL,
141 "(public-key (rsa (n %b)(e %b)))",
142 (int)rsa_n_len, rsa_n,
143 (int)rsa_e_len, rsa_e);
144 if (err)
145 die ("constructing public key failed: %s\n", gpg_strerror (err));
146 gcry_free (rsa_n);
147 gcry_free (rsa_e);
148 gcry_free (rsa_d);
149
150 for (mno = 0; mno < DIM (tbl[0].m); mno++)
151 {
152 void *mesg, *seed, *encr;
153 size_t mesg_len, seed_len, encr_len;
154 gcry_sexp_t plain, ciph;
155
156 if (verbose)
157 info ("running test: %s\n", tbl[tno].m[mno].desc);
158
159 mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len);
160 seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len);
161
162 err = gcry_sexp_build (&plain, NULL,
163 "(data (flags oaep)(hash-algo sha1)"
164 "(value %b)(random-override %b))",
165 (int)mesg_len, mesg,
166 (int)seed_len, seed);
167 if (err)
168 die ("constructing plain data failed: %s\n", gpg_strerror (err));
169 gcry_free (mesg);
170 gcry_free (seed);
171
172 err = gcry_pk_encrypt (&ciph, plain, pub_key);
173 if (err)
174 {
175 show_sexp ("plain:\n", ciph);
176 fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err));
177 }
178 else
179 {
180 if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr,
181 tbl[tno].m[mno].desc))
182 {
183 show_sexp ("encrypt result:\n", ciph);
184 fail ("mismatch in gcry_pk_encrypt\n");
185 }
186 gcry_sexp_release (ciph);
187 ciph = NULL;
188 }
189 gcry_sexp_release (plain);
190 plain = NULL;
191
192 /* Now test the decryption. */
193 seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len);
194 encr = data_from_hex (tbl[tno].m[mno].encr, &encr_len);
195
196 err = gcry_sexp_build (&ciph, NULL,
197 "(enc-val (flags oaep)(hash-algo sha1)"
198 "(random-override %b)"
199 "(rsa (a %b)))",
200 (int)seed_len, seed,
201 (int)encr_len, encr);
202 if (err)
203 die ("constructing cipher data failed: %s\n", gpg_strerror (err));
204 gcry_free (encr);
205 gcry_free (seed);
206
207 err = gcry_pk_decrypt (&plain, ciph, sec_key);
208 if (err)
209 {
210 show_sexp ("ciph:\n", ciph);
211 fail ("gcry_pk_decrypt failed: %s\n", gpg_strerror (err));
212 }
213 else
214 {
215 if (extract_cmp_data (plain, "value", tbl[tno].m[mno].mesg,
216 tbl[tno].m[mno].desc))
217 {
218 show_sexp ("decrypt result:\n", plain);
219 fail ("mismatch in gcry_pk_decrypt\n");
220 }
221 gcry_sexp_release (plain);
222 plain = NULL;
223 }
224 gcry_sexp_release (ciph);
225 ciph = NULL;
226 }
227
228 gcry_sexp_release (sec_key);
229 gcry_sexp_release (pub_key);
230 }
231 }
232
233
234 /* Check against the PSS test vectors from
235 ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1d2-vec.zip . */
236 static void
check_pss(void)237 check_pss (void)
238 {
239 #include "pkcs1v2-pss.h"
240 gpg_error_t err;
241 int tno, mno;
242
243 for (tno = 0; tno < DIM (tbl); tno++)
244 {
245 void *rsa_n, *rsa_e, *rsa_d;
246 size_t rsa_n_len, rsa_e_len, rsa_d_len;
247 gcry_sexp_t sec_key, pub_key;
248
249 if (verbose > 1)
250 info ("(%s)\n", tbl[tno].desc);
251
252 rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len);
253 rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len);
254 rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len);
255 err = gcry_sexp_build (&sec_key, NULL,
256 "(private-key (rsa (n %b)(e %b)(d %b)))",
257 (int)rsa_n_len, rsa_n,
258 (int)rsa_e_len, rsa_e,
259 (int)rsa_d_len, rsa_d);
260 if (err)
261 die ("constructing private key failed: %s\n", gpg_strerror (err));
262 err = gcry_sexp_build (&pub_key, NULL,
263 "(public-key (rsa (n %b)(e %b)))",
264 (int)rsa_n_len, rsa_n,
265 (int)rsa_e_len, rsa_e);
266 if (err)
267 die ("constructing public key failed: %s\n", gpg_strerror (err));
268 gcry_free (rsa_n);
269 gcry_free (rsa_e);
270 gcry_free (rsa_d);
271
272 for (mno = 0; mno < DIM (tbl[0].m); mno++)
273 {
274 void *mesg, *salt, *sign;
275 size_t mesg_len, salt_len, sign_len;
276 gcry_sexp_t sigtmpl, sig;
277 char mhash[20];
278
279 if (verbose)
280 info ("running test: %s\n", tbl[tno].m[mno].desc);
281
282 mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len);
283 salt = data_from_hex (tbl[tno].m[mno].salt, &salt_len);
284
285 gcry_md_hash_buffer (GCRY_MD_SHA1, mhash, mesg, mesg_len);
286 err = gcry_sexp_build (&sigtmpl, NULL,
287 "(data (flags pss)"
288 "(hash sha1 %b)"
289 "(random-override %b))",
290 20, mhash,
291 (int)salt_len, salt);
292 if (err)
293 die ("constructing sig template failed: %s\n", gpg_strerror (err));
294 gcry_free (mesg);
295 gcry_free (salt);
296
297 err = gcry_pk_sign (&sig, sigtmpl, sec_key);
298 if (err)
299 {
300 show_sexp ("sigtmpl:\n", sigtmpl);
301 fail ("gcry_pk_sign failed: %s\n", gpg_strerror (err));
302 }
303 else
304 {
305 if (extract_cmp_data (sig, "s", tbl[tno].m[mno].sign,
306 tbl[tno].m[mno].desc))
307 {
308 show_sexp ("sign result:\n", sig);
309 fail ("mismatch in gcry_pk_sign\n");
310 }
311 gcry_sexp_release (sig);
312 sig = NULL;
313 }
314 gcry_sexp_release (sigtmpl);
315 sigtmpl = NULL;
316
317 /* Now test the verification. */
318 salt = data_from_hex (tbl[tno].m[mno].salt, &salt_len);
319 sign = data_from_hex (tbl[tno].m[mno].sign, &sign_len);
320
321 err = gcry_sexp_build (&sig, NULL,
322 "(sig-val(rsa(s %b)))",
323 (int)sign_len, sign);
324 if (err)
325 die ("constructing verify data failed: %s\n", gpg_strerror (err));
326 err = gcry_sexp_build (&sigtmpl, NULL,
327 "(data (flags pss)"
328 "(hash sha1 %b)"
329 "(random-override %b))",
330 20, mhash,
331 (int)salt_len, salt);
332 if (err)
333 die ("constructing verify tmpl failed: %s\n", gpg_strerror (err));
334 gcry_free (sign);
335 gcry_free (salt);
336
337 err = gcry_pk_verify (sig, sigtmpl, pub_key);
338 if (err)
339 {
340 show_sexp ("sig:\n", sig);
341 show_sexp ("sigtmpl:\n", sigtmpl);
342 fail ("gcry_pk_verify failed: %s\n", gpg_strerror (err));
343 }
344 gcry_sexp_release (sig);
345 sig = NULL;
346 gcry_sexp_release (sigtmpl);
347 sigtmpl = NULL;
348 }
349
350 gcry_sexp_release (sec_key);
351 gcry_sexp_release (pub_key);
352 }
353 }
354
355
356 /* Check against PKCS#1 v1.5 encryption test vectors as found at
357 ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15crypt-vectors.txt . */
358 static void
check_v15crypt(void)359 check_v15crypt (void)
360 {
361 #include "pkcs1v2-v15c.h"
362 gpg_error_t err;
363 int tno, mno;
364
365 for (tno = 0; tno < DIM (tbl); tno++)
366 {
367 void *rsa_n, *rsa_e, *rsa_d;
368 size_t rsa_n_len, rsa_e_len, rsa_d_len;
369 gcry_sexp_t sec_key, pub_key;
370
371 if (verbose > 1)
372 info ("(%s)\n", tbl[tno].desc);
373
374 rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len);
375 rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len);
376 rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len);
377 err = gcry_sexp_build (&sec_key, NULL,
378 "(private-key (rsa (n %b)(e %b)(d %b)))",
379 (int)rsa_n_len, rsa_n,
380 (int)rsa_e_len, rsa_e,
381 (int)rsa_d_len, rsa_d);
382 if (err)
383 die ("constructing private key failed: %s\n", gpg_strerror (err));
384 err = gcry_sexp_build (&pub_key, NULL,
385 "(public-key (rsa (n %b)(e %b)))",
386 (int)rsa_n_len, rsa_n,
387 (int)rsa_e_len, rsa_e);
388 if (err)
389 die ("constructing public key failed: %s\n", gpg_strerror (err));
390 gcry_free (rsa_n);
391 gcry_free (rsa_e);
392 gcry_free (rsa_d);
393
394 for (mno = 0; mno < DIM (tbl[0].m); mno++)
395 {
396 void *mesg, *seed, *encr;
397 size_t mesg_len, seed_len, encr_len;
398 gcry_sexp_t plain, ciph;
399
400 if (verbose)
401 info ("running test: %s\n", tbl[tno].m[mno].desc);
402
403 mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len);
404 seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len);
405
406 err = gcry_sexp_build (&plain, NULL,
407 "(data (flags pkcs1)(hash-algo sha1)"
408 "(value %b)(random-override %b))",
409 (int)mesg_len, mesg,
410 (int)seed_len, seed);
411 if (err)
412 die ("constructing plain data failed: %s\n", gpg_strerror (err));
413 gcry_free (mesg);
414 gcry_free (seed);
415
416 err = gcry_pk_encrypt (&ciph, plain, pub_key);
417 if (err)
418 {
419 show_sexp ("plain:\n", ciph);
420 fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err));
421 }
422 else
423 {
424 if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr,
425 tbl[tno].m[mno].desc))
426 {
427 show_sexp ("encrypt result:\n", ciph);
428 fail ("mismatch in gcry_pk_encrypt\n");
429 }
430 gcry_sexp_release (ciph);
431 ciph = NULL;
432 }
433 gcry_sexp_release (plain);
434 plain = NULL;
435
436 /* Now test the decryption. */
437 seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len);
438 encr = data_from_hex (tbl[tno].m[mno].encr, &encr_len);
439
440 err = gcry_sexp_build (&ciph, NULL,
441 "(enc-val (flags pkcs1)(hash-algo sha1)"
442 "(random-override %b)"
443 "(rsa (a %b)))",
444 (int)seed_len, seed,
445 (int)encr_len, encr);
446 if (err)
447 die ("constructing cipher data failed: %s\n", gpg_strerror (err));
448 gcry_free (encr);
449 gcry_free (seed);
450
451 err = gcry_pk_decrypt (&plain, ciph, sec_key);
452 if (err)
453 {
454 show_sexp ("ciph:\n", ciph);
455 fail ("gcry_pk_decrypt failed: %s\n", gpg_strerror (err));
456 }
457 else
458 {
459 if (extract_cmp_data (plain, "value", tbl[tno].m[mno].mesg,
460 tbl[tno].m[mno].desc))
461 {
462 show_sexp ("decrypt result:\n", plain);
463 fail ("mismatch in gcry_pk_decrypt\n");
464 }
465 gcry_sexp_release (plain);
466 plain = NULL;
467 }
468 gcry_sexp_release (ciph);
469 ciph = NULL;
470 }
471
472 gcry_sexp_release (sec_key);
473 gcry_sexp_release (pub_key);
474 }
475 }
476
477
478 /* Check against PKCS#1 v1.5 signature test vectors as found at
479 ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt . */
480 static void
check_v15sign(void)481 check_v15sign (void)
482 {
483 #include "pkcs1v2-v15s.h"
484 gpg_error_t err;
485 int tno, mno;
486
487 for (tno = 0; tno < DIM (tbl); tno++)
488 {
489 void *rsa_n, *rsa_e, *rsa_d;
490 size_t rsa_n_len, rsa_e_len, rsa_d_len;
491 gcry_sexp_t sec_key, pub_key;
492
493 if (verbose > 1)
494 info ("(%s)\n", tbl[tno].desc);
495
496 rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len);
497 rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len);
498 rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len);
499 err = gcry_sexp_build (&sec_key, NULL,
500 "(private-key (rsa (n %b)(e %b)(d %b)))",
501 (int)rsa_n_len, rsa_n,
502 (int)rsa_e_len, rsa_e,
503 (int)rsa_d_len, rsa_d);
504 if (err)
505 die ("constructing private key failed: %s\n", gpg_strerror (err));
506 err = gcry_sexp_build (&pub_key, NULL,
507 "(public-key (rsa (n %b)(e %b)))",
508 (int)rsa_n_len, rsa_n,
509 (int)rsa_e_len, rsa_e);
510 if (err)
511 die ("constructing public key failed: %s\n", gpg_strerror (err));
512 gcry_free (rsa_n);
513 gcry_free (rsa_e);
514 gcry_free (rsa_d);
515
516 for (mno = 0; mno < DIM (tbl[0].m); mno++)
517 {
518 void *mesg, *sign;
519 size_t mesg_len, sign_len;
520 gcry_sexp_t sigtmpl, sig;
521 char mhash[20];
522
523 if (verbose)
524 info ("running test: %s\n", tbl[tno].m[mno].desc);
525
526 mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len);
527
528 gcry_md_hash_buffer (GCRY_MD_SHA1, mhash, mesg, mesg_len);
529 err = gcry_sexp_build (&sigtmpl, NULL,
530 "(data (flags pkcs1)"
531 "(hash sha1 %b))",
532 20, mhash);
533 if (err)
534 die ("constructing sig template failed: %s\n", gpg_strerror (err));
535 gcry_free (mesg);
536
537 err = gcry_pk_sign (&sig, sigtmpl, sec_key);
538 if (err)
539 {
540 show_sexp ("sigtmpl:\n", sigtmpl);
541 fail ("gcry_pk_sign failed: %s\n", gpg_strerror (err));
542 }
543 else
544 {
545 if (extract_cmp_data (sig, "s", tbl[tno].m[mno].sign,
546 tbl[tno].m[mno].desc))
547 {
548 show_sexp ("sign result:\n", sig);
549 fail ("mismatch in gcry_pk_sign\n");
550 }
551 gcry_sexp_release (sig);
552 sig = NULL;
553 }
554 gcry_sexp_release (sigtmpl);
555 sigtmpl = NULL;
556
557 /* Now test the verification. */
558 sign = data_from_hex (tbl[tno].m[mno].sign, &sign_len);
559
560 err = gcry_sexp_build (&sig, NULL,
561 "(sig-val(rsa(s %b)))",
562 (int)sign_len, sign);
563 if (err)
564 die ("constructing verify data failed: %s\n", gpg_strerror (err));
565 err = gcry_sexp_build (&sigtmpl, NULL,
566 "(data (flags pkcs1)"
567 "(hash sha1 %b))",
568 20, mhash);
569 if (err)
570 die ("constructing verify tmpl failed: %s\n", gpg_strerror (err));
571 gcry_free (sign);
572
573 err = gcry_pk_verify (sig, sigtmpl, pub_key);
574 if (err)
575 {
576 show_sexp ("sig:\n", sig);
577 show_sexp ("sigtmpl:\n", sigtmpl);
578 fail ("gcry_pk_verify failed: %s\n", gpg_strerror (err));
579 }
580 gcry_sexp_release (sig);
581 sig = NULL;
582 gcry_sexp_release (sigtmpl);
583 sigtmpl = NULL;
584 }
585
586 gcry_sexp_release (sec_key);
587 gcry_sexp_release (pub_key);
588 }
589 }
590
591
592 int
main(int argc,char ** argv)593 main (int argc, char **argv)
594 {
595 int last_argc = -1;
596 int run_oaep = 0;
597 int run_pss = 0;
598 int run_v15c = 0;
599 int run_v15s = 0;
600
601 if (argc)
602 { argc--; argv++; }
603
604 while (argc && last_argc != argc )
605 {
606 last_argc = argc;
607 if (!strcmp (*argv, "--"))
608 {
609 argc--; argv++;
610 break;
611 }
612 else if (!strcmp (*argv, "--verbose"))
613 {
614 verbose++;
615 argc--; argv++;
616 }
617 else if (!strcmp (*argv, "--debug"))
618 {
619 verbose = 2;
620 debug = 1;
621 argc--; argv++;
622 }
623 else if (!strcmp (*argv, "--die"))
624 {
625 die_on_error = 1;
626 argc--; argv++;
627 }
628 else if (!strcmp (*argv, "--oaep"))
629 {
630 run_oaep = 1;
631 argc--; argv++;
632 }
633 else if (!strcmp (*argv, "--pss"))
634 {
635 run_pss = 1;
636 argc--; argv++;
637 }
638 else if (!strcmp (*argv, "--v15c"))
639 {
640 run_v15c = 1;
641 argc--; argv++;
642 }
643 else if (!strcmp (*argv, "--v15s"))
644 {
645 run_v15s = 1;
646 argc--; argv++;
647 }
648 }
649
650 if (!run_oaep && !run_pss && !run_v15c && !run_v15s)
651 run_oaep = run_pss = run_v15c = run_v15s = 1;
652
653 xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose));
654 xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
655 if (!gcry_check_version ("1.5.0"))
656 die ("version mismatch\n");
657 xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
658 if (debug)
659 xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
660 /* No valuable keys are create, so we can speed up our RNG. */
661 xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
662
663 if (run_oaep)
664 check_oaep ();
665 if (run_pss)
666 check_pss ();
667 if (run_v15c)
668 check_v15crypt ();
669 if (run_v15s)
670 check_v15sign ();
671
672 if (verbose)
673 fprintf (stderr, "\nAll tests completed. Errors: %i\n", error_count);
674
675 return error_count ? 1 : 0;
676 }
677