]>
Commit | Line | Data |
---|---|---|
307e3978 | 1 | /* evp_test.c */ |
0e360199 | 2 | /* |
307e3978 DSH |
3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
4 | * project. | |
5 | */ | |
6 | /* ==================================================================== | |
7 | * Copyright (c) 2015 The OpenSSL Project. All rights reserved. | |
0e360199 BL |
8 | * |
9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
12 | * | |
13 | * 1. Redistributions of source code must retain the above copyright | |
0f113f3e | 14 | * notice, this list of conditions and the following disclaimer. |
0e360199 BL |
15 | * |
16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in | |
18 | * the documentation and/or other materials provided with the | |
19 | * distribution. | |
20 | * | |
21 | * 3. All advertising materials mentioning features or use of this | |
22 | * software must display the following acknowledgment: | |
23 | * "This product includes software developed by the OpenSSL Project | |
307e3978 | 24 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" |
0e360199 BL |
25 | * |
26 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
27 | * endorse or promote products derived from this software without | |
28 | * prior written permission. For written permission, please contact | |
307e3978 | 29 | * licensing@OpenSSL.org. |
0e360199 BL |
30 | * |
31 | * 5. Products derived from this software may not be called "OpenSSL" | |
32 | * nor may "OpenSSL" appear in their names without prior written | |
33 | * permission of the OpenSSL Project. | |
34 | * | |
35 | * 6. Redistributions of any form whatsoever must retain the following | |
36 | * acknowledgment: | |
37 | * "This product includes software developed by the OpenSSL Project | |
307e3978 | 38 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" |
0e360199 BL |
39 | * |
40 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
41 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
43 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
44 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
45 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
47 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
49 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
50 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
51 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
307e3978 | 52 | * ==================================================================== |
0e360199 BL |
53 | */ |
54 | ||
55 | #include <stdio.h> | |
56 | #include <string.h> | |
307e3978 DSH |
57 | #include <stdlib.h> |
58 | #include <ctype.h> | |
0e360199 | 59 | #include <openssl/evp.h> |
0b13e9f0 | 60 | #include <openssl/err.h> |
307e3978 | 61 | #include <openssl/x509v3.h> |
0e360199 | 62 | |
307e3978 DSH |
63 | /* Remove spaces from beginning and end of a string */ |
64 | ||
65 | static void remove_space(char **pval) | |
0f113f3e | 66 | { |
307e3978 | 67 | unsigned char *p = (unsigned char *)*pval; |
0f113f3e | 68 | |
307e3978 DSH |
69 | while (isspace(*p)) |
70 | p++; | |
71 | ||
72 | *pval = (char *)p; | |
73 | ||
74 | p = p + strlen(*pval) - 1; | |
75 | ||
76 | /* Remove trailing space */ | |
77 | while (isspace(*p)) | |
78 | *p-- = 0; | |
0f113f3e | 79 | } |
0e360199 | 80 | |
307e3978 DSH |
81 | /* |
82 | * Given a line of the form: | |
83 | * name = value # comment | |
84 | * extract name and value. NB: modifies passed buffer. | |
85 | */ | |
86 | ||
87 | static int parse_line(char **pkw, char **pval, char *linebuf) | |
0f113f3e | 88 | { |
307e3978 | 89 | char *p; |
0e360199 | 90 | |
307e3978 | 91 | p = linebuf + strlen(linebuf) - 1; |
0f113f3e | 92 | |
307e3978 DSH |
93 | if (*p != '\n') { |
94 | fprintf(stderr, "FATAL: missing EOL\n"); | |
95 | exit(1); | |
0e360199 BL |
96 | } |
97 | ||
307e3978 | 98 | /* Look for # */ |
5b46eee0 | 99 | |
307e3978 | 100 | p = strchr(linebuf, '#'); |
5b46eee0 | 101 | |
307e3978 DSH |
102 | if (p) |
103 | *p = '\0'; | |
5b46eee0 | 104 | |
307e3978 DSH |
105 | /* Look for = sign */ |
106 | p = strchr(linebuf, '='); | |
5b46eee0 | 107 | |
307e3978 DSH |
108 | /* If no '=' exit */ |
109 | if (!p) | |
110 | return 0; | |
5b46eee0 | 111 | |
307e3978 | 112 | *p++ = '\0'; |
5b46eee0 | 113 | |
307e3978 DSH |
114 | *pkw = linebuf; |
115 | *pval = p; | |
5b46eee0 | 116 | |
307e3978 DSH |
117 | /* Remove spaces from keyword and value */ |
118 | remove_space(pkw); | |
119 | remove_space(pval); | |
120 | ||
121 | return 1; | |
0f113f3e | 122 | } |
0e360199 | 123 | |
307e3978 DSH |
124 | /* For a hex string "value" convert to a binary allocated buffer */ |
125 | static int test_bin(const char *value, unsigned char **buf, size_t *buflen) | |
0f113f3e | 126 | { |
307e3978 DSH |
127 | long len; |
128 | if (!*value) { | |
129 | /* Don't return NULL for zero length buffer */ | |
130 | *buf = OPENSSL_malloc(1); | |
131 | if (!*buf) | |
132 | return 0; | |
133 | **buf = 0; | |
134 | *buflen = 0; | |
135 | return 1; | |
136 | } | |
83251f39 DSH |
137 | /* Check for string literal */ |
138 | if (value[0] == '"') { | |
139 | size_t vlen; | |
140 | value++; | |
141 | vlen = strlen(value); | |
142 | if (value[vlen - 1] != '"') | |
143 | return 0; | |
144 | vlen--; | |
145 | *buf = BUF_memdup(value, vlen); | |
146 | *buflen = vlen; | |
147 | return 1; | |
148 | } | |
307e3978 DSH |
149 | *buf = string_to_hex(value, &len); |
150 | if (!*buf) { | |
151 | fprintf(stderr, "Value=%s\n", value); | |
152 | ERR_print_errors_fp(stderr); | |
153 | return -1; | |
154 | } | |
155 | /* Size of input buffer means we'll never overflow */ | |
156 | *buflen = len; | |
157 | return 1; | |
0f113f3e | 158 | } |
848f735a | 159 | |
307e3978 DSH |
160 | /* Structure holding test information */ |
161 | struct evp_test { | |
162 | /* method for this test */ | |
163 | const struct evp_test_method *meth; | |
164 | /* current line being processed */ | |
165 | unsigned int line; | |
166 | /* start line of current test */ | |
167 | unsigned int start_line; | |
168 | /* Error string for test */ | |
169 | const char *err; | |
170 | /* Expected error value of test */ | |
171 | char *expected_err; | |
172 | /* Number of tests */ | |
173 | int ntests; | |
174 | /* Error count */ | |
175 | int errors; | |
b033e5d5 DSH |
176 | /* If output mismatch expected and got value */ |
177 | unsigned char *out_got; | |
178 | unsigned char *out_expected; | |
179 | size_t out_len; | |
307e3978 DSH |
180 | /* test specific data */ |
181 | void *data; | |
182 | }; | |
183 | /* Test method structure */ | |
184 | struct evp_test_method { | |
185 | /* Name of test as it appears in file */ | |
186 | const char *name; | |
187 | /* Initialise test for "alg" */ | |
188 | int (*init) (struct evp_test * t, const char *alg); | |
189 | /* Clean up method */ | |
190 | void (*cleanup) (struct evp_test * t); | |
191 | /* Test specific name value pair processing */ | |
192 | int (*parse) (struct evp_test * t, const char *name, const char *value); | |
193 | /* Run the test itself */ | |
194 | int (*run_test) (struct evp_test * t); | |
195 | }; | |
196 | ||
197 | static const struct evp_test_method digest_test_method, cipher_test_method; | |
83251f39 | 198 | static const struct evp_test_method aead_test_method, mac_test_method; |
307e3978 DSH |
199 | |
200 | static const struct evp_test_method *evp_test_list[] = { | |
201 | &digest_test_method, | |
202 | &cipher_test_method, | |
83251f39 DSH |
203 | &mac_test_method, |
204 | NULL | |
307e3978 DSH |
205 | }; |
206 | ||
207 | static const struct evp_test_method *evp_find_test(const char *name) | |
0f113f3e | 208 | { |
307e3978 DSH |
209 | const struct evp_test_method **tt; |
210 | for (tt = evp_test_list; *tt; tt++) { | |
211 | if (!strcmp(name, (*tt)->name)) | |
212 | return *tt; | |
213 | } | |
214 | return NULL; | |
0f113f3e MC |
215 | } |
216 | ||
b033e5d5 DSH |
217 | static void hex_print(const char *name, const unsigned char *buf, size_t len) |
218 | { | |
219 | size_t i; | |
220 | fprintf(stderr, "%s ", name); | |
221 | for (i = 0; i < len; i++) | |
222 | fprintf(stderr, "%02X", buf[i]); | |
223 | fputs("\n", stderr); | |
224 | } | |
225 | ||
226 | static void print_expected(struct evp_test *t) | |
227 | { | |
228 | if (t->out_expected == NULL) | |
229 | return; | |
230 | hex_print("Expected:", t->out_expected, t->out_len); | |
231 | hex_print("Got: ", t->out_got, t->out_len); | |
232 | OPENSSL_free(t->out_expected); | |
233 | OPENSSL_free(t->out_got); | |
234 | t->out_expected = NULL; | |
235 | t->out_got = NULL; | |
236 | } | |
237 | ||
307e3978 | 238 | static int check_test_error(struct evp_test *t) |
0f113f3e | 239 | { |
307e3978 DSH |
240 | if (!t->err && !t->expected_err) |
241 | return 1; | |
242 | if (t->err && !t->expected_err) { | |
243 | fprintf(stderr, "Test line %d: unexpected error %s\n", | |
244 | t->start_line, t->err); | |
b033e5d5 | 245 | print_expected(t); |
307e3978 | 246 | return 0; |
0f113f3e | 247 | } |
307e3978 DSH |
248 | if (!t->err && t->expected_err) { |
249 | fprintf(stderr, "Test line %d: succeeded expecting %s\n", | |
250 | t->start_line, t->expected_err); | |
251 | return 0; | |
252 | } | |
253 | if (!strcmp(t->err, t->expected_err)) | |
254 | return 1; | |
544a2aea | 255 | |
307e3978 DSH |
256 | fprintf(stderr, "Test line %d: expecting %s got %s\n", |
257 | t->start_line, t->expected_err, t->err); | |
258 | return 0; | |
259 | } | |
0f113f3e | 260 | |
307e3978 | 261 | /* Setup a new test, run any existing test */ |
0f113f3e | 262 | |
307e3978 DSH |
263 | static int setup_test(struct evp_test *t, const struct evp_test_method *tmeth) |
264 | { | |
265 | /* If we already have a test set up run it */ | |
266 | if (t->meth) { | |
267 | t->ntests++; | |
268 | t->err = NULL; | |
269 | if (t->meth->run_test(t) != 1) { | |
270 | fprintf(stderr, "%s test error line %d\n", | |
271 | t->meth->name, t->start_line); | |
272 | return 0; | |
0f113f3e | 273 | } |
307e3978 DSH |
274 | if (!check_test_error(t)) { |
275 | if (t->err) | |
0f113f3e | 276 | ERR_print_errors_fp(stderr); |
307e3978 | 277 | t->errors++; |
0f113f3e | 278 | } |
307e3978 DSH |
279 | ERR_clear_error(); |
280 | t->meth->cleanup(t); | |
281 | /* If new test type free old data */ | |
282 | if (tmeth != t->meth && t->data) { | |
283 | OPENSSL_free(t->data); | |
284 | t->data = NULL; | |
0f113f3e | 285 | } |
307e3978 DSH |
286 | if (t->expected_err) { |
287 | OPENSSL_free(t->expected_err); | |
288 | t->expected_err = NULL; | |
0f113f3e | 289 | } |
307e3978 DSH |
290 | } |
291 | t->meth = tmeth; | |
292 | return 1; | |
293 | } | |
0f113f3e | 294 | |
307e3978 DSH |
295 | static int process_test(struct evp_test *t, char *buf, int verbose) |
296 | { | |
297 | char *keyword, *value; | |
298 | int rv = 0; | |
299 | const struct evp_test_method *tmeth; | |
300 | if (verbose) | |
301 | fputs(buf, stdout); | |
302 | if (!parse_line(&keyword, &value, buf)) | |
303 | return 1; | |
304 | /* See if keyword corresponds to a test start */ | |
305 | tmeth = evp_find_test(keyword); | |
306 | if (tmeth) { | |
307 | if (!setup_test(t, tmeth)) | |
308 | return 0; | |
309 | t->start_line = t->line; | |
310 | if (!tmeth->init(t, value)) { | |
311 | fprintf(stderr, "Unknown %s: %s\n", keyword, value); | |
312 | return 0; | |
0f113f3e | 313 | } |
307e3978 DSH |
314 | return 1; |
315 | } else if (!strcmp(keyword, "Result")) { | |
316 | if (t->expected_err) { | |
317 | fprintf(stderr, "Line %d: multiple result lines\n", t->line); | |
318 | return 0; | |
0f113f3e | 319 | } |
307e3978 DSH |
320 | t->expected_err = BUF_strdup(value); |
321 | if (!t->expected_err) | |
322 | return 0; | |
323 | } else { | |
324 | /* Must be test specific line: try to parse it */ | |
325 | if (t->meth) | |
326 | rv = t->meth->parse(t, keyword, value); | |
327 | ||
328 | if (rv == 0) | |
329 | fprintf(stderr, "line %d: unexpected keyword %s\n", | |
330 | t->line, keyword); | |
331 | ||
332 | if (rv < 0) | |
333 | fprintf(stderr, "line %d: error processing keyword %s\n", | |
334 | t->line, keyword); | |
335 | if (rv <= 0) | |
336 | return 0; | |
0f113f3e | 337 | } |
307e3978 DSH |
338 | return 1; |
339 | } | |
0f113f3e | 340 | |
b033e5d5 DSH |
341 | static int check_output(struct evp_test *t, const unsigned char *expected, |
342 | const unsigned char *got, size_t len) | |
343 | { | |
344 | if (!memcmp(expected, got, len)) | |
345 | return 0; | |
346 | t->out_expected = BUF_memdup(expected, len); | |
347 | t->out_got = BUF_memdup(got, len); | |
348 | t->out_len = len; | |
349 | if (t->out_expected == NULL || t->out_got == NULL) { | |
350 | fprintf(stderr, "Memory allocation error!\n"); | |
351 | exit(1); | |
352 | } | |
353 | return 1; | |
354 | } | |
355 | ||
307e3978 DSH |
356 | int main(int argc, char **argv) |
357 | { | |
358 | FILE *in = NULL; | |
359 | char buf[10240]; | |
360 | struct evp_test t; | |
0f113f3e | 361 | |
b033e5d5 DSH |
362 | if (argc != 2) { |
363 | fprintf(stderr, "usage: evp_test testfile.txt\n"); | |
364 | return 1; | |
365 | } | |
366 | ||
307e3978 DSH |
367 | ERR_load_crypto_strings(); |
368 | OpenSSL_add_all_algorithms(); | |
369 | t.meth = NULL; | |
370 | t.err = NULL; | |
371 | t.line = 0; | |
372 | t.start_line = -1; | |
373 | t.errors = 0; | |
374 | t.ntests = 0; | |
b033e5d5 DSH |
375 | t.out_expected = NULL; |
376 | t.out_got = NULL; | |
377 | t.out_len = 0; | |
307e3978 DSH |
378 | in = fopen(argv[1], "r"); |
379 | while (fgets(buf, sizeof(buf), in)) { | |
380 | t.line++; | |
381 | if (!process_test(&t, buf, 0)) | |
382 | exit(1); | |
383 | } | |
384 | /* Run any final test we have */ | |
385 | if (!setup_test(&t, NULL)) | |
386 | exit(1); | |
387 | fprintf(stderr, "%d tests completed with %d errors\n", | |
388 | t.ntests, t.errors); | |
389 | fclose(in); | |
6906a7c1 DSH |
390 | if (t.errors) |
391 | return 1; | |
307e3978 | 392 | return 0; |
0f113f3e MC |
393 | } |
394 | ||
307e3978 | 395 | static void test_free(void *d) |
0f113f3e | 396 | { |
307e3978 DSH |
397 | if (d) |
398 | OPENSSL_free(d); | |
399 | } | |
4897dc40 | 400 | |
307e3978 | 401 | /* Message digest tests */ |
4897dc40 | 402 | |
307e3978 DSH |
403 | struct digest_data { |
404 | /* Digest this test is for */ | |
405 | const EVP_MD *digest; | |
406 | /* Input to digest */ | |
407 | unsigned char *input; | |
408 | size_t input_len; | |
409 | /* Expected output */ | |
410 | unsigned char *output; | |
411 | size_t output_len; | |
412 | }; | |
4897dc40 | 413 | |
307e3978 DSH |
414 | static int digest_test_init(struct evp_test *t, const char *alg) |
415 | { | |
416 | const EVP_MD *digest; | |
417 | struct digest_data *mdat = t->data; | |
418 | digest = EVP_get_digestbyname(alg); | |
419 | if (!digest) | |
420 | return 0; | |
421 | mdat = OPENSSL_malloc(sizeof(struct digest_data)); | |
422 | mdat->digest = digest; | |
423 | mdat->input = NULL; | |
424 | mdat->output = NULL; | |
425 | t->data = mdat; | |
4897dc40 | 426 | return 1; |
0f113f3e | 427 | } |
4897dc40 | 428 | |
307e3978 DSH |
429 | static void digest_test_cleanup(struct evp_test *t) |
430 | { | |
431 | struct digest_data *mdat = t->data; | |
432 | test_free(mdat->input); | |
433 | test_free(mdat->output); | |
434 | } | |
435 | ||
436 | static int digest_test_parse(struct evp_test *t, | |
437 | const char *keyword, const char *value) | |
438 | { | |
439 | struct digest_data *mdata = t->data; | |
440 | if (!strcmp(keyword, "Input")) | |
441 | return test_bin(value, &mdata->input, &mdata->input_len); | |
442 | if (!strcmp(keyword, "Output")) | |
443 | return test_bin(value, &mdata->output, &mdata->output_len); | |
444 | return 0; | |
445 | } | |
446 | ||
447 | static int digest_test_run(struct evp_test *t) | |
0f113f3e | 448 | { |
307e3978 DSH |
449 | struct digest_data *mdata = t->data; |
450 | const char *err = "INTERNAL_ERROR"; | |
451 | EVP_MD_CTX *mctx; | |
4897dc40 | 452 | unsigned char md[EVP_MAX_MD_SIZE]; |
307e3978 DSH |
453 | unsigned int md_len; |
454 | mctx = EVP_MD_CTX_create(); | |
455 | if (!mctx) | |
456 | goto err; | |
457 | err = "DIGESTINIT_ERROR"; | |
458 | if (!EVP_DigestInit_ex(mctx, mdata->digest, NULL)) | |
459 | goto err; | |
460 | err = "DIGESTUPDATE_ERROR"; | |
461 | if (!EVP_DigestUpdate(mctx, mdata->input, mdata->input_len)) | |
462 | goto err; | |
463 | err = "DIGESTFINAL_ERROR"; | |
464 | if (!EVP_DigestFinal(mctx, md, &md_len)) | |
465 | goto err; | |
466 | err = "DIGEST_LENGTH_MISMATCH"; | |
467 | if (md_len != mdata->output_len) | |
468 | goto err; | |
469 | err = "DIGEST_MISMATCH"; | |
b033e5d5 | 470 | if (check_output(t, mdata->output, md, md_len)) |
307e3978 DSH |
471 | goto err; |
472 | err = NULL; | |
473 | err: | |
474 | if (mctx) | |
475 | EVP_MD_CTX_destroy(mctx); | |
476 | t->err = err; | |
b033e5d5 | 477 | return 1; |
307e3978 | 478 | } |
4897dc40 | 479 | |
307e3978 DSH |
480 | static const struct evp_test_method digest_test_method = { |
481 | "Digest", | |
482 | digest_test_init, | |
483 | digest_test_cleanup, | |
484 | digest_test_parse, | |
485 | digest_test_run | |
486 | }; | |
487 | ||
488 | /* Cipher tests */ | |
489 | struct cipher_data { | |
490 | const EVP_CIPHER *cipher; | |
491 | int enc; | |
492 | /* Set to EVP_CIPH_GCM_MODE or EVP_CIPH_CCM_MODE if AEAD */ | |
493 | int aead; | |
494 | unsigned char *key; | |
495 | size_t key_len; | |
496 | unsigned char *iv; | |
497 | size_t iv_len; | |
498 | unsigned char *plaintext; | |
499 | size_t plaintext_len; | |
500 | unsigned char *ciphertext; | |
501 | size_t ciphertext_len; | |
502 | /* GCM, CCM only */ | |
503 | unsigned char *aad; | |
504 | size_t aad_len; | |
505 | unsigned char *tag; | |
506 | size_t tag_len; | |
507 | }; | |
508 | ||
509 | static int cipher_test_init(struct evp_test *t, const char *alg) | |
510 | { | |
511 | const EVP_CIPHER *cipher; | |
512 | struct cipher_data *cdat = t->data; | |
513 | cipher = EVP_get_cipherbyname(alg); | |
514 | if (!cipher) | |
0f113f3e | 515 | return 0; |
307e3978 DSH |
516 | cdat = OPENSSL_malloc(sizeof(struct cipher_data)); |
517 | cdat->cipher = cipher; | |
518 | cdat->enc = -1; | |
519 | cdat->key = NULL; | |
520 | cdat->iv = NULL; | |
521 | cdat->ciphertext = NULL; | |
522 | cdat->plaintext = NULL; | |
523 | cdat->aad = NULL; | |
524 | cdat->tag = NULL; | |
525 | t->data = cdat; | |
526 | if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE | |
527 | || EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE) | |
528 | cdat->aead = EVP_CIPHER_mode(cipher); | |
529 | else | |
530 | cdat->aead = 0; | |
4897dc40 | 531 | |
307e3978 DSH |
532 | return 1; |
533 | } | |
4897dc40 | 534 | |
307e3978 DSH |
535 | static void cipher_test_cleanup(struct evp_test *t) |
536 | { | |
537 | struct cipher_data *cdat = t->data; | |
538 | test_free(cdat->key); | |
539 | test_free(cdat->iv); | |
540 | test_free(cdat->ciphertext); | |
541 | test_free(cdat->plaintext); | |
542 | test_free(cdat->aad); | |
543 | test_free(cdat->tag); | |
544 | } | |
4897dc40 | 545 | |
307e3978 DSH |
546 | static int cipher_test_parse(struct evp_test *t, const char *keyword, |
547 | const char *value) | |
548 | { | |
549 | struct cipher_data *cdat = t->data; | |
550 | if (!strcmp(keyword, "Key")) | |
551 | return test_bin(value, &cdat->key, &cdat->key_len); | |
552 | if (!strcmp(keyword, "IV")) | |
553 | return test_bin(value, &cdat->iv, &cdat->iv_len); | |
554 | if (!strcmp(keyword, "Plaintext")) | |
555 | return test_bin(value, &cdat->plaintext, &cdat->plaintext_len); | |
556 | if (!strcmp(keyword, "Ciphertext")) | |
557 | return test_bin(value, &cdat->ciphertext, &cdat->ciphertext_len); | |
558 | if (cdat->aead) { | |
559 | if (!strcmp(keyword, "AAD")) | |
560 | return test_bin(value, &cdat->aad, &cdat->aad_len); | |
561 | if (!strcmp(keyword, "Tag")) | |
562 | return test_bin(value, &cdat->tag, &cdat->tag_len); | |
0f113f3e | 563 | } |
4897dc40 | 564 | |
307e3978 DSH |
565 | if (!strcmp(keyword, "Operation")) { |
566 | if (!strcmp(value, "ENCRYPT")) | |
567 | cdat->enc = 1; | |
568 | else if (!strcmp(value, "DECRYPT")) | |
569 | cdat->enc = 0; | |
570 | else | |
571 | return 0; | |
572 | return 1; | |
0f113f3e | 573 | } |
307e3978 | 574 | return 0; |
0f113f3e | 575 | } |
4897dc40 | 576 | |
307e3978 | 577 | static int cipher_test_enc(struct evp_test *t, int enc) |
0f113f3e | 578 | { |
307e3978 DSH |
579 | struct cipher_data *cdat = t->data; |
580 | unsigned char *in, *out, *tmp = NULL; | |
581 | size_t in_len, out_len; | |
582 | int tmplen, tmpflen; | |
583 | EVP_CIPHER_CTX *ctx = NULL; | |
584 | const char *err; | |
585 | err = "INTERNAL_ERROR"; | |
586 | ctx = EVP_CIPHER_CTX_new(); | |
587 | if (!ctx) | |
588 | goto err; | |
589 | EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); | |
590 | if (enc) { | |
591 | in = cdat->plaintext; | |
592 | in_len = cdat->plaintext_len; | |
593 | out = cdat->ciphertext; | |
594 | out_len = cdat->ciphertext_len; | |
595 | } else { | |
596 | in = cdat->ciphertext; | |
597 | in_len = cdat->ciphertext_len; | |
598 | out = cdat->plaintext; | |
599 | out_len = cdat->plaintext_len; | |
0f113f3e | 600 | } |
307e3978 DSH |
601 | tmp = OPENSSL_malloc(in_len + 2 * EVP_MAX_BLOCK_LENGTH); |
602 | if (!tmp) | |
603 | goto err; | |
604 | err = "CIPHERINIT_ERROR"; | |
605 | if (!EVP_CipherInit_ex(ctx, cdat->cipher, NULL, NULL, NULL, enc)) | |
606 | goto err; | |
607 | err = "INVALID_IV_LENGTH"; | |
608 | if (cdat->iv) { | |
609 | if (cdat->aead == EVP_CIPH_GCM_MODE) { | |
610 | if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, | |
611 | cdat->iv_len, 0)) | |
612 | goto err; | |
613 | } else if (cdat->aead == EVP_CIPH_CCM_MODE) { | |
614 | if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, | |
615 | cdat->iv_len, 0)) | |
616 | goto err; | |
617 | } else if (cdat->iv_len != (size_t)EVP_CIPHER_CTX_iv_length(ctx)) | |
618 | goto err; | |
0f113f3e | 619 | } |
307e3978 DSH |
620 | if (cdat->aead) { |
621 | unsigned char *tag; | |
622 | /* | |
623 | * If encrypting just set tag length. If decrypting set | |
624 | * tag length and value. | |
625 | */ | |
626 | if (enc) { | |
627 | err = "TAG_LENGTH_SET_ERROR"; | |
628 | tag = NULL; | |
0f113f3e | 629 | } else { |
307e3978 DSH |
630 | err = "TAG_SET_ERROR"; |
631 | tag = cdat->tag; | |
0f113f3e | 632 | } |
307e3978 DSH |
633 | if (cdat->aead == EVP_CIPH_GCM_MODE && tag) { |
634 | if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, | |
635 | cdat->tag_len, tag)) | |
636 | goto err; | |
637 | } else if (cdat->aead == EVP_CIPH_CCM_MODE) { | |
638 | if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, | |
639 | cdat->tag_len, tag)) | |
640 | goto err; | |
0f113f3e | 641 | } |
307e3978 | 642 | } |
0f113f3e | 643 | |
307e3978 DSH |
644 | err = "INVALID_KEY_LENGTH"; |
645 | if (!EVP_CIPHER_CTX_set_key_length(ctx, cdat->key_len)) | |
646 | goto err; | |
647 | err = "KEY_SET_ERROR"; | |
648 | if (!EVP_CipherInit_ex(ctx, NULL, NULL, cdat->key, cdat->iv, -1)) | |
649 | goto err; | |
650 | ||
651 | if (cdat->aead == EVP_CIPH_CCM_MODE) { | |
652 | if (!EVP_CipherUpdate(ctx, NULL, &tmplen, NULL, out_len)) { | |
653 | err = "CCM_PLAINTEXT_LENGTH_SET_ERROR"; | |
654 | goto err; | |
0f113f3e MC |
655 | } |
656 | } | |
307e3978 DSH |
657 | if (cdat->aad) { |
658 | if (!EVP_CipherUpdate(ctx, NULL, &tmplen, cdat->aad, cdat->aad_len)) { | |
659 | err = "AAD_SET_ERROR"; | |
660 | goto err; | |
661 | } | |
662 | } | |
663 | EVP_CIPHER_CTX_set_padding(ctx, 0); | |
664 | err = "CIPHERUPDATE_ERROR"; | |
665 | if (!EVP_CipherUpdate(ctx, tmp, &tmplen, in, in_len)) | |
666 | goto err; | |
667 | if (cdat->aead == EVP_CIPH_CCM_MODE) | |
668 | tmpflen = 0; | |
669 | else { | |
670 | err = "CIPHERFINAL_ERROR"; | |
671 | if (!EVP_CipherFinal_ex(ctx, tmp + tmplen, &tmpflen)) | |
672 | goto err; | |
673 | } | |
674 | err = "LENGTH_MISMATCH"; | |
675 | if (out_len != (size_t)(tmplen + tmpflen)) | |
676 | goto err; | |
677 | err = "VALUE_MISMATCH"; | |
b033e5d5 | 678 | if (check_output(t, out, tmp, out_len)) |
307e3978 DSH |
679 | goto err; |
680 | if (enc && cdat->aead) { | |
681 | unsigned char rtag[16]; | |
682 | if (cdat->tag_len > sizeof(rtag)) { | |
683 | err = "TAG_LENGTH_INTERNAL_ERROR"; | |
684 | goto err; | |
685 | } | |
686 | /* EVP_CTRL_CCM_GET_TAG and EVP_CTRL_GCM_GET_TAG are equal. */ | |
687 | if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, | |
688 | cdat->tag_len, rtag)) { | |
689 | err = "TAG_RETRIEVE_ERROR"; | |
690 | goto err; | |
691 | } | |
b033e5d5 | 692 | if (check_output(t, cdat->tag, rtag, cdat->tag_len)) { |
307e3978 DSH |
693 | err = "TAG_VALUE_MISMATCH"; |
694 | goto err; | |
695 | } | |
696 | } | |
697 | err = NULL; | |
698 | err: | |
699 | if (tmp) | |
700 | OPENSSL_free(tmp); | |
701 | EVP_CIPHER_CTX_free(ctx); | |
702 | t->err = err; | |
703 | return err ? 0 : 1; | |
704 | } | |
0e360199 | 705 | |
307e3978 DSH |
706 | static int cipher_test_run(struct evp_test *t) |
707 | { | |
708 | struct cipher_data *cdat = t->data; | |
709 | int rv; | |
710 | if (!cdat->key) { | |
711 | t->err = "NO_KEY"; | |
712 | return 0; | |
713 | } | |
714 | if (!cdat->iv && EVP_CIPHER_iv_length(cdat->cipher)) { | |
715 | /* IV is optional and usually omitted in wrap mode */ | |
716 | if (EVP_CIPHER_mode(cdat->cipher) != EVP_CIPH_WRAP_MODE) { | |
717 | t->err = "NO_IV"; | |
718 | return 0; | |
719 | } | |
720 | } | |
721 | if (cdat->aead && !cdat->tag) { | |
722 | t->err = "NO_TAG"; | |
723 | return 0; | |
724 | } | |
725 | if (cdat->enc) { | |
726 | rv = cipher_test_enc(t, 1); | |
727 | /* Not fatal errors: return */ | |
728 | if (rv != 1) { | |
729 | if (rv < 0) | |
730 | return 0; | |
731 | return 1; | |
732 | } | |
733 | } | |
734 | if (cdat->enc != 1) { | |
735 | rv = cipher_test_enc(t, 0); | |
736 | /* Not fatal errors: return */ | |
737 | if (rv != 1) { | |
738 | if (rv < 0) | |
739 | return 0; | |
740 | return 1; | |
741 | } | |
742 | } | |
743 | return 1; | |
0f113f3e | 744 | } |
307e3978 DSH |
745 | |
746 | static const struct evp_test_method cipher_test_method = { | |
747 | "Cipher", | |
748 | cipher_test_init, | |
749 | cipher_test_cleanup, | |
750 | cipher_test_parse, | |
751 | cipher_test_run | |
752 | }; | |
83251f39 DSH |
753 | |
754 | struct mac_data { | |
755 | /* MAC type */ | |
756 | int type; | |
757 | /* Algorithm string for this MAC */ | |
758 | char *alg; | |
759 | /* MAC key */ | |
760 | unsigned char *key; | |
761 | size_t key_len; | |
762 | /* Input to MAC */ | |
763 | unsigned char *input; | |
764 | size_t input_len; | |
765 | /* Expected output */ | |
766 | unsigned char *output; | |
767 | size_t output_len; | |
768 | }; | |
769 | ||
770 | static int mac_test_init(struct evp_test *t, const char *alg) | |
771 | { | |
772 | int type; | |
773 | struct mac_data *mdat; | |
774 | if (!strcmp(alg, "HMAC")) | |
775 | type = EVP_PKEY_HMAC; | |
776 | else if (!strcmp(alg, "CMAC")) | |
777 | type = EVP_PKEY_CMAC; | |
778 | else | |
779 | return 0; | |
780 | ||
781 | mdat = OPENSSL_malloc(sizeof(struct mac_data)); | |
782 | mdat->type = type; | |
783 | mdat->alg = NULL; | |
784 | mdat->key = NULL; | |
785 | mdat->input = NULL; | |
786 | mdat->output = NULL; | |
787 | t->data = mdat; | |
788 | return 1; | |
789 | } | |
790 | ||
791 | static void mac_test_cleanup(struct evp_test *t) | |
792 | { | |
793 | struct mac_data *mdat = t->data; | |
794 | test_free(mdat->alg); | |
795 | test_free(mdat->key); | |
796 | test_free(mdat->input); | |
797 | test_free(mdat->output); | |
798 | } | |
799 | ||
800 | static int mac_test_parse(struct evp_test *t, | |
801 | const char *keyword, const char *value) | |
802 | { | |
803 | struct mac_data *mdata = t->data; | |
804 | if (!strcmp(keyword, "Key")) | |
805 | return test_bin(value, &mdata->key, &mdata->key_len); | |
806 | if (!strcmp(keyword, "Algorithm")) { | |
807 | mdata->alg = BUF_strdup(value); | |
808 | if (!mdata->alg) | |
809 | return 0; | |
810 | return 1; | |
811 | } | |
812 | if (!strcmp(keyword, "Input")) | |
813 | return test_bin(value, &mdata->input, &mdata->input_len); | |
814 | if (!strcmp(keyword, "Output")) | |
815 | return test_bin(value, &mdata->output, &mdata->output_len); | |
816 | return 0; | |
817 | } | |
818 | ||
819 | static int mac_test_run(struct evp_test *t) | |
820 | { | |
821 | struct mac_data *mdata = t->data; | |
822 | const char *err = "INTERNAL_ERROR"; | |
823 | EVP_MD_CTX *mctx = NULL; | |
824 | EVP_PKEY_CTX *pctx = NULL, *genctx = NULL; | |
825 | EVP_PKEY *key = NULL; | |
826 | const EVP_MD *md = NULL; | |
827 | unsigned char *mac = NULL; | |
828 | size_t mac_len; | |
829 | ||
830 | err = "MAC_PKEY_CTX_ERROR"; | |
831 | genctx = EVP_PKEY_CTX_new_id(mdata->type, NULL); | |
832 | if (!genctx) | |
833 | goto err; | |
834 | ||
835 | err = "MAC_KEYGEN_INIT_ERROR"; | |
836 | if (EVP_PKEY_keygen_init(genctx) <= 0) | |
837 | goto err; | |
838 | if (mdata->type == EVP_PKEY_CMAC) { | |
839 | err = "MAC_ALGORITHM_SET_ERROR"; | |
840 | if (EVP_PKEY_CTX_ctrl_str(genctx, "cipher", mdata->alg) <= 0) | |
841 | goto err; | |
842 | } | |
843 | ||
844 | err = "MAC_KEY_SET_ERROR"; | |
845 | if (EVP_PKEY_CTX_set_mac_key(genctx, mdata->key, mdata->key_len) <= 0) | |
846 | goto err; | |
847 | ||
848 | err = "MAC_KEY_GENERATE_ERROR"; | |
849 | if (EVP_PKEY_keygen(genctx, &key) <= 0) | |
850 | goto err; | |
851 | if (mdata->type == EVP_PKEY_HMAC) { | |
852 | err = "MAC_ALGORITHM_SET_ERROR"; | |
853 | md = EVP_get_digestbyname(mdata->alg); | |
854 | if (!md) | |
855 | goto err; | |
856 | } | |
857 | mctx = EVP_MD_CTX_create(); | |
858 | if (!mctx) | |
859 | goto err; | |
860 | err = "DIGESTSIGNINIT_ERROR"; | |
861 | if (!EVP_DigestSignInit(mctx, &pctx, md, NULL, key)) | |
862 | goto err; | |
863 | ||
864 | err = "DIGESTSIGNUPDATE_ERROR"; | |
865 | if (!EVP_DigestSignUpdate(mctx, mdata->input, mdata->input_len)) | |
866 | goto err; | |
867 | err = "DIGESTSIGNFINAL_LENGTH_ERROR"; | |
868 | if (!EVP_DigestSignFinal(mctx, NULL, &mac_len)) | |
869 | goto err; | |
870 | mac = OPENSSL_malloc(mac_len); | |
871 | if (!mac) { | |
872 | fprintf(stderr, "Error allocating mac buffer!\n"); | |
873 | exit(1); | |
874 | } | |
875 | if (!EVP_DigestSignFinal(mctx, mac, &mac_len)) | |
876 | goto err; | |
877 | err = "MAC_LENGTH_MISMATCH"; | |
878 | if (mac_len != mdata->output_len) | |
879 | goto err; | |
880 | err = "MAC_MISMATCH"; | |
881 | if (check_output(t, mdata->output, mac, mac_len)) | |
882 | goto err; | |
883 | err = NULL; | |
884 | err: | |
885 | if (mctx) | |
886 | EVP_MD_CTX_destroy(mctx); | |
887 | if (mac) | |
888 | OPENSSL_free(mac); | |
889 | if (genctx) | |
890 | EVP_PKEY_CTX_free(genctx); | |
891 | if (key) | |
892 | EVP_PKEY_free(key); | |
893 | t->err = err; | |
894 | return 1; | |
895 | } | |
896 | ||
897 | static const struct evp_test_method mac_test_method = { | |
898 | "MAC", | |
899 | mac_test_init, | |
900 | mac_test_cleanup, | |
901 | mac_test_parse, | |
902 | mac_test_run | |
903 | }; |