dev_crypto_cipher: return immediately if allocating cin/cout failed
[openssl.git] / crypto / evp / evp_test.c
1 /* Written by Ben Laurie, 2001 */
2 /*
3  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer. 
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    openssl-core@openssl.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49
50 #include <stdio.h>
51 #include <string.h>
52
53 #include "../e_os.h"
54
55 #include <openssl/opensslconf.h>
56 #include <openssl/evp.h>
57 #ifndef OPENSSL_NO_ENGINE
58 #include <openssl/engine.h>
59 #endif
60 #include <openssl/err.h>
61 #include <openssl/conf.h>
62
63 static void hexdump(FILE *f,const char *title,const unsigned char *s,int l)
64     {
65     int n=0;
66
67     fprintf(f,"%s",title);
68     for( ; n < l ; ++n)
69         {
70         if((n%16) == 0)
71             fprintf(f,"\n%04x",n);
72         fprintf(f," %02x",s[n]);
73         }
74     fprintf(f,"\n");
75     }
76
77 static int convert(unsigned char *s)
78     {
79     unsigned char *d;
80
81     for(d=s ; *s ; s+=2,++d)
82         {
83         unsigned int n;
84
85         if(!s[1])
86             {
87             fprintf(stderr,"Odd number of hex digits!");
88             EXIT(4);
89             }
90         sscanf((char *)s,"%2x",&n);
91         *d=(unsigned char)n;
92         }
93     return s-d;
94     }
95
96 static char *sstrsep(char **string, const char *delim)
97     {
98     char isdelim[256];
99     char *token = *string;
100
101     if (**string == 0)
102         return NULL;
103
104     memset(isdelim, 0, 256);
105     isdelim[0] = 1;
106
107     while (*delim)
108         {
109         isdelim[(unsigned char)(*delim)] = 1;
110         delim++;
111         }
112
113     while (!isdelim[(unsigned char)(**string)])
114         {
115         (*string)++;
116         }
117
118     if (**string)
119         {
120         **string = 0;
121         (*string)++;
122         }
123
124     return token;
125     }
126
127 static unsigned char *ustrsep(char **p,const char *sep)
128     { return (unsigned char *)sstrsep(p,sep); }
129
130 static int test1_exit(int ec)
131         {
132         EXIT(ec);
133         return(0);              /* To keep some compilers quiet */
134         }
135
136 /* Test copying of contexts */
137 static void test_ctx_replace(EVP_CIPHER_CTX **pctx)
138         {
139         /* Make copy of context and replace original */
140         EVP_CIPHER_CTX *ctx_copy;
141         ctx_copy = EVP_CIPHER_CTX_new();
142         EVP_CIPHER_CTX_copy(ctx_copy, *pctx);
143         EVP_CIPHER_CTX_free(*pctx);
144         *pctx = ctx_copy;
145         }
146
147 static void test1(const EVP_CIPHER *c,const unsigned char *key,int kn,
148                   const unsigned char *iv,int in,
149                   const unsigned char *plaintext,int pn,
150                   const unsigned char *ciphertext,int cn,
151                   const unsigned char *aad,int an,
152                   const unsigned char *tag,int tn,
153                   int encdec)
154     {
155     EVP_CIPHER_CTX *ctx = NULL;
156     unsigned char out[4096];
157     int outl,outl2,mode;
158
159     printf("Testing cipher %s%s\n",EVP_CIPHER_name(c),
160            (encdec == 1 ? "(encrypt)" : (encdec == 0 ? "(decrypt)" : "(encrypt/decrypt)")));
161     hexdump(stdout,"Key",key,kn);
162     if(in)
163         hexdump(stdout,"IV",iv,in);
164     hexdump(stdout,"Plaintext",plaintext,pn);
165     hexdump(stdout,"Ciphertext",ciphertext,cn);
166     if (an)
167         hexdump(stdout,"AAD",aad,an);
168     if (tn)
169         hexdump(stdout,"Tag",tag,tn);
170     mode = EVP_CIPHER_mode(c); 
171     if(kn != EVP_CIPHER_key_length(c))
172         {
173         fprintf(stderr,"Key length doesn't match, got %d expected %lu\n",kn,
174                 (unsigned long)EVP_CIPHER_key_length(c));
175         test1_exit(5);
176         }
177     ctx = EVP_CIPHER_CTX_new();
178     EVP_CIPHER_CTX_set_flags(ctx,EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
179     if (encdec != 0)
180         {
181         if (mode == EVP_CIPH_GCM_MODE)
182             {
183             if(!EVP_EncryptInit_ex(ctx,c,NULL,NULL,NULL))
184                 {
185                 fprintf(stderr,"EncryptInit failed\n");
186                 ERR_print_errors_fp(stderr);
187                 test1_exit(10);
188                 }
189             if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL))
190                 {
191                 fprintf(stderr,"IV length set failed\n");
192                 ERR_print_errors_fp(stderr);
193                 test1_exit(11);
194                 }
195             if(!EVP_EncryptInit_ex(ctx,NULL,NULL,key,iv))
196                 {
197                 fprintf(stderr,"Key/IV set failed\n");
198                 ERR_print_errors_fp(stderr);
199                 test1_exit(12);
200                 }
201             if (an && !EVP_EncryptUpdate(ctx,NULL,&outl,aad,an))
202                 {
203                 fprintf(stderr,"AAD set failed\n");
204                 ERR_print_errors_fp(stderr);
205                 test1_exit(13);
206                 }
207             }
208         else if (mode == EVP_CIPH_CCM_MODE)
209             {
210             if(!EVP_EncryptInit_ex(ctx,c,NULL,NULL,NULL))
211                 {
212                 fprintf(stderr,"EncryptInit failed\n");
213                 ERR_print_errors_fp(stderr);
214                 test1_exit(10);
215                 }
216             if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, in, NULL))
217                 {
218                 fprintf(stderr,"IV length set failed\n");
219                 ERR_print_errors_fp(stderr);
220                 test1_exit(11);
221                 }
222             if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tn, NULL))
223                 {
224                 fprintf(stderr,"Tag length set failed\n");
225                 ERR_print_errors_fp(stderr);
226                 test1_exit(11);
227                 }
228             if(!EVP_EncryptInit_ex(ctx,NULL,NULL,key,iv))
229                 {
230                 fprintf(stderr,"Key/IV set failed\n");
231                 ERR_print_errors_fp(stderr);
232                 test1_exit(12);
233                 }
234             if (!EVP_EncryptUpdate(ctx,NULL,&outl,NULL,pn))
235                 {
236                 fprintf(stderr,"Plaintext length set failed\n");
237                 ERR_print_errors_fp(stderr);
238                 test1_exit(12);
239                 }
240             if (an && !EVP_EncryptUpdate(ctx,NULL,&outl,aad,an))
241                 {
242                 fprintf(stderr,"AAD set failed\n");
243                 ERR_print_errors_fp(stderr);
244                 test1_exit(13);
245                 }
246             }
247         else if (mode == EVP_CIPH_WRAP_MODE)
248             {
249             if(!EVP_EncryptInit_ex(ctx,c,NULL,key,in ? iv : NULL))
250                 {
251                 fprintf(stderr,"EncryptInit failed\n");
252                 ERR_print_errors_fp(stderr);
253                 test1_exit(10);
254                 }
255             }
256         else if(!EVP_EncryptInit_ex(ctx,c,NULL,key,iv))
257             {
258             fprintf(stderr,"EncryptInit failed\n");
259             ERR_print_errors_fp(stderr);
260             test1_exit(10);
261             }
262         EVP_CIPHER_CTX_set_padding(ctx,0);
263
264         test_ctx_replace(&ctx);
265
266         if(!EVP_EncryptUpdate(ctx,out,&outl,plaintext,pn))
267             {
268             fprintf(stderr,"Encrypt failed\n");
269             ERR_print_errors_fp(stderr);
270             test1_exit(6);
271             }
272         if(!EVP_EncryptFinal_ex(ctx,out+outl,&outl2))
273             {
274             fprintf(stderr,"EncryptFinal failed\n");
275             ERR_print_errors_fp(stderr);
276             test1_exit(7);
277             }
278
279         if(outl+outl2 != cn)
280             {
281             fprintf(stderr,"Ciphertext length mismatch got %d expected %d\n",
282                     outl+outl2,cn);
283             test1_exit(8);
284             }
285
286         if(memcmp(out,ciphertext,cn))
287             {
288             fprintf(stderr,"Ciphertext mismatch\n");
289             hexdump(stderr,"Got",out,cn);
290             hexdump(stderr,"Expected",ciphertext,cn);
291             test1_exit(9);
292             }
293         if (mode == EVP_CIPH_GCM_MODE || mode == EVP_CIPH_CCM_MODE)
294             {
295             unsigned char rtag[16];
296             /* Note: EVP_CTRL_CCM_GET_TAG has same value as 
297              * EVP_CTRL_GCM_GET_TAG
298              */
299             if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tn, rtag))
300                 {
301                 fprintf(stderr,"Get tag failed\n");
302                 ERR_print_errors_fp(stderr);
303                 test1_exit(14);
304                 }
305             if (memcmp(rtag, tag, tn))
306                 {
307                 fprintf(stderr,"Tag mismatch\n");
308                 hexdump(stderr,"Got",rtag,tn);
309                 hexdump(stderr,"Expected",tag,tn);
310                 test1_exit(9);
311                 }
312             }
313         }
314
315     if (encdec <= 0)
316         {
317         if (mode == EVP_CIPH_GCM_MODE)
318             {
319             if(!EVP_DecryptInit_ex(ctx,c,NULL,NULL,NULL))
320                 {
321                 fprintf(stderr,"EncryptInit failed\n");
322                 ERR_print_errors_fp(stderr);
323                 test1_exit(10);
324                 }
325             if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL))
326                 {
327                 fprintf(stderr,"IV length set failed\n");
328                 ERR_print_errors_fp(stderr);
329                 test1_exit(11);
330                 }
331             if(!EVP_DecryptInit_ex(ctx,NULL,NULL,key,iv))
332                 {
333                 fprintf(stderr,"Key/IV set failed\n");
334                 ERR_print_errors_fp(stderr);
335                 test1_exit(12);
336                 }
337             if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tn, (void *)tag))
338                 {
339                 fprintf(stderr,"Set tag failed\n");
340                 ERR_print_errors_fp(stderr);
341                 test1_exit(14);
342                 }
343             if (an && !EVP_DecryptUpdate(ctx,NULL,&outl,aad,an))
344                 {
345                 fprintf(stderr,"AAD set failed\n");
346                 ERR_print_errors_fp(stderr);
347                 test1_exit(13);
348                 }
349             }
350         else if (mode == EVP_CIPH_CCM_MODE)
351             {
352             if(!EVP_DecryptInit_ex(ctx,c,NULL,NULL,NULL))
353                 {
354                 fprintf(stderr,"DecryptInit failed\n");
355                 ERR_print_errors_fp(stderr);
356                 test1_exit(10);
357                 }
358             if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, in, NULL))
359                 {
360                 fprintf(stderr,"IV length set failed\n");
361                 ERR_print_errors_fp(stderr);
362                 test1_exit(11);
363                 }
364             if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tn, (void *)tag))
365                 {
366                 fprintf(stderr,"Tag length set failed\n");
367                 ERR_print_errors_fp(stderr);
368                 test1_exit(11);
369                 }
370             if(!EVP_DecryptInit_ex(ctx,NULL,NULL,key,iv))
371                 {
372                 fprintf(stderr,"Key/Nonce set failed\n");
373                 ERR_print_errors_fp(stderr);
374                 test1_exit(12);
375                 }
376             if (!EVP_DecryptUpdate(ctx,NULL,&outl,NULL,pn))
377                 {
378                 fprintf(stderr,"Plaintext length set failed\n");
379                 ERR_print_errors_fp(stderr);
380                 test1_exit(12);
381                 }
382             if (an && !EVP_EncryptUpdate(ctx,NULL,&outl,aad,an))
383                 {
384                 fprintf(stderr,"AAD set failed\n");
385                 ERR_print_errors_fp(stderr);
386                 test1_exit(13);
387                 }
388             }
389         else if (mode == EVP_CIPH_WRAP_MODE)
390             {
391             if(!EVP_DecryptInit_ex(ctx,c,NULL,key,in ? iv : NULL))
392                 {
393                 fprintf(stderr,"EncryptInit failed\n");
394                 ERR_print_errors_fp(stderr);
395                 test1_exit(10);
396                 }
397             }
398         else if(!EVP_DecryptInit_ex(ctx,c,NULL,key,iv))
399             {
400             fprintf(stderr,"DecryptInit failed\n");
401             ERR_print_errors_fp(stderr);
402             test1_exit(11);
403             }
404         EVP_CIPHER_CTX_set_padding(ctx,0);
405
406         test_ctx_replace(&ctx);
407
408         if(!EVP_DecryptUpdate(ctx,out,&outl,ciphertext,cn))
409             {
410             fprintf(stderr,"Decrypt failed\n");
411             ERR_print_errors_fp(stderr);
412             test1_exit(6);
413             }
414         if(mode != EVP_CIPH_CCM_MODE && !EVP_DecryptFinal_ex(ctx,out+outl,&outl2))
415             {
416             fprintf(stderr,"DecryptFinal failed\n");
417             ERR_print_errors_fp(stderr);
418             test1_exit(7);
419             }
420
421         if(outl+outl2 != pn)
422             {
423             fprintf(stderr,"Plaintext length mismatch got %d expected %d\n",
424                     outl+outl2,pn);
425             test1_exit(8);
426             }
427
428         if(memcmp(out,plaintext,pn))
429             {
430             fprintf(stderr,"Plaintext mismatch\n");
431             hexdump(stderr,"Got",out,pn);
432             hexdump(stderr,"Expected",plaintext,pn);
433             test1_exit(9);
434             }
435         }
436
437     EVP_CIPHER_CTX_free(ctx);
438
439     printf("\n");
440     }
441
442 static int test_cipher(const char *cipher,const unsigned char *key,int kn,
443                        const unsigned char *iv,int in,
444                        const unsigned char *plaintext,int pn,
445                        const unsigned char *ciphertext,int cn,
446                        const unsigned char *aad,int an,
447                        const unsigned char *tag,int tn,
448                        int encdec)
449     {
450     const EVP_CIPHER *c;
451
452     c=EVP_get_cipherbyname(cipher);
453     if(!c)
454         return 0;
455
456     test1(c,key,kn,iv,in,plaintext,pn,ciphertext,cn,aad,an,tag,tn,encdec);
457
458     return 1;
459     }
460
461 static int test_digest(const char *digest,
462                        const unsigned char *plaintext,int pn,
463                        const unsigned char *ciphertext, unsigned int cn)
464     {
465     const EVP_MD *d;
466     EVP_MD_CTX ctx;
467     unsigned char md[EVP_MAX_MD_SIZE];
468     unsigned int mdn;
469
470     d=EVP_get_digestbyname(digest);
471     if(!d)
472         return 0;
473
474     printf("Testing digest %s\n",EVP_MD_name(d));
475     hexdump(stdout,"Plaintext",plaintext,pn);
476     hexdump(stdout,"Digest",ciphertext,cn);
477
478     EVP_MD_CTX_init(&ctx);
479     if(!EVP_DigestInit_ex(&ctx,d, NULL))
480         {
481         fprintf(stderr,"DigestInit failed\n");
482         ERR_print_errors_fp(stderr);
483         EXIT(100);
484         }
485     if(!EVP_DigestUpdate(&ctx,plaintext,pn))
486         {
487         fprintf(stderr,"DigestUpdate failed\n");
488         ERR_print_errors_fp(stderr);
489         EXIT(101);
490         }
491     if(!EVP_DigestFinal_ex(&ctx,md,&mdn))
492         {
493         fprintf(stderr,"DigestFinal failed\n");
494         ERR_print_errors_fp(stderr);
495         EXIT(101);
496         }
497     EVP_MD_CTX_cleanup(&ctx);
498
499     if(mdn != cn)
500         {
501         fprintf(stderr,"Digest length mismatch, got %d expected %d\n",mdn,cn);
502         EXIT(102);
503         }
504
505     if(memcmp(md,ciphertext,cn))
506         {
507         fprintf(stderr,"Digest mismatch\n");
508         hexdump(stderr,"Got",md,cn);
509         hexdump(stderr,"Expected",ciphertext,cn);
510         EXIT(103);
511         }
512
513     printf("\n");
514
515     EVP_MD_CTX_cleanup(&ctx);
516
517     return 1;
518     }
519
520 int main(int argc,char **argv)
521     {
522     const char *szTestFile;
523     FILE *f;
524
525     if(argc != 2)
526         {
527         fprintf(stderr,"%s <test file>\n",argv[0]);
528         EXIT(1);
529         }
530     CRYPTO_malloc_debug_init();
531     CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
532     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
533
534     szTestFile=argv[1];
535
536     f=fopen(szTestFile,"r");
537     if(!f)
538         {
539         perror(szTestFile);
540         EXIT(2);
541         }
542     ERR_load_crypto_strings();
543     /* Load up the software EVP_CIPHER and EVP_MD definitions */
544     OpenSSL_add_all_ciphers();
545     OpenSSL_add_all_digests();
546 #ifndef OPENSSL_NO_ENGINE
547     /* Load all compiled-in ENGINEs */
548     ENGINE_load_builtin_engines();
549 #endif
550 #if 0
551     OPENSSL_config();
552 #endif
553 #ifndef OPENSSL_NO_ENGINE
554     /* Register all available ENGINE implementations of ciphers and digests.
555      * This could perhaps be changed to "ENGINE_register_all_complete()"? */
556     ENGINE_register_all_ciphers();
557     ENGINE_register_all_digests();
558     /* If we add command-line options, this statement should be switchable.
559      * It'll prevent ENGINEs being ENGINE_init()ialised for cipher/digest use if
560      * they weren't already initialised. */
561     /* ENGINE_set_cipher_flags(ENGINE_CIPHER_FLAG_NOINIT); */
562 #endif
563
564     for( ; ; )
565         {
566         char line[4096];
567         char *p;
568         char *cipher;
569         unsigned char *iv,*key,*plaintext,*ciphertext,*aad,*tag;
570         int encdec;
571         int kn,in,pn,cn;
572         int an = 0;
573         int tn = 0;
574
575         if(!fgets((char *)line,sizeof line,f))
576             break;
577         if(line[0] == '#' || line[0] == '\n')
578             continue;
579         p=line;
580         cipher=sstrsep(&p,":"); 
581         key=ustrsep(&p,":");
582         iv=ustrsep(&p,":");
583         plaintext=ustrsep(&p,":");
584         ciphertext=ustrsep(&p,":");
585         if (p[-1] == '\n') {
586             encdec = -1;
587             p[-1] = '\0';
588             tag=aad=NULL;
589             an=tn=0;
590         } else {
591             aad=ustrsep(&p,":");
592             tag=ustrsep(&p,":");
593             if (tag == NULL) {
594                 p = (char *)aad;
595                 tag=aad=NULL;
596                 an=tn=0;
597             }
598             if (p [-1] == '\n') {
599                 encdec = -1;
600                 p[-1] = '\0';
601             } else
602                 encdec = atoi(sstrsep(&p,"\n"));
603         }
604
605         kn=convert(key);
606         in=convert(iv);
607         pn=convert(plaintext);
608         cn=convert(ciphertext);
609         if (aad) {
610             an=convert(aad);
611             tn=convert(tag);
612         }
613
614         if(!test_cipher(cipher,key,kn,iv,in,plaintext,pn,ciphertext,cn,aad,an,tag,tn,encdec)
615            && !test_digest(cipher,plaintext,pn,ciphertext,cn))
616             {
617 #ifdef OPENSSL_NO_AES
618             if (strstr(cipher, "AES") == cipher)
619                 {
620                 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 
621                 continue;
622                 }
623 #endif
624 #ifdef OPENSSL_NO_DES
625             if (strstr(cipher, "DES") == cipher)
626                 {
627                 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 
628                 continue;
629                 }
630 #endif
631 #ifdef OPENSSL_NO_RC4
632             if (strstr(cipher, "RC4") == cipher)
633                 {
634                 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 
635                 continue;
636                 }
637 #endif
638 #ifdef OPENSSL_NO_CAMELLIA
639             if (strstr(cipher, "CAMELLIA") == cipher)
640                 {
641                 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 
642                 continue;
643                 }
644 #endif
645 #ifdef OPENSSL_NO_SEED
646             if (strstr(cipher, "SEED") == cipher)
647                 {
648                 fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); 
649                 continue;
650                 }
651 #endif
652             fprintf(stderr,"Can't find %s\n",cipher);
653             EXIT(3);
654             }
655         }
656         fclose(f);
657
658 #ifndef OPENSSL_NO_ENGINE
659     ENGINE_cleanup();
660 #endif
661     EVP_cleanup();
662     CRYPTO_cleanup_all_ex_data();
663     ERR_remove_thread_state(NULL);
664     ERR_free_strings();
665     CRYPTO_mem_leaks_fp(stderr);
666
667     return 0;
668     }