]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - crypto/openssl/fips/fips_test_suite.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / crypto / openssl / fips / fips_test_suite.c
1 /* ====================================================================
2  * Copyright (c) 2003 The OpenSSL Project.  All rights reserved.
3  *
4  *
5  * This command is intended as a test driver for the FIPS-140 testing
6  * lab performing FIPS-140 validation.  It demonstrates the use of the
7  * OpenSSL library ito perform a variety of common cryptographic
8  * functions.  A power-up self test is demonstrated by deliberately
9  * pointing to an invalid executable hash
10  *
11  * Contributed by Steve Marquess.
12  *
13  */
14 #include <stdio.h>
15 #include <assert.h>
16 #include <ctype.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <openssl/aes.h>
20 #include <openssl/des.h>
21 #include <openssl/hmac.h>
22 #include <openssl/err.h>
23
24 #include <openssl/bn.h>
25 #include <openssl/rand.h>
26 #include <openssl/sha.h>
27
28
29 #ifndef OPENSSL_FIPS
30 int main(int argc, char *argv[])
31     {
32     printf("No FIPS support\n");
33     return(0);
34     }
35 #else
36
37 #include <openssl/rsa.h>
38 #include <openssl/dsa.h>
39 #include <openssl/dh.h>
40
41 #include <openssl/fips.h>
42 #include "fips_utl.h"
43
44 /* AES: encrypt and decrypt known plaintext, verify result matches original plaintext
45 */
46 static int FIPS_aes_test(void)
47         {
48         int ret = 0;
49         unsigned char pltmp[16];
50         unsigned char citmp[16];
51         unsigned char key[16] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
52         unsigned char plaintext[16] = "etaonrishdlcu";
53         EVP_CIPHER_CTX ctx;
54         EVP_CIPHER_CTX_init(&ctx);
55         if (EVP_CipherInit_ex(&ctx, EVP_aes_128_ecb(),NULL, key, NULL, 1) <= 0)
56                 goto err;
57         EVP_Cipher(&ctx, citmp, plaintext, 16);
58         if (EVP_CipherInit_ex(&ctx, EVP_aes_128_ecb(),NULL, key, NULL, 0) <= 0)
59                 goto err;
60         EVP_Cipher(&ctx, pltmp, citmp, 16);
61         if (memcmp(pltmp, plaintext, 16))
62                 goto err;
63         ret = 1;
64         err:
65         EVP_CIPHER_CTX_cleanup(&ctx);
66         return ret;
67         }
68
69 static int FIPS_des3_test(void)
70         {
71         int ret = 0;
72         unsigned char pltmp[8];
73         unsigned char citmp[8];
74         unsigned char key[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
75                               19,20,21,22,23,24};
76         unsigned char plaintext[] = { 'e', 't', 'a', 'o', 'n', 'r', 'i', 's' };
77         EVP_CIPHER_CTX ctx;
78         EVP_CIPHER_CTX_init(&ctx);
79         if (EVP_CipherInit_ex(&ctx, EVP_des_ede3_ecb(),NULL, key, NULL, 1) <= 0)
80                 goto err;
81         EVP_Cipher(&ctx, citmp, plaintext, 8);
82         if (EVP_CipherInit_ex(&ctx, EVP_des_ede3_ecb(),NULL, key, NULL, 0) <= 0)
83                 goto err;
84         EVP_Cipher(&ctx, pltmp, citmp, 8);
85         if (memcmp(pltmp, plaintext, 8))
86                 goto err;
87         ret = 1;
88         err:
89         EVP_CIPHER_CTX_cleanup(&ctx);
90         return ret;
91         }
92
93 /*
94  * DSA: generate keys and sign, verify input plaintext.
95  */
96 static int FIPS_dsa_test(int bad)
97     {
98     DSA *dsa = NULL;
99     EVP_PKEY pk;
100     unsigned char dgst[] = "etaonrishdlc";
101     unsigned char buf[60];
102     unsigned int slen;
103     int r = 0;
104     EVP_MD_CTX mctx;
105
106     ERR_clear_error();
107     EVP_MD_CTX_init(&mctx);
108     dsa = FIPS_dsa_new();
109     if (!dsa)
110         goto end;
111     if (!DSA_generate_parameters_ex(dsa, 1024,NULL,0,NULL,NULL,NULL))
112         goto end;
113     if (!DSA_generate_key(dsa))
114         goto end;
115     if (bad)
116             BN_add_word(dsa->pub_key, 1);
117
118     pk.type = EVP_PKEY_DSA;
119     pk.pkey.dsa = dsa;
120
121     if (!EVP_SignInit_ex(&mctx, EVP_dss1(), NULL))
122         goto end;
123     if (!EVP_SignUpdate(&mctx, dgst, sizeof(dgst) - 1))
124         goto end;
125     if (!EVP_SignFinal(&mctx, buf, &slen, &pk))
126         goto end;
127
128     if (!EVP_VerifyInit_ex(&mctx, EVP_dss1(), NULL))
129         goto end;
130     if (!EVP_VerifyUpdate(&mctx, dgst, sizeof(dgst) - 1))
131         goto end;
132     r = EVP_VerifyFinal(&mctx, buf, slen, &pk);
133     end:
134     EVP_MD_CTX_cleanup(&mctx);
135     if (dsa)
136           FIPS_dsa_free(dsa);
137     if (r != 1)
138         return 0;
139     return 1;
140     }
141
142 /*
143  * RSA: generate keys and sign, verify input plaintext.
144  */
145 static int FIPS_rsa_test(int bad)
146     {
147     RSA *key;
148     unsigned char input_ptext[] = "etaonrishdlc";
149     unsigned char buf[256];
150     unsigned int slen;
151     BIGNUM *bn;
152     EVP_MD_CTX mctx;
153     EVP_PKEY pk;
154     int r = 0;
155
156     ERR_clear_error();
157     EVP_MD_CTX_init(&mctx);
158     key = FIPS_rsa_new();
159     bn = BN_new();
160     if (!key || !bn)
161         return 0;
162     BN_set_word(bn, 65537);
163     if (!RSA_generate_key_ex(key, 1024,bn,NULL))
164         return 0;
165     BN_free(bn);
166     if (bad)
167             BN_add_word(key->n, 1);
168
169     pk.type = EVP_PKEY_RSA;
170     pk.pkey.rsa = key;
171
172     if (!EVP_SignInit_ex(&mctx, EVP_sha1(), NULL))
173         goto end;
174     if (!EVP_SignUpdate(&mctx, input_ptext, sizeof(input_ptext) - 1))
175         goto end;
176     if (!EVP_SignFinal(&mctx, buf, &slen, &pk))
177         goto end;
178
179     if (!EVP_VerifyInit_ex(&mctx, EVP_sha1(), NULL))
180         goto end;
181     if (!EVP_VerifyUpdate(&mctx, input_ptext, sizeof(input_ptext) - 1))
182         goto end;
183     r = EVP_VerifyFinal(&mctx, buf, slen, &pk);
184     end:
185     EVP_MD_CTX_cleanup(&mctx);
186     if (key)
187           FIPS_rsa_free(key);
188     if (r != 1)
189         return 0;
190     return 1;
191     }
192
193 /* SHA1: generate hash of known digest value and compare to known
194    precomputed correct hash
195 */
196 static int FIPS_sha1_test()
197     {
198     unsigned char digest[SHA_DIGEST_LENGTH] =
199         { 0x11, 0xf1, 0x9a, 0x3a, 0xec, 0x1a, 0x1e, 0x8e, 0x65, 0xd4, 0x9a, 0x38, 0x0c, 0x8b, 0x1e, 0x2c, 0xe8, 0xb3, 0xc5, 0x18 };
200     unsigned char str[] = "etaonrishd";
201
202     unsigned char md[SHA_DIGEST_LENGTH];
203
204     ERR_clear_error();
205     if (!EVP_Digest(str,sizeof(str) - 1,md, NULL, EVP_sha1(), NULL)) return 0;
206     if (memcmp(md,digest,sizeof(md)))
207         return 0;
208     return 1;
209     }
210
211 /* SHA256: generate hash of known digest value and compare to known
212    precomputed correct hash
213 */
214 static int FIPS_sha256_test()
215     {
216     unsigned char digest[SHA256_DIGEST_LENGTH] =
217         {0xf5, 0x53, 0xcd, 0xb8, 0xcf, 0x1, 0xee, 0x17, 0x9b, 0x93, 0xc9, 0x68, 0xc0, 0xea, 0x40, 0x91,
218          0x6, 0xec, 0x8e, 0x11, 0x96, 0xc8, 0x5d, 0x1c, 0xaf, 0x64, 0x22, 0xe6, 0x50, 0x4f, 0x47, 0x57};
219     unsigned char str[] = "etaonrishd";
220
221     unsigned char md[SHA256_DIGEST_LENGTH];
222
223     ERR_clear_error();
224     if (!EVP_Digest(str,sizeof(str) - 1,md, NULL, EVP_sha256(), NULL)) return 0;
225     if (memcmp(md,digest,sizeof(md)))
226         return 0;
227     return 1;
228     }
229
230 /* SHA512: generate hash of known digest value and compare to known
231    precomputed correct hash
232 */
233 static int FIPS_sha512_test()
234     {
235     unsigned char digest[SHA512_DIGEST_LENGTH] =
236         {0x99, 0xc9, 0xe9, 0x5b, 0x88, 0xd4, 0x78, 0x88, 0xdf, 0x88, 0x5f, 0x94, 0x71, 0x64, 0x28, 0xca,
237          0x16, 0x1f, 0x3d, 0xf4, 0x1f, 0xf3, 0x0f, 0xc5, 0x03, 0x99, 0xb2, 0xd0, 0xe7, 0x0b, 0x94, 0x4a,
238          0x45, 0xd2, 0x6c, 0x4f, 0x20, 0x06, 0xef, 0x71, 0xa9, 0x25, 0x7f, 0x24, 0xb1, 0xd9, 0x40, 0x22,
239          0x49, 0x54, 0x10, 0xc2, 0x22, 0x9d, 0x27, 0xfe, 0xbd, 0xd6, 0xd6, 0xeb, 0x2d, 0x42, 0x1d, 0xa3};
240     unsigned char str[] = "etaonrishd";
241
242     unsigned char md[SHA512_DIGEST_LENGTH];
243
244     ERR_clear_error();
245     if (!EVP_Digest(str,sizeof(str) - 1,md, NULL, EVP_sha512(), NULL)) return 0;
246     if (memcmp(md,digest,sizeof(md)))
247         return 0;
248     return 1;
249     }
250
251 /* HMAC-SHA1: generate hash of known digest value and compare to known
252    precomputed correct hash
253 */
254 static int FIPS_hmac_sha1_test()
255     {
256     unsigned char key[] = "etaonrishd";
257     unsigned char iv[] = "Sample text";
258     unsigned char kaval[EVP_MAX_MD_SIZE] =
259         {0x73, 0xf7, 0xa0, 0x48, 0xf8, 0x94, 0xed, 0xdd, 0x0a, 0xea, 0xea, 0x56, 0x1b, 0x61, 0x2e, 0x70,
260          0xb2, 0xfb, 0xec, 0xc6};
261
262     unsigned char out[EVP_MAX_MD_SIZE];
263     unsigned int outlen;
264
265     ERR_clear_error();
266     if (!HMAC(EVP_sha1(),key,sizeof(key)-1,iv,sizeof(iv)-1,out,&outlen)) return 0;
267     if (memcmp(out,kaval,outlen))
268         return 0;
269     return 1;
270     }
271
272 /* HMAC-SHA224: generate hash of known digest value and compare to known
273    precomputed correct hash
274 */
275 static int FIPS_hmac_sha224_test()
276     {
277     unsigned char key[] = "etaonrishd";
278     unsigned char iv[] = "Sample text";
279     unsigned char kaval[EVP_MAX_MD_SIZE] =
280         {0x75, 0x58, 0xd5, 0xbd, 0x55, 0x6d, 0x87, 0x0f, 0x75, 0xff, 0xbe, 0x1c, 0xb2, 0xf0, 0x20, 0x35,
281          0xe5, 0x62, 0x49, 0xb6, 0x94, 0xb9, 0xfc, 0x65, 0x34, 0x33, 0x3a, 0x19};
282
283     unsigned char out[EVP_MAX_MD_SIZE];
284     unsigned int outlen;
285
286     ERR_clear_error();
287     if (!HMAC(EVP_sha224(),key,sizeof(key)-1,iv,sizeof(iv)-1,out,&outlen)) return 0;
288     if (memcmp(out,kaval,outlen))
289         return 0;
290     return 1;
291     }
292
293 /* HMAC-SHA256: generate hash of known digest value and compare to known
294    precomputed correct hash
295 */
296 static int FIPS_hmac_sha256_test()
297     {
298     unsigned char key[] = "etaonrishd";
299     unsigned char iv[] = "Sample text";
300     unsigned char kaval[EVP_MAX_MD_SIZE] =
301         {0xe9, 0x17, 0xc1, 0x7b, 0x4c, 0x6b, 0x77, 0xda, 0xd2, 0x30, 0x36, 0x02, 0xf5, 0x72, 0x33, 0x87,
302          0x9f, 0xc6, 0x6e, 0x7b, 0x7e, 0xa8, 0xea, 0xaa, 0x9f, 0xba, 0xee, 0x51, 0xff, 0xda, 0x24, 0xf4};
303
304     unsigned char out[EVP_MAX_MD_SIZE];
305     unsigned int outlen;
306
307     ERR_clear_error();
308     if (!HMAC(EVP_sha256(),key,sizeof(key)-1,iv,sizeof(iv)-1,out,&outlen)) return 0;
309     if (memcmp(out,kaval,outlen))
310         return 0;
311     return 1;
312     }
313
314 /* HMAC-SHA384: generate hash of known digest value and compare to known
315    precomputed correct hash
316 */
317 static int FIPS_hmac_sha384_test()
318     {
319     unsigned char key[] = "etaonrishd";
320     unsigned char iv[] = "Sample text";
321     unsigned char kaval[EVP_MAX_MD_SIZE] =
322         {0xb2, 0x9d, 0x40, 0x58, 0x32, 0xc4, 0xe3, 0x31, 0xb6, 0x63, 0x08, 0x26, 0x99, 0xef, 0x3b, 0x10,
323          0xe2, 0xdf, 0xf8, 0xff, 0xc6, 0xe1, 0x03, 0x29, 0x81, 0x2a, 0x1b, 0xac, 0xb0, 0x07, 0x39, 0x08,
324          0xf3, 0x91, 0x35, 0x11, 0x76, 0xd6, 0x4c, 0x20, 0xfb, 0x4d, 0xc3, 0xf3, 0xb8, 0x9b, 0x88, 0x1c};
325
326     unsigned char out[EVP_MAX_MD_SIZE];
327     unsigned int outlen;
328
329     ERR_clear_error();
330     if (!HMAC(EVP_sha384(),key,sizeof(key)-1,iv,sizeof(iv)-1,out,&outlen)) return 0;
331     if (memcmp(out,kaval,outlen))
332         return 0;
333     return 1;
334     }
335
336 /* HMAC-SHA512: generate hash of known digest value and compare to known
337    precomputed correct hash
338 */
339 static int FIPS_hmac_sha512_test()
340     {
341     unsigned char key[] = "etaonrishd";
342     unsigned char iv[] = "Sample text";
343     unsigned char kaval[EVP_MAX_MD_SIZE] =
344         {0xcd, 0x3e, 0xb9, 0x51, 0xb8, 0xbc, 0x7f, 0x9a, 0x23, 0xaf, 0xf3, 0x77, 0x59, 0x85, 0xa9, 0xe6,
345          0xf7, 0xd1, 0x51, 0x96, 0x17, 0xe0, 0x92, 0xd8, 0xa6, 0x3b, 0xc1, 0xad, 0x7e, 0x24, 0xca, 0xb1,
346          0xd7, 0x79, 0x0a, 0xa5, 0xea, 0x2c, 0x02, 0x58, 0x0b, 0xa6, 0x52, 0x6b, 0x61, 0x7f, 0xeb, 0x9c,
347          0x47, 0x86, 0x5d, 0x74, 0x2b, 0x88, 0xdf, 0xee, 0x46, 0x69, 0x96, 0x3d, 0xa6, 0xd9, 0x2a, 0x53};
348
349     unsigned char out[EVP_MAX_MD_SIZE];
350     unsigned int outlen;
351
352     ERR_clear_error();
353     if (!HMAC(EVP_sha512(),key,sizeof(key)-1,iv,sizeof(iv)-1,out,&outlen)) return 0;
354     if (memcmp(out,kaval,outlen))
355         return 0;
356     return 1;
357     }
358
359
360 /* DH: generate shared parameters
361 */
362 static int dh_test()
363     {
364     DH *dh;
365     ERR_clear_error();
366     dh = FIPS_dh_new();
367     if (!dh)
368         return 0;
369     if (!DH_generate_parameters_ex(dh, 1024, 2, NULL))
370         return 0;
371     FIPS_dh_free(dh);
372     return 1;
373     }
374
375 /* Zeroize
376 */
377 static int Zeroize()
378     {
379     RSA *key;
380     BIGNUM *bn;
381     unsigned char userkey[16] = 
382         { 0x48, 0x50, 0xf0, 0xa3, 0x3a, 0xed, 0xd3, 0xaf, 0x6e, 0x47, 0x7f, 0x83, 0x02, 0xb1, 0x09, 0x68 };
383     size_t i;
384     int n;
385
386     key = FIPS_rsa_new();
387     bn = BN_new();
388     if (!key || !bn)
389         return 0;
390     BN_set_word(bn, 65537);
391     if (!RSA_generate_key_ex(key, 1024,bn,NULL))
392         return 0;
393     BN_free(bn);
394     
395     n = BN_num_bytes(key->d);
396     printf(" Generated %d byte RSA private key\n", n);
397     printf("\tBN key before overwriting:\n");
398     do_bn_print(stdout, key->d);
399     BN_rand(key->d,n*8,-1,0);
400     printf("\tBN key after overwriting:\n");
401     do_bn_print(stdout, key->d);
402
403     printf("\tchar buffer key before overwriting: \n\t\t");
404     for(i = 0; i < sizeof(userkey); i++) printf("%02x", userkey[i]);
405         printf("\n");
406     RAND_bytes(userkey, sizeof userkey);
407     printf("\tchar buffer key after overwriting: \n\t\t");
408     for(i = 0; i < sizeof(userkey); i++) printf("%02x", userkey[i]);
409         printf("\n");
410
411     return 1;
412     }
413
414 static int Error;
415 static const char * Fail(const char *msg)
416     {
417     do_print_errors();
418     Error++;
419     return msg; 
420     }
421
422 static void test_msg(const char *msg, int result)
423         {
424         printf("%s...%s\n", msg, result ? "successful" : Fail("Failed!"));
425         }
426
427 int main(int argc,char **argv)
428     {
429
430     int do_corrupt_rsa_keygen = 0, do_corrupt_dsa_keygen = 0;
431     int bad_rsa = 0, bad_dsa = 0;
432     int do_rng_stick = 0;
433     int no_exit = 0;
434
435     printf("\tFIPS-mode test application\n\n");
436
437     /* Load entropy from external file, if any */
438     RAND_load_file(".rnd", 1024);
439
440     if (argv[1]) {
441         /* Corrupted KAT tests */
442         if (!strcmp(argv[1], "aes")) {
443             FIPS_corrupt_aes();
444             printf("AES encryption/decryption with corrupted KAT...\n");
445         } else if (!strcmp(argv[1], "des")) {
446             FIPS_corrupt_des();
447             printf("DES3-ECB encryption/decryption with corrupted KAT...\n");
448         } else if (!strcmp(argv[1], "dsa")) {
449             FIPS_corrupt_dsa();
450             printf("DSA key generation and signature validation with corrupted KAT...\n");
451         } else if (!strcmp(argv[1], "rsa")) {
452             FIPS_corrupt_rsa();
453             printf("RSA key generation and signature validation with corrupted KAT...\n");
454         } else if (!strcmp(argv[1], "rsakey")) {
455             printf("RSA key generation and signature validation with corrupted key...\n");
456             bad_rsa = 1;
457             no_exit = 1;
458         } else if (!strcmp(argv[1], "rsakeygen")) {
459             do_corrupt_rsa_keygen = 1;
460             no_exit = 1;
461             printf("RSA key generation and signature validation with corrupted keygen...\n");
462         } else if (!strcmp(argv[1], "dsakey")) {
463             printf("DSA key generation and signature validation with corrupted key...\n");
464             bad_dsa = 1;
465             no_exit = 1;
466         } else if (!strcmp(argv[1], "dsakeygen")) {
467             do_corrupt_dsa_keygen = 1;
468             no_exit = 1;
469             printf("DSA key generation and signature validation with corrupted keygen...\n");
470         } else if (!strcmp(argv[1], "sha1")) {
471             FIPS_corrupt_sha1();
472             printf("SHA-1 hash with corrupted KAT...\n");
473         } else if (!strcmp(argv[1], "rng")) {
474             FIPS_corrupt_rng();
475         } else if (!strcmp(argv[1], "rngstick")) {
476             do_rng_stick = 1;
477             no_exit = 1;
478             printf("RNG test with stuck continuous test...\n");
479         } else {
480             printf("Bad argument \"%s\"\n", argv[1]);
481             exit(1);
482         }
483         if (!no_exit) {
484                 if (!FIPS_mode_set(1)) {
485                     do_print_errors();
486                     printf("Power-up self test failed\n");
487                     exit(1);
488                 }
489                 printf("Power-up self test successful\n");
490                 exit(0);
491         }
492     }
493
494     /* Non-Approved cryptographic operation
495     */
496     printf("1. Non-Approved cryptographic operation test...\n");
497     test_msg("\ta. Included algorithm (D-H)...", dh_test());
498
499     /* Power-up self test
500     */
501     ERR_clear_error();
502     test_msg("2. Automatic power-up self test", FIPS_mode_set(1));
503     if (!FIPS_mode())
504         exit(1);
505     if (do_corrupt_dsa_keygen)
506             FIPS_corrupt_dsa_keygen();
507     if (do_corrupt_rsa_keygen)
508             FIPS_corrupt_rsa_keygen();
509     if (do_rng_stick)
510             FIPS_rng_stick();
511
512     /* AES encryption/decryption
513     */
514     test_msg("3. AES encryption/decryption", FIPS_aes_test());
515
516     /* RSA key generation and encryption/decryption
517     */
518     test_msg("4. RSA key generation and encryption/decryption",
519                                                 FIPS_rsa_test(bad_rsa));
520
521     /* DES-CBC encryption/decryption
522     */
523     test_msg("5. DES-ECB encryption/decryption", FIPS_des3_test());
524
525     /* DSA key generation and signature validation
526     */
527     test_msg("6. DSA key generation and signature validation",
528                                                 FIPS_dsa_test(bad_dsa));
529
530     /* SHA-1 hash
531     */
532     test_msg("7a. SHA-1 hash", FIPS_sha1_test());
533
534     /* SHA-256 hash
535     */
536     test_msg("7b. SHA-256 hash", FIPS_sha256_test());
537
538     /* SHA-512 hash
539     */
540     test_msg("7c. SHA-512 hash", FIPS_sha512_test());
541
542     /* HMAC-SHA-1 hash
543     */
544     test_msg("7d. HMAC-SHA-1 hash", FIPS_hmac_sha1_test());
545
546     /* HMAC-SHA-224 hash
547     */
548     test_msg("7e. HMAC-SHA-224 hash", FIPS_hmac_sha224_test());
549
550     /* HMAC-SHA-256 hash
551     */
552     test_msg("7f. HMAC-SHA-256 hash", FIPS_hmac_sha256_test());
553
554     /* HMAC-SHA-384 hash
555     */
556     test_msg("7g. HMAC-SHA-384 hash", FIPS_hmac_sha384_test());
557
558     /* HMAC-SHA-512 hash
559     */
560     test_msg("7h. HMAC-SHA-512 hash", FIPS_hmac_sha512_test());
561
562     /* Non-Approved cryptographic operation
563     */
564     printf("8. Non-Approved cryptographic operation test...\n");
565     printf("\ta. Included algorithm (D-H)...%s\n",
566                 dh_test() ? "successful as expected"
567                                                 : Fail("failed INCORRECTLY!") );
568
569     /* Zeroization
570     */
571     printf("9. Zero-ization...\n\t%s\n",
572                 Zeroize() ? "successful as expected"
573                                         : Fail("failed INCORRECTLY!") );
574
575     printf("\nAll tests completed with %d errors\n", Error);
576     return Error ? 1 : 0;
577     }
578
579 #endif