Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / boringssl / src / crypto / cipher / cipher_test.c
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.] */
56
57 #include <stdio.h>
58
59 #include <openssl/bio.h>
60 #include <openssl/cipher.h>
61 #include <openssl/crypto.h>
62 #include <openssl/err.h>
63
64
65 static void hexdump(FILE *f, const char *title, const uint8_t *s, int l) {
66   int n = 0;
67
68   fprintf(f, "%s", title);
69   for (; n < l; ++n) {
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(uint8_t *s) {
78   uint8_t *d;
79
80   for (d = s; *s; s += 2, ++d) {
81     unsigned int n;
82
83     if (!s[1]) {
84       fprintf(stderr, "Odd number of hex digits!");
85       exit(4);
86     }
87     sscanf((char *)s, "%2x", &n);
88     *d = (uint8_t)n;
89   }
90   return s - d;
91 }
92
93 static char *sstrsep(char **string, const char *delim) {
94   char isdelim[256];
95   char *token = *string;
96
97   if (**string == 0) {
98     return NULL;
99   }
100
101   memset(isdelim, 0, 256);
102   isdelim[0] = 1;
103
104   while (*delim) {
105     isdelim[(uint8_t)(*delim)] = 1;
106     delim++;
107   }
108
109   while (!isdelim[(uint8_t)(**string)]) {
110     (*string)++;
111   }
112
113   if (**string) {
114     **string = 0;
115     (*string)++;
116   }
117
118   return token;
119 }
120
121 static uint8_t *ustrsep(char **p, const char *sep) {
122   return (uint8_t *)sstrsep(p, sep);
123 }
124
125 static void test1(const EVP_CIPHER *c, const uint8_t *key, int kn,
126                   const uint8_t *iv, int in, const uint8_t *plaintext, int pn,
127                   const uint8_t *ciphertext, int cn, const uint8_t *aad, int an,
128                   const uint8_t *tag, int tn, int encdec) {
129   EVP_CIPHER_CTX ctx;
130   uint8_t out[4096];
131   int outl, outl2, mode;
132
133   printf("Testing cipher %s%s\n", EVP_CIPHER_name(c),
134          (encdec == 1 ? "(encrypt)"
135                       : (encdec == 0 ? "(decrypt)" : "(encrypt/decrypt)")));
136   hexdump(stdout, "Key", key, kn);
137   if (in) {
138     hexdump(stdout, "IV", iv, in);
139   }
140   hexdump(stdout, "Plaintext", plaintext, pn);
141   hexdump(stdout, "Ciphertext", ciphertext, cn);
142   if (an) {
143     hexdump(stdout, "AAD", aad, an);
144   }
145   if (tn) {
146     hexdump(stdout, "Tag", tag, tn);
147   }
148   mode = EVP_CIPHER_mode(c);
149   if (kn != EVP_CIPHER_key_length(c)) {
150     fprintf(stderr, "Key length doesn't match, got %d expected %lu\n", kn,
151             (unsigned long)EVP_CIPHER_key_length(c));
152     exit(5);
153   }
154   EVP_CIPHER_CTX_init(&ctx);
155   if (encdec != 0) {
156     if (mode == EVP_CIPH_GCM_MODE) {
157       if (!EVP_EncryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
158         fprintf(stderr, "EncryptInit failed\n");
159         BIO_print_errors_fp(stderr);
160         exit(10);
161       }
162       if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) {
163         fprintf(stderr, "IV length set failed\n");
164         BIO_print_errors_fp(stderr);
165         exit(11);
166       }
167       if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, iv)) {
168         fprintf(stderr, "Key/IV set failed\n");
169         BIO_print_errors_fp(stderr);
170         exit(12);
171       }
172       if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) {
173         fprintf(stderr, "AAD set failed\n");
174         BIO_print_errors_fp(stderr);
175         exit(13);
176       }
177     } else if (!EVP_EncryptInit_ex(&ctx, c, NULL, key, iv)) {
178       fprintf(stderr, "EncryptInit failed\n");
179       BIO_print_errors_fp(stderr);
180       exit(10);
181     }
182     EVP_CIPHER_CTX_set_padding(&ctx, 0);
183
184     if (!EVP_EncryptUpdate(&ctx, out, &outl, plaintext, pn)) {
185       fprintf(stderr, "Encrypt failed\n");
186       BIO_print_errors_fp(stderr);
187       exit(6);
188     }
189     if (!EVP_EncryptFinal_ex(&ctx, out + outl, &outl2)) {
190       fprintf(stderr, "EncryptFinal failed\n");
191       BIO_print_errors_fp(stderr);
192       exit(7);
193     }
194
195     if (outl + outl2 != cn) {
196       fprintf(stderr, "Ciphertext length mismatch got %d expected %d\n",
197               outl + outl2, cn);
198       exit(8);
199     }
200
201     if (memcmp(out, ciphertext, cn)) {
202       fprintf(stderr, "Ciphertext mismatch\n");
203       hexdump(stderr, "Got", out, cn);
204       hexdump(stderr, "Expected", ciphertext, cn);
205       exit(9);
206     }
207     if (mode == EVP_CIPH_GCM_MODE) {
208       uint8_t rtag[16];
209       /* Note: EVP_CTRL_CCM_GET_TAG has same value as
210        * EVP_CTRL_GCM_GET_TAG
211        */
212       if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, tn, rtag)) {
213         fprintf(stderr, "Get tag failed\n");
214         BIO_print_errors_fp(stderr);
215         exit(14);
216       }
217       if (memcmp(rtag, tag, tn)) {
218         fprintf(stderr, "Tag mismatch\n");
219         hexdump(stderr, "Got", rtag, tn);
220         hexdump(stderr, "Expected", tag, tn);
221         exit(9);
222       }
223     }
224   }
225
226   if (encdec <= 0) {
227     if (mode == EVP_CIPH_GCM_MODE) {
228       if (!EVP_DecryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
229         fprintf(stderr, "EncryptInit failed\n");
230         BIO_print_errors_fp(stderr);
231         exit(10);
232       }
233       if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) {
234         fprintf(stderr, "IV length set failed\n");
235         BIO_print_errors_fp(stderr);
236         exit(11);
237       }
238       if (!EVP_DecryptInit_ex(&ctx, NULL, NULL, key, iv)) {
239         fprintf(stderr, "Key/IV set failed\n");
240         BIO_print_errors_fp(stderr);
241         exit(12);
242       }
243       if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, tn, (void *)tag)) {
244         fprintf(stderr, "Set tag failed\n");
245         BIO_print_errors_fp(stderr);
246         exit(14);
247       }
248       if (an && !EVP_DecryptUpdate(&ctx, NULL, &outl, aad, an)) {
249         fprintf(stderr, "AAD set failed\n");
250         BIO_print_errors_fp(stderr);
251         exit(13);
252       }
253     } else if (!EVP_DecryptInit_ex(&ctx, c, NULL, key, iv)) {
254       fprintf(stderr, "DecryptInit failed\n");
255       BIO_print_errors_fp(stderr);
256       exit(11);
257     }
258     EVP_CIPHER_CTX_set_padding(&ctx, 0);
259
260     if (!EVP_DecryptUpdate(&ctx, out, &outl, ciphertext, cn)) {
261       fprintf(stderr, "Decrypt failed\n");
262       BIO_print_errors_fp(stderr);
263       exit(6);
264     }
265     outl2 = 0;
266     if (!EVP_DecryptFinal_ex(&ctx, out + outl, &outl2)) {
267       fprintf(stderr, "DecryptFinal failed\n");
268       BIO_print_errors_fp(stderr);
269       exit(7);
270     }
271
272     if (outl + outl2 != pn) {
273       fprintf(stderr, "Plaintext length mismatch got %d expected %d\n",
274               outl + outl2, pn);
275       exit(8);
276     }
277
278     if (memcmp(out, plaintext, pn)) {
279       fprintf(stderr, "Plaintext mismatch\n");
280       hexdump(stderr, "Got", out, pn);
281       hexdump(stderr, "Expected", plaintext, pn);
282       exit(9);
283     }
284   }
285
286   EVP_CIPHER_CTX_cleanup(&ctx);
287
288   printf("\n");
289 }
290
291 static int test_cipher(const char *cipher, const uint8_t *key, int kn,
292                        const uint8_t *iv, int in, const uint8_t *plaintext,
293                        int pn, const uint8_t *ciphertext, int cn,
294                        const uint8_t *aad, int an, const uint8_t *tag, int tn,
295                        int encdec) {
296   const EVP_CIPHER *c;
297
298   if (strcmp(cipher, "DES-CBC") == 0) {
299     c = EVP_des_cbc();
300   } else if (strcmp(cipher, "DES-EDE3-CBC") == 0) {
301     c = EVP_des_ede3_cbc();
302   } else if (strcmp(cipher, "RC4") == 0) {
303     c = EVP_rc4();
304   } else if (strcmp(cipher, "AES-128-ECB") == 0) {
305     c = EVP_aes_128_ecb();
306   } else if (strcmp(cipher, "AES-256-ECB") == 0) {
307     c = EVP_aes_256_ecb();
308   } else if (strcmp(cipher, "AES-128-CBC") == 0) {
309     c = EVP_aes_128_cbc();
310   } else if (strcmp(cipher, "AES-128-GCM") == 0) {
311     c = EVP_aes_128_gcm();
312   } else if (strcmp(cipher, "AES-256-CBC") == 0) {
313     c = EVP_aes_256_cbc();
314   } else if (strcmp(cipher, "AES-128-CTR") == 0) {
315     c = EVP_aes_128_ctr();
316   } else if (strcmp(cipher, "AES-256-CTR") == 0) {
317     c = EVP_aes_256_ctr();
318   } else if (strcmp(cipher, "AES-256-GCM") == 0) {
319     c = EVP_aes_256_gcm();
320   } else {
321     fprintf(stderr, "Unknown cipher type %s\n", cipher);
322     return 0;
323   }
324
325   test1(c, key, kn, iv, in, plaintext, pn, ciphertext, cn, aad, an, tag, tn,
326         encdec);
327
328   return 1;
329 }
330
331 int main(int argc, char **argv) {
332   const char *input_file;
333   FILE *f;
334
335   CRYPTO_library_init();
336
337   if (argc != 2) {
338     fprintf(stderr, "%s <test file>\n", argv[0]);
339     return 1;
340   }
341
342   input_file = argv[1];
343
344   f = fopen(input_file, "r");
345   if (!f) {
346     perror(input_file);
347     return 2;
348   }
349
350   ERR_load_crypto_strings();
351
352   for (;;) {
353     char line[4096];
354     char *p;
355     char *cipher;
356     uint8_t *iv, *key, *plaintext, *ciphertext, *aad, *tag;
357     int encdec;
358     int kn, in, pn, cn;
359     int an = 0;
360     int tn = 0;
361
362     if (!fgets((char *)line, sizeof line, f)) {
363       break;
364     }
365     if (line[0] == '#' || line[0] == '\n') {
366       continue;
367     }
368     p = line;
369     cipher = sstrsep(&p, ":");
370     key = ustrsep(&p, ":");
371     iv = ustrsep(&p, ":");
372     plaintext = ustrsep(&p, ":");
373     ciphertext = ustrsep(&p, ":");
374     if (p[-1] == '\n') {
375       encdec = -1;
376       p[-1] = '\0';
377       tag = aad = NULL;
378       an = tn = 0;
379     } else {
380       aad = ustrsep(&p, ":");
381       tag = ustrsep(&p, ":");
382       if (tag == NULL) {
383         p = (char *)aad;
384         tag = aad = NULL;
385         an = tn = 0;
386       }
387       if (p[-1] == '\n') {
388         encdec = -1;
389         p[-1] = '\0';
390       } else
391         encdec = atoi(sstrsep(&p, "\n"));
392     }
393
394     kn = convert(key);
395     in = convert(iv);
396     pn = convert(plaintext);
397     cn = convert(ciphertext);
398     if (aad) {
399       an = convert(aad);
400       tn = convert(tag);
401     }
402
403     if (!test_cipher(cipher, key, kn, iv, in, plaintext, pn, ciphertext, cn,
404                      aad, an, tag, tn, encdec)) {
405       return 3;
406     }
407   }
408   fclose(f);
409
410   printf("PASS\n");
411   return 0;
412 }