1109998Smarkm/* Written by Ben Laurie, 2001 */
2109998Smarkm/*
3344604Sjkim * Copyright (c) 2001-2019 The OpenSSL Project.  All rights reserved.
4109998Smarkm *
5109998Smarkm * Redistribution and use in source and binary forms, with or without
6109998Smarkm * modification, are permitted provided that the following conditions
7109998Smarkm * are met:
8109998Smarkm *
9109998Smarkm * 1. Redistributions of source code must retain the above copyright
10280297Sjkim *    notice, this list of conditions and the following disclaimer.
11109998Smarkm *
12109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
13109998Smarkm *    notice, this list of conditions and the following disclaimer in
14109998Smarkm *    the documentation and/or other materials provided with the
15109998Smarkm *    distribution.
16109998Smarkm *
17109998Smarkm * 3. All advertising materials mentioning features or use of this
18109998Smarkm *    software must display the following acknowledgment:
19109998Smarkm *    "This product includes software developed by the OpenSSL Project
20109998Smarkm *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21109998Smarkm *
22109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23109998Smarkm *    endorse or promote products derived from this software without
24109998Smarkm *    prior written permission. For written permission, please contact
25109998Smarkm *    openssl-core@openssl.org.
26109998Smarkm *
27109998Smarkm * 5. Products derived from this software may not be called "OpenSSL"
28109998Smarkm *    nor may "OpenSSL" appear in their names without prior written
29109998Smarkm *    permission of the OpenSSL Project.
30109998Smarkm *
31109998Smarkm * 6. Redistributions of any form whatsoever must retain the following
32109998Smarkm *    acknowledgment:
33109998Smarkm *    "This product includes software developed by the OpenSSL Project
34109998Smarkm *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35109998Smarkm *
36109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39109998Smarkm * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE.
48109998Smarkm */
49109998Smarkm
50109998Smarkm#include <stdio.h>
51109998Smarkm#include <string.h>
52109998Smarkm
53109998Smarkm#include "../e_os.h"
54109998Smarkm
55160814Ssimon#include <openssl/opensslconf.h>
56109998Smarkm#include <openssl/evp.h>
57111147Snectar#ifndef OPENSSL_NO_ENGINE
58280297Sjkim# include <openssl/engine.h>
59111147Snectar#endif
60111147Snectar#include <openssl/err.h>
61109998Smarkm#include <openssl/conf.h>
62109998Smarkm
63280297Sjkimstatic void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
64280297Sjkim{
65280297Sjkim    int n = 0;
66109998Smarkm
67280297Sjkim    fprintf(f, "%s", title);
68280297Sjkim    for (; n < l; ++n) {
69280297Sjkim        if ((n % 16) == 0)
70280297Sjkim            fprintf(f, "\n%04x", n);
71280297Sjkim        fprintf(f, " %02x", s[n]);
72109998Smarkm    }
73280297Sjkim    fprintf(f, "\n");
74280297Sjkim}
75109998Smarkm
76109998Smarkmstatic int convert(unsigned char *s)
77280297Sjkim{
78109998Smarkm    unsigned char *d;
79306195Sjkim    int digits = 0;
80109998Smarkm
81280297Sjkim    for (d = s; *s; s += 2, ++d) {
82280297Sjkim        unsigned int n;
83109998Smarkm
84280297Sjkim        if (!s[1]) {
85280297Sjkim            fprintf(stderr, "Odd number of hex digits!");
86280297Sjkim            EXIT(4);
87280297Sjkim        }
88280297Sjkim        sscanf((char *)s, "%2x", &n);
89280297Sjkim        *d = (unsigned char)n;
90306195Sjkim        digits++;
91109998Smarkm    }
92306195Sjkim    return digits;
93280297Sjkim}
94109998Smarkm
95109998Smarkmstatic char *sstrsep(char **string, const char *delim)
96280297Sjkim{
97109998Smarkm    char isdelim[256];
98109998Smarkm    char *token = *string;
99109998Smarkm
100109998Smarkm    if (**string == 0)
101109998Smarkm        return NULL;
102109998Smarkm
103109998Smarkm    memset(isdelim, 0, 256);
104109998Smarkm    isdelim[0] = 1;
105109998Smarkm
106280297Sjkim    while (*delim) {
107109998Smarkm        isdelim[(unsigned char)(*delim)] = 1;
108109998Smarkm        delim++;
109280297Sjkim    }
110109998Smarkm
111280297Sjkim    while (!isdelim[(unsigned char)(**string)]) {
112109998Smarkm        (*string)++;
113280297Sjkim    }
114109998Smarkm
115280297Sjkim    if (**string) {
116109998Smarkm        **string = 0;
117109998Smarkm        (*string)++;
118280297Sjkim    }
119109998Smarkm
120109998Smarkm    return token;
121280297Sjkim}
122109998Smarkm
123280297Sjkimstatic unsigned char *ustrsep(char **p, const char *sep)
124280297Sjkim{
125280297Sjkim    return (unsigned char *)sstrsep(p, sep);
126280297Sjkim}
127109998Smarkm
128109998Smarkmstatic int test1_exit(int ec)
129280297Sjkim{
130280297Sjkim    EXIT(ec);
131280297Sjkim    return (0);                 /* To keep some compilers quiet */
132280297Sjkim}
133109998Smarkm
134280297Sjkimstatic void test1(const EVP_CIPHER *c, const unsigned char *key, int kn,
135280297Sjkim                  const unsigned char *iv, int in,
136280297Sjkim                  const unsigned char *plaintext, int pn,
137290207Sjkim                  const unsigned char *ciphertext, int cn,
138290207Sjkim                  const unsigned char *aad, int an,
139290207Sjkim                  const unsigned char *tag, int tn, int encdec)
140280297Sjkim{
141109998Smarkm    EVP_CIPHER_CTX ctx;
142109998Smarkm    unsigned char out[4096];
143290207Sjkim    int outl, outl2, mode;
144109998Smarkm
145280297Sjkim    printf("Testing cipher %s%s\n", EVP_CIPHER_name(c),
146280297Sjkim           (encdec ==
147280297Sjkim            1 ? "(encrypt)" : (encdec ==
148280297Sjkim                               0 ? "(decrypt)" : "(encrypt/decrypt)")));
149280297Sjkim    hexdump(stdout, "Key", key, kn);
150280297Sjkim    if (in)
151280297Sjkim        hexdump(stdout, "IV", iv, in);
152280297Sjkim    hexdump(stdout, "Plaintext", plaintext, pn);
153280297Sjkim    hexdump(stdout, "Ciphertext", ciphertext, cn);
154290207Sjkim    if (an)
155290207Sjkim        hexdump(stdout, "AAD", aad, an);
156290207Sjkim    if (tn)
157290207Sjkim        hexdump(stdout, "Tag", tag, tn);
158290207Sjkim    mode = EVP_CIPHER_mode(c);
159290207Sjkim    if (kn != EVP_CIPHER_key_length(c)) {
160280297Sjkim        fprintf(stderr, "Key length doesn't match, got %d expected %lu\n", kn,
161290207Sjkim                (unsigned long)EVP_CIPHER_key_length(c));
162280297Sjkim        test1_exit(5);
163280297Sjkim    }
164109998Smarkm    EVP_CIPHER_CTX_init(&ctx);
165290207Sjkim    EVP_CIPHER_CTX_set_flags(&ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
166280297Sjkim    if (encdec != 0) {
167290207Sjkim        if (mode == EVP_CIPH_GCM_MODE) {
168290207Sjkim            if (!EVP_EncryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
169290207Sjkim                fprintf(stderr, "EncryptInit failed\n");
170290207Sjkim                ERR_print_errors_fp(stderr);
171290207Sjkim                test1_exit(10);
172290207Sjkim            }
173290207Sjkim            if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) {
174290207Sjkim                fprintf(stderr, "IV length set failed\n");
175290207Sjkim                ERR_print_errors_fp(stderr);
176290207Sjkim                test1_exit(11);
177290207Sjkim            }
178290207Sjkim            if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, iv)) {
179290207Sjkim                fprintf(stderr, "Key/IV set failed\n");
180290207Sjkim                ERR_print_errors_fp(stderr);
181290207Sjkim                test1_exit(12);
182290207Sjkim            }
183290207Sjkim            if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) {
184290207Sjkim                fprintf(stderr, "AAD set failed\n");
185290207Sjkim                ERR_print_errors_fp(stderr);
186290207Sjkim                test1_exit(13);
187290207Sjkim            }
188290207Sjkim        } else if (mode == EVP_CIPH_CCM_MODE) {
189290207Sjkim            if (!EVP_EncryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
190290207Sjkim                fprintf(stderr, "EncryptInit failed\n");
191290207Sjkim                ERR_print_errors_fp(stderr);
192290207Sjkim                test1_exit(10);
193290207Sjkim            }
194290207Sjkim            if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, in, NULL)) {
195290207Sjkim                fprintf(stderr, "IV length set failed\n");
196290207Sjkim                ERR_print_errors_fp(stderr);
197290207Sjkim                test1_exit(11);
198290207Sjkim            }
199290207Sjkim            if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, tn, NULL)) {
200290207Sjkim                fprintf(stderr, "Tag length set failed\n");
201290207Sjkim                ERR_print_errors_fp(stderr);
202290207Sjkim                test1_exit(11);
203290207Sjkim            }
204290207Sjkim            if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, iv)) {
205290207Sjkim                fprintf(stderr, "Key/IV set failed\n");
206290207Sjkim                ERR_print_errors_fp(stderr);
207290207Sjkim                test1_exit(12);
208290207Sjkim            }
209290207Sjkim            if (!EVP_EncryptUpdate(&ctx, NULL, &outl, NULL, pn)) {
210290207Sjkim                fprintf(stderr, "Plaintext length set failed\n");
211290207Sjkim                ERR_print_errors_fp(stderr);
212290207Sjkim                test1_exit(12);
213290207Sjkim            }
214290207Sjkim            if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) {
215290207Sjkim                fprintf(stderr, "AAD set failed\n");
216290207Sjkim                ERR_print_errors_fp(stderr);
217290207Sjkim                test1_exit(13);
218290207Sjkim            }
219290207Sjkim        } else if (mode == EVP_CIPH_WRAP_MODE) {
220290207Sjkim            if (!EVP_EncryptInit_ex(&ctx, c, NULL, key, in ? iv : NULL)) {
221290207Sjkim                fprintf(stderr, "EncryptInit failed\n");
222290207Sjkim                ERR_print_errors_fp(stderr);
223290207Sjkim                test1_exit(10);
224290207Sjkim            }
225290207Sjkim        } else if (!EVP_EncryptInit_ex(&ctx, c, NULL, key, iv)) {
226280297Sjkim            fprintf(stderr, "EncryptInit failed\n");
227280297Sjkim            ERR_print_errors_fp(stderr);
228280297Sjkim            test1_exit(10);
229280297Sjkim        }
230280297Sjkim        EVP_CIPHER_CTX_set_padding(&ctx, 0);
231109998Smarkm
232280297Sjkim        if (!EVP_EncryptUpdate(&ctx, out, &outl, plaintext, pn)) {
233280297Sjkim            fprintf(stderr, "Encrypt failed\n");
234280297Sjkim            ERR_print_errors_fp(stderr);
235280297Sjkim            test1_exit(6);
236280297Sjkim        }
237280297Sjkim        if (!EVP_EncryptFinal_ex(&ctx, out + outl, &outl2)) {
238280297Sjkim            fprintf(stderr, "EncryptFinal failed\n");
239280297Sjkim            ERR_print_errors_fp(stderr);
240280297Sjkim            test1_exit(7);
241280297Sjkim        }
242109998Smarkm
243280297Sjkim        if (outl + outl2 != cn) {
244280297Sjkim            fprintf(stderr, "Ciphertext length mismatch got %d expected %d\n",
245280297Sjkim                    outl + outl2, cn);
246280297Sjkim            test1_exit(8);
247280297Sjkim        }
248109998Smarkm
249280297Sjkim        if (memcmp(out, ciphertext, cn)) {
250280297Sjkim            fprintf(stderr, "Ciphertext mismatch\n");
251280297Sjkim            hexdump(stderr, "Got", out, cn);
252280297Sjkim            hexdump(stderr, "Expected", ciphertext, cn);
253280297Sjkim            test1_exit(9);
254280297Sjkim        }
255290207Sjkim        if (mode == EVP_CIPH_GCM_MODE || mode == EVP_CIPH_CCM_MODE) {
256290207Sjkim            unsigned char rtag[16];
257290207Sjkim            /*
258290207Sjkim             * Note: EVP_CTRL_CCM_GET_TAG has same value as
259290207Sjkim             * EVP_CTRL_GCM_GET_TAG
260290207Sjkim             */
261290207Sjkim            if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, tn, rtag)) {
262290207Sjkim                fprintf(stderr, "Get tag failed\n");
263290207Sjkim                ERR_print_errors_fp(stderr);
264290207Sjkim                test1_exit(14);
265290207Sjkim            }
266290207Sjkim            if (memcmp(rtag, tag, tn)) {
267290207Sjkim                fprintf(stderr, "Tag mismatch\n");
268290207Sjkim                hexdump(stderr, "Got", rtag, tn);
269290207Sjkim                hexdump(stderr, "Expected", tag, tn);
270290207Sjkim                test1_exit(9);
271290207Sjkim            }
272290207Sjkim        }
273280297Sjkim    }
274109998Smarkm
275280297Sjkim    if (encdec <= 0) {
276290207Sjkim        if (mode == EVP_CIPH_GCM_MODE) {
277290207Sjkim            if (!EVP_DecryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
278290207Sjkim                fprintf(stderr, "EncryptInit failed\n");
279290207Sjkim                ERR_print_errors_fp(stderr);
280290207Sjkim                test1_exit(10);
281290207Sjkim            }
282290207Sjkim            if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) {
283290207Sjkim                fprintf(stderr, "IV length set failed\n");
284290207Sjkim                ERR_print_errors_fp(stderr);
285290207Sjkim                test1_exit(11);
286290207Sjkim            }
287290207Sjkim            if (!EVP_DecryptInit_ex(&ctx, NULL, NULL, key, iv)) {
288290207Sjkim                fprintf(stderr, "Key/IV set failed\n");
289290207Sjkim                ERR_print_errors_fp(stderr);
290290207Sjkim                test1_exit(12);
291290207Sjkim            }
292290207Sjkim            if (!EVP_CIPHER_CTX_ctrl
293290207Sjkim                (&ctx, EVP_CTRL_GCM_SET_TAG, tn, (void *)tag)) {
294290207Sjkim                fprintf(stderr, "Set tag failed\n");
295290207Sjkim                ERR_print_errors_fp(stderr);
296290207Sjkim                test1_exit(14);
297290207Sjkim            }
298290207Sjkim            if (an && !EVP_DecryptUpdate(&ctx, NULL, &outl, aad, an)) {
299290207Sjkim                fprintf(stderr, "AAD set failed\n");
300290207Sjkim                ERR_print_errors_fp(stderr);
301290207Sjkim                test1_exit(13);
302290207Sjkim            }
303290207Sjkim        } else if (mode == EVP_CIPH_CCM_MODE) {
304290207Sjkim            if (!EVP_DecryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
305290207Sjkim                fprintf(stderr, "DecryptInit failed\n");
306290207Sjkim                ERR_print_errors_fp(stderr);
307290207Sjkim                test1_exit(10);
308290207Sjkim            }
309290207Sjkim            if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, in, NULL)) {
310290207Sjkim                fprintf(stderr, "IV length set failed\n");
311290207Sjkim                ERR_print_errors_fp(stderr);
312290207Sjkim                test1_exit(11);
313290207Sjkim            }
314290207Sjkim            if (!EVP_CIPHER_CTX_ctrl
315290207Sjkim                (&ctx, EVP_CTRL_CCM_SET_TAG, tn, (void *)tag)) {
316290207Sjkim                fprintf(stderr, "Tag length set failed\n");
317290207Sjkim                ERR_print_errors_fp(stderr);
318290207Sjkim                test1_exit(11);
319290207Sjkim            }
320290207Sjkim            if (!EVP_DecryptInit_ex(&ctx, NULL, NULL, key, iv)) {
321290207Sjkim                fprintf(stderr, "Key/Nonce set failed\n");
322290207Sjkim                ERR_print_errors_fp(stderr);
323290207Sjkim                test1_exit(12);
324290207Sjkim            }
325290207Sjkim            if (!EVP_DecryptUpdate(&ctx, NULL, &outl, NULL, pn)) {
326290207Sjkim                fprintf(stderr, "Plaintext length set failed\n");
327290207Sjkim                ERR_print_errors_fp(stderr);
328290207Sjkim                test1_exit(12);
329290207Sjkim            }
330344604Sjkim            if (an && !EVP_DecryptUpdate(&ctx, NULL, &outl, aad, an)) {
331290207Sjkim                fprintf(stderr, "AAD set failed\n");
332290207Sjkim                ERR_print_errors_fp(stderr);
333290207Sjkim                test1_exit(13);
334290207Sjkim            }
335290207Sjkim        } else if (mode == EVP_CIPH_WRAP_MODE) {
336290207Sjkim            if (!EVP_DecryptInit_ex(&ctx, c, NULL, key, in ? iv : NULL)) {
337290207Sjkim                fprintf(stderr, "EncryptInit failed\n");
338290207Sjkim                ERR_print_errors_fp(stderr);
339290207Sjkim                test1_exit(10);
340290207Sjkim            }
341290207Sjkim        } else if (!EVP_DecryptInit_ex(&ctx, c, NULL, key, iv)) {
342280297Sjkim            fprintf(stderr, "DecryptInit failed\n");
343280297Sjkim            ERR_print_errors_fp(stderr);
344280297Sjkim            test1_exit(11);
345280297Sjkim        }
346280297Sjkim        EVP_CIPHER_CTX_set_padding(&ctx, 0);
347109998Smarkm
348280297Sjkim        if (!EVP_DecryptUpdate(&ctx, out, &outl, ciphertext, cn)) {
349280297Sjkim            fprintf(stderr, "Decrypt failed\n");
350280297Sjkim            ERR_print_errors_fp(stderr);
351280297Sjkim            test1_exit(6);
352280297Sjkim        }
353290207Sjkim        if (mode != EVP_CIPH_CCM_MODE
354290207Sjkim            && !EVP_DecryptFinal_ex(&ctx, out + outl, &outl2)) {
355280297Sjkim            fprintf(stderr, "DecryptFinal failed\n");
356280297Sjkim            ERR_print_errors_fp(stderr);
357280297Sjkim            test1_exit(7);
358280297Sjkim        }
359109998Smarkm
360280297Sjkim        if (outl + outl2 != pn) {
361280297Sjkim            fprintf(stderr, "Plaintext length mismatch got %d expected %d\n",
362280297Sjkim                    outl + outl2, pn);
363280297Sjkim            test1_exit(8);
364280297Sjkim        }
365109998Smarkm
366280297Sjkim        if (memcmp(out, plaintext, pn)) {
367280297Sjkim            fprintf(stderr, "Plaintext mismatch\n");
368280297Sjkim            hexdump(stderr, "Got", out, pn);
369280297Sjkim            hexdump(stderr, "Expected", plaintext, pn);
370280297Sjkim            test1_exit(9);
371280297Sjkim        }
372280297Sjkim    }
373109998Smarkm
374109998Smarkm    EVP_CIPHER_CTX_cleanup(&ctx);
375109998Smarkm
376109998Smarkm    printf("\n");
377280297Sjkim}
378109998Smarkm
379280297Sjkimstatic int test_cipher(const char *cipher, const unsigned char *key, int kn,
380280297Sjkim                       const unsigned char *iv, int in,
381280297Sjkim                       const unsigned char *plaintext, int pn,
382290207Sjkim                       const unsigned char *ciphertext, int cn,
383290207Sjkim                       const unsigned char *aad, int an,
384290207Sjkim                       const unsigned char *tag, int tn, int encdec)
385280297Sjkim{
386109998Smarkm    const EVP_CIPHER *c;
387109998Smarkm
388280297Sjkim    c = EVP_get_cipherbyname(cipher);
389280297Sjkim    if (!c)
390280297Sjkim        return 0;
391109998Smarkm
392290207Sjkim    test1(c, key, kn, iv, in, plaintext, pn, ciphertext, cn, aad, an, tag, tn,
393290207Sjkim          encdec);
394109998Smarkm
395109998Smarkm    return 1;
396280297Sjkim}
397109998Smarkm
398109998Smarkmstatic int test_digest(const char *digest,
399280297Sjkim                       const unsigned char *plaintext, int pn,
400280297Sjkim                       const unsigned char *ciphertext, unsigned int cn)
401280297Sjkim{
402109998Smarkm    const EVP_MD *d;
403109998Smarkm    EVP_MD_CTX ctx;
404109998Smarkm    unsigned char md[EVP_MAX_MD_SIZE];
405109998Smarkm    unsigned int mdn;
406109998Smarkm
407280297Sjkim    d = EVP_get_digestbyname(digest);
408280297Sjkim    if (!d)
409280297Sjkim        return 0;
410109998Smarkm
411280297Sjkim    printf("Testing digest %s\n", EVP_MD_name(d));
412280297Sjkim    hexdump(stdout, "Plaintext", plaintext, pn);
413280297Sjkim    hexdump(stdout, "Digest", ciphertext, cn);
414109998Smarkm
415109998Smarkm    EVP_MD_CTX_init(&ctx);
416280297Sjkim    if (!EVP_DigestInit_ex(&ctx, d, NULL)) {
417280297Sjkim        fprintf(stderr, "DigestInit failed\n");
418280297Sjkim        ERR_print_errors_fp(stderr);
419280297Sjkim        EXIT(100);
420280297Sjkim    }
421280297Sjkim    if (!EVP_DigestUpdate(&ctx, plaintext, pn)) {
422280297Sjkim        fprintf(stderr, "DigestUpdate failed\n");
423280297Sjkim        ERR_print_errors_fp(stderr);
424280297Sjkim        EXIT(101);
425280297Sjkim    }
426280297Sjkim    if (!EVP_DigestFinal_ex(&ctx, md, &mdn)) {
427280297Sjkim        fprintf(stderr, "DigestFinal failed\n");
428280297Sjkim        ERR_print_errors_fp(stderr);
429280297Sjkim        EXIT(101);
430280297Sjkim    }
431109998Smarkm    EVP_MD_CTX_cleanup(&ctx);
432109998Smarkm
433280297Sjkim    if (mdn != cn) {
434280297Sjkim        fprintf(stderr, "Digest length mismatch, got %d expected %d\n", mdn,
435280297Sjkim                cn);
436280297Sjkim        EXIT(102);
437280297Sjkim    }
438109998Smarkm
439280297Sjkim    if (memcmp(md, ciphertext, cn)) {
440280297Sjkim        fprintf(stderr, "Digest mismatch\n");
441280297Sjkim        hexdump(stderr, "Got", md, cn);
442280297Sjkim        hexdump(stderr, "Expected", ciphertext, cn);
443280297Sjkim        EXIT(103);
444280297Sjkim    }
445109998Smarkm
446109998Smarkm    printf("\n");
447109998Smarkm
448109998Smarkm    EVP_MD_CTX_cleanup(&ctx);
449109998Smarkm
450109998Smarkm    return 1;
451280297Sjkim}
452109998Smarkm
453280297Sjkimint main(int argc, char **argv)
454280297Sjkim{
455109998Smarkm    const char *szTestFile;
456109998Smarkm    FILE *f;
457109998Smarkm
458280297Sjkim    if (argc != 2) {
459280297Sjkim        fprintf(stderr, "%s <test file>\n", argv[0]);
460280297Sjkim        EXIT(1);
461280297Sjkim    }
462109998Smarkm    CRYPTO_malloc_debug_init();
463109998Smarkm    CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
464109998Smarkm    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
465109998Smarkm
466280297Sjkim    szTestFile = argv[1];
467109998Smarkm
468280297Sjkim    f = fopen(szTestFile, "r");
469280297Sjkim    if (!f) {
470280297Sjkim        perror(szTestFile);
471280297Sjkim        EXIT(2);
472280297Sjkim    }
473290207Sjkim    ERR_load_crypto_strings();
474109998Smarkm    /* Load up the software EVP_CIPHER and EVP_MD definitions */
475109998Smarkm    OpenSSL_add_all_ciphers();
476109998Smarkm    OpenSSL_add_all_digests();
477111147Snectar#ifndef OPENSSL_NO_ENGINE
478109998Smarkm    /* Load all compiled-in ENGINEs */
479109998Smarkm    ENGINE_load_builtin_engines();
480111147Snectar#endif
481109998Smarkm#if 0
482109998Smarkm    OPENSSL_config();
483109998Smarkm#endif
484111147Snectar#ifndef OPENSSL_NO_ENGINE
485280297Sjkim    /*
486280297Sjkim     * Register all available ENGINE implementations of ciphers and digests.
487280297Sjkim     * This could perhaps be changed to "ENGINE_register_all_complete()"?
488280297Sjkim     */
489109998Smarkm    ENGINE_register_all_ciphers();
490109998Smarkm    ENGINE_register_all_digests();
491280297Sjkim    /*
492280297Sjkim     * If we add command-line options, this statement should be switchable.
493280297Sjkim     * It'll prevent ENGINEs being ENGINE_init()ialised for cipher/digest use
494280297Sjkim     * if they weren't already initialised.
495280297Sjkim     */
496109998Smarkm    /* ENGINE_set_cipher_flags(ENGINE_CIPHER_FLAG_NOINIT); */
497111147Snectar#endif
498109998Smarkm
499280297Sjkim    for (;;) {
500280297Sjkim        char line[4096];
501280297Sjkim        char *p;
502280297Sjkim        char *cipher;
503290207Sjkim        unsigned char *iv, *key, *plaintext, *ciphertext, *aad, *tag;
504280297Sjkim        int encdec;
505280297Sjkim        int kn, in, pn, cn;
506290207Sjkim        int an = 0;
507290207Sjkim        int tn = 0;
508109998Smarkm
509331638Sjkim        if (!fgets((char *)line, sizeof(line), f))
510280297Sjkim            break;
511280297Sjkim        if (line[0] == '#' || line[0] == '\n')
512280297Sjkim            continue;
513280297Sjkim        p = line;
514280297Sjkim        cipher = sstrsep(&p, ":");
515280297Sjkim        key = ustrsep(&p, ":");
516280297Sjkim        iv = ustrsep(&p, ":");
517280297Sjkim        plaintext = ustrsep(&p, ":");
518280297Sjkim        ciphertext = ustrsep(&p, ":");
519280297Sjkim        if (p[-1] == '\n') {
520290207Sjkim            encdec = -1;
521280297Sjkim            p[-1] = '\0';
522290207Sjkim            tag = aad = NULL;
523290207Sjkim            an = tn = 0;
524280297Sjkim        } else {
525290207Sjkim            aad = ustrsep(&p, ":");
526290207Sjkim            tag = ustrsep(&p, ":");
527290207Sjkim            if (tag == NULL) {
528290207Sjkim                p = (char *)aad;
529290207Sjkim                tag = aad = NULL;
530290207Sjkim                an = tn = 0;
531290207Sjkim            }
532290207Sjkim            if (p[-1] == '\n') {
533290207Sjkim                encdec = -1;
534290207Sjkim                p[-1] = '\0';
535290207Sjkim            } else
536290207Sjkim                encdec = atoi(sstrsep(&p, "\n"));
537280297Sjkim        }
538109998Smarkm
539280297Sjkim        kn = convert(key);
540280297Sjkim        in = convert(iv);
541280297Sjkim        pn = convert(plaintext);
542280297Sjkim        cn = convert(ciphertext);
543290207Sjkim        if (aad) {
544290207Sjkim            an = convert(aad);
545290207Sjkim            tn = convert(tag);
546290207Sjkim        }
547109998Smarkm
548280297Sjkim        if (!test_cipher
549290207Sjkim            (cipher, key, kn, iv, in, plaintext, pn, ciphertext, cn, aad, an,
550290207Sjkim             tag, tn, encdec)
551280297Sjkim            && !test_digest(cipher, plaintext, pn, ciphertext, cn)) {
552160814Ssimon#ifdef OPENSSL_NO_AES
553280297Sjkim            if (strstr(cipher, "AES") == cipher) {
554280297Sjkim                fprintf(stdout, "Cipher disabled, skipping %s\n", cipher);
555280297Sjkim                continue;
556280297Sjkim            }
557160814Ssimon#endif
558160814Ssimon#ifdef OPENSSL_NO_DES
559280297Sjkim            if (strstr(cipher, "DES") == cipher) {
560280297Sjkim                fprintf(stdout, "Cipher disabled, skipping %s\n", cipher);
561280297Sjkim                continue;
562280297Sjkim            }
563160814Ssimon#endif
564160814Ssimon#ifdef OPENSSL_NO_RC4
565280297Sjkim            if (strstr(cipher, "RC4") == cipher) {
566280297Sjkim                fprintf(stdout, "Cipher disabled, skipping %s\n", cipher);
567280297Sjkim                continue;
568280297Sjkim            }
569160814Ssimon#endif
570162911Ssimon#ifdef OPENSSL_NO_CAMELLIA
571280297Sjkim            if (strstr(cipher, "CAMELLIA") == cipher) {
572280297Sjkim                fprintf(stdout, "Cipher disabled, skipping %s\n", cipher);
573280297Sjkim                continue;
574280297Sjkim            }
575162911Ssimon#endif
576194206Ssimon#ifdef OPENSSL_NO_SEED
577280297Sjkim            if (strstr(cipher, "SEED") == cipher) {
578280297Sjkim                fprintf(stdout, "Cipher disabled, skipping %s\n", cipher);
579280297Sjkim                continue;
580280297Sjkim            }
581194206Ssimon#endif
582280297Sjkim            fprintf(stderr, "Can't find %s\n", cipher);
583280297Sjkim            EXIT(3);
584280297Sjkim        }
585280297Sjkim    }
586280297Sjkim    fclose(f);
587109998Smarkm
588111147Snectar#ifndef OPENSSL_NO_ENGINE
589109998Smarkm    ENGINE_cleanup();
590111147Snectar#endif
591109998Smarkm    EVP_cleanup();
592109998Smarkm    CRYPTO_cleanup_all_ex_data();
593238405Sjkim    ERR_remove_thread_state(NULL);
594109998Smarkm    ERR_free_strings();
595109998Smarkm    CRYPTO_mem_leaks_fp(stderr);
596109998Smarkm
597109998Smarkm    return 0;
598280297Sjkim}
599