]>
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> |
5824cc29 | 60 | #include <openssl/pem.h> |
0b13e9f0 | 61 | #include <openssl/err.h> |
307e3978 | 62 | #include <openssl/x509v3.h> |
3b53e18a | 63 | #include "internal/numbers.h" |
0e360199 | 64 | |
307e3978 DSH |
65 | /* Remove spaces from beginning and end of a string */ |
66 | ||
67 | static void remove_space(char **pval) | |
0f113f3e | 68 | { |
307e3978 | 69 | unsigned char *p = (unsigned char *)*pval; |
0f113f3e | 70 | |
307e3978 DSH |
71 | while (isspace(*p)) |
72 | p++; | |
73 | ||
74 | *pval = (char *)p; | |
75 | ||
76 | p = p + strlen(*pval) - 1; | |
77 | ||
78 | /* Remove trailing space */ | |
79 | while (isspace(*p)) | |
80 | *p-- = 0; | |
0f113f3e | 81 | } |
0e360199 | 82 | |
307e3978 DSH |
83 | /* |
84 | * Given a line of the form: | |
85 | * name = value # comment | |
86 | * extract name and value. NB: modifies passed buffer. | |
87 | */ | |
88 | ||
89 | static int parse_line(char **pkw, char **pval, char *linebuf) | |
0f113f3e | 90 | { |
307e3978 | 91 | char *p; |
0e360199 | 92 | |
307e3978 | 93 | p = linebuf + strlen(linebuf) - 1; |
0f113f3e | 94 | |
307e3978 DSH |
95 | if (*p != '\n') { |
96 | fprintf(stderr, "FATAL: missing EOL\n"); | |
97 | exit(1); | |
0e360199 BL |
98 | } |
99 | ||
307e3978 | 100 | /* Look for # */ |
5b46eee0 | 101 | |
307e3978 | 102 | p = strchr(linebuf, '#'); |
5b46eee0 | 103 | |
307e3978 DSH |
104 | if (p) |
105 | *p = '\0'; | |
5b46eee0 | 106 | |
307e3978 DSH |
107 | /* Look for = sign */ |
108 | p = strchr(linebuf, '='); | |
5b46eee0 | 109 | |
307e3978 DSH |
110 | /* If no '=' exit */ |
111 | if (!p) | |
112 | return 0; | |
5b46eee0 | 113 | |
307e3978 | 114 | *p++ = '\0'; |
5b46eee0 | 115 | |
307e3978 DSH |
116 | *pkw = linebuf; |
117 | *pval = p; | |
5b46eee0 | 118 | |
307e3978 DSH |
119 | /* Remove spaces from keyword and value */ |
120 | remove_space(pkw); | |
121 | remove_space(pval); | |
122 | ||
123 | return 1; | |
0f113f3e | 124 | } |
0e360199 | 125 | |
307e3978 DSH |
126 | /* For a hex string "value" convert to a binary allocated buffer */ |
127 | static int test_bin(const char *value, unsigned char **buf, size_t *buflen) | |
0f113f3e | 128 | { |
307e3978 DSH |
129 | long len; |
130 | if (!*value) { | |
131 | /* Don't return NULL for zero length buffer */ | |
132 | *buf = OPENSSL_malloc(1); | |
133 | if (!*buf) | |
134 | return 0; | |
135 | **buf = 0; | |
136 | *buflen = 0; | |
137 | return 1; | |
138 | } | |
83251f39 DSH |
139 | /* Check for string literal */ |
140 | if (value[0] == '"') { | |
141 | size_t vlen; | |
142 | value++; | |
143 | vlen = strlen(value); | |
144 | if (value[vlen - 1] != '"') | |
145 | return 0; | |
146 | vlen--; | |
3b53e18a DSH |
147 | if (vlen == 0) { |
148 | *buf = OPENSSL_malloc(1); | |
149 | if (*buf == NULL) | |
150 | return 0; | |
151 | **buf = 0; | |
152 | } else { | |
153 | *buf = BUF_memdup(value, vlen); | |
154 | if (*buf == NULL) | |
155 | return 0; | |
156 | } | |
83251f39 DSH |
157 | *buflen = vlen; |
158 | return 1; | |
159 | } | |
307e3978 DSH |
160 | *buf = string_to_hex(value, &len); |
161 | if (!*buf) { | |
162 | fprintf(stderr, "Value=%s\n", value); | |
163 | ERR_print_errors_fp(stderr); | |
164 | return -1; | |
165 | } | |
166 | /* Size of input buffer means we'll never overflow */ | |
167 | *buflen = len; | |
168 | return 1; | |
0f113f3e | 169 | } |
3b53e18a DSH |
170 | /* Parse unsigned decimal 64 bit integer value */ |
171 | static int test_uint64(const char *value, uint64_t *pr) | |
172 | { | |
173 | const char *p = value; | |
174 | if (!*p) { | |
175 | fprintf(stderr, "Invalid empty integer value\n"); | |
176 | return -1; | |
177 | } | |
178 | *pr = 0; | |
179 | while (*p) { | |
180 | if (*pr > UINT64_MAX/10) { | |
181 | fprintf(stderr, "Integer string overflow value=%s\n", value); | |
182 | return -1; | |
183 | } | |
184 | *pr *= 10; | |
185 | if (*p < '0' || *p > '9') { | |
186 | fprintf(stderr, "Invalid integer string value=%s\n", value); | |
187 | return -1; | |
188 | } | |
189 | *pr += *p - '0'; | |
190 | p++; | |
191 | } | |
192 | return 1; | |
193 | } | |
848f735a | 194 | |
307e3978 DSH |
195 | /* Structure holding test information */ |
196 | struct evp_test { | |
5824cc29 DSH |
197 | /* file being read */ |
198 | FILE *in; | |
199 | /* List of public and private keys */ | |
200 | struct key_list *private; | |
201 | struct key_list *public; | |
307e3978 DSH |
202 | /* method for this test */ |
203 | const struct evp_test_method *meth; | |
204 | /* current line being processed */ | |
205 | unsigned int line; | |
206 | /* start line of current test */ | |
207 | unsigned int start_line; | |
208 | /* Error string for test */ | |
209 | const char *err; | |
210 | /* Expected error value of test */ | |
211 | char *expected_err; | |
212 | /* Number of tests */ | |
213 | int ntests; | |
214 | /* Error count */ | |
215 | int errors; | |
7a6c9792 DSH |
216 | /* Number of tests skipped */ |
217 | int nskip; | |
b033e5d5 DSH |
218 | /* If output mismatch expected and got value */ |
219 | unsigned char *out_got; | |
220 | unsigned char *out_expected; | |
221 | size_t out_len; | |
307e3978 DSH |
222 | /* test specific data */ |
223 | void *data; | |
7a6c9792 DSH |
224 | /* Current test should be skipped */ |
225 | int skip; | |
307e3978 | 226 | }; |
5824cc29 DSH |
227 | |
228 | struct key_list { | |
229 | char *name; | |
230 | EVP_PKEY *key; | |
231 | struct key_list *next; | |
232 | }; | |
233 | ||
307e3978 DSH |
234 | /* Test method structure */ |
235 | struct evp_test_method { | |
236 | /* Name of test as it appears in file */ | |
237 | const char *name; | |
238 | /* Initialise test for "alg" */ | |
239 | int (*init) (struct evp_test * t, const char *alg); | |
240 | /* Clean up method */ | |
241 | void (*cleanup) (struct evp_test * t); | |
242 | /* Test specific name value pair processing */ | |
243 | int (*parse) (struct evp_test * t, const char *name, const char *value); | |
244 | /* Run the test itself */ | |
245 | int (*run_test) (struct evp_test * t); | |
246 | }; | |
247 | ||
248 | static const struct evp_test_method digest_test_method, cipher_test_method; | |
f9e31463 | 249 | static const struct evp_test_method mac_test_method; |
5824cc29 DSH |
250 | static const struct evp_test_method psign_test_method, pverify_test_method; |
251 | static const struct evp_test_method pdecrypt_test_method; | |
252 | static const struct evp_test_method pverify_recover_test_method; | |
3b53e18a | 253 | static const struct evp_test_method pbe_test_method; |
307e3978 DSH |
254 | |
255 | static const struct evp_test_method *evp_test_list[] = { | |
256 | &digest_test_method, | |
257 | &cipher_test_method, | |
83251f39 | 258 | &mac_test_method, |
5824cc29 DSH |
259 | &psign_test_method, |
260 | &pverify_test_method, | |
261 | &pdecrypt_test_method, | |
262 | &pverify_recover_test_method, | |
3b53e18a | 263 | &pbe_test_method, |
83251f39 | 264 | NULL |
307e3978 DSH |
265 | }; |
266 | ||
267 | static const struct evp_test_method *evp_find_test(const char *name) | |
0f113f3e | 268 | { |
307e3978 | 269 | const struct evp_test_method **tt; |
86885c28 | 270 | |
307e3978 | 271 | for (tt = evp_test_list; *tt; tt++) { |
86885c28 | 272 | if (strcmp(name, (*tt)->name) == 0) |
307e3978 DSH |
273 | return *tt; |
274 | } | |
275 | return NULL; | |
0f113f3e MC |
276 | } |
277 | ||
b033e5d5 DSH |
278 | static void hex_print(const char *name, const unsigned char *buf, size_t len) |
279 | { | |
280 | size_t i; | |
281 | fprintf(stderr, "%s ", name); | |
282 | for (i = 0; i < len; i++) | |
283 | fprintf(stderr, "%02X", buf[i]); | |
284 | fputs("\n", stderr); | |
285 | } | |
286 | ||
5724bd49 DSH |
287 | static void free_expected(struct evp_test *t) |
288 | { | |
b548a1f1 RS |
289 | OPENSSL_free(t->expected_err); |
290 | t->expected_err = NULL; | |
25aaa98a RS |
291 | OPENSSL_free(t->out_expected); |
292 | OPENSSL_free(t->out_got); | |
293 | t->out_expected = NULL; | |
294 | t->out_got = NULL; | |
5724bd49 DSH |
295 | } |
296 | ||
b033e5d5 DSH |
297 | static void print_expected(struct evp_test *t) |
298 | { | |
299 | if (t->out_expected == NULL) | |
300 | return; | |
301 | hex_print("Expected:", t->out_expected, t->out_len); | |
302 | hex_print("Got: ", t->out_got, t->out_len); | |
5724bd49 | 303 | free_expected(t); |
b033e5d5 DSH |
304 | } |
305 | ||
307e3978 | 306 | static int check_test_error(struct evp_test *t) |
0f113f3e | 307 | { |
307e3978 DSH |
308 | if (!t->err && !t->expected_err) |
309 | return 1; | |
310 | if (t->err && !t->expected_err) { | |
311 | fprintf(stderr, "Test line %d: unexpected error %s\n", | |
312 | t->start_line, t->err); | |
b033e5d5 | 313 | print_expected(t); |
307e3978 | 314 | return 0; |
0f113f3e | 315 | } |
307e3978 DSH |
316 | if (!t->err && t->expected_err) { |
317 | fprintf(stderr, "Test line %d: succeeded expecting %s\n", | |
318 | t->start_line, t->expected_err); | |
319 | return 0; | |
320 | } | |
86885c28 | 321 | if (strcmp(t->err, t->expected_err) == 0) |
307e3978 | 322 | return 1; |
544a2aea | 323 | |
307e3978 DSH |
324 | fprintf(stderr, "Test line %d: expecting %s got %s\n", |
325 | t->start_line, t->expected_err, t->err); | |
326 | return 0; | |
327 | } | |
0f113f3e | 328 | |
307e3978 | 329 | /* Setup a new test, run any existing test */ |
0f113f3e | 330 | |
307e3978 DSH |
331 | static int setup_test(struct evp_test *t, const struct evp_test_method *tmeth) |
332 | { | |
333 | /* If we already have a test set up run it */ | |
334 | if (t->meth) { | |
335 | t->ntests++; | |
7a6c9792 | 336 | if (t->skip) { |
578ce42d | 337 | t->meth = tmeth; |
7a6c9792 DSH |
338 | t->nskip++; |
339 | return 1; | |
340 | } | |
307e3978 DSH |
341 | t->err = NULL; |
342 | if (t->meth->run_test(t) != 1) { | |
343 | fprintf(stderr, "%s test error line %d\n", | |
344 | t->meth->name, t->start_line); | |
345 | return 0; | |
0f113f3e | 346 | } |
307e3978 DSH |
347 | if (!check_test_error(t)) { |
348 | if (t->err) | |
0f113f3e | 349 | ERR_print_errors_fp(stderr); |
307e3978 | 350 | t->errors++; |
0f113f3e | 351 | } |
307e3978 DSH |
352 | ERR_clear_error(); |
353 | t->meth->cleanup(t); | |
d5ec8efc DSH |
354 | OPENSSL_free(t->data); |
355 | t->data = NULL; | |
b548a1f1 RS |
356 | OPENSSL_free(t->expected_err); |
357 | t->expected_err = NULL; | |
5724bd49 | 358 | free_expected(t); |
307e3978 DSH |
359 | } |
360 | t->meth = tmeth; | |
361 | return 1; | |
362 | } | |
0f113f3e | 363 | |
7a6c9792 | 364 | static int find_key(EVP_PKEY **ppk, const char *name, struct key_list *lst) |
5824cc29 DSH |
365 | { |
366 | for (; lst; lst = lst->next) { | |
86885c28 | 367 | if (strcmp(lst->name, name) == 0) { |
7a6c9792 DSH |
368 | if (ppk) |
369 | *ppk = lst->key; | |
370 | return 1; | |
371 | } | |
5824cc29 | 372 | } |
7a6c9792 | 373 | return 0; |
5824cc29 DSH |
374 | } |
375 | ||
376 | static void free_key_list(struct key_list *lst) | |
377 | { | |
d5ec8efc | 378 | while (lst != NULL) { |
366448ec | 379 | struct key_list *ltmp; |
5824cc29 DSH |
380 | EVP_PKEY_free(lst->key); |
381 | OPENSSL_free(lst->name); | |
366448ec DSH |
382 | ltmp = lst->next; |
383 | OPENSSL_free(lst); | |
384 | lst = ltmp; | |
5824cc29 DSH |
385 | } |
386 | } | |
387 | ||
7a6c9792 DSH |
388 | static int check_unsupported() |
389 | { | |
390 | long err = ERR_peek_error(); | |
391 | if (ERR_GET_LIB(err) == ERR_LIB_EVP | |
366448ec | 392 | && ERR_GET_REASON(err) == EVP_R_UNSUPPORTED_ALGORITHM) { |
7a6c9792 DSH |
393 | ERR_clear_error(); |
394 | return 1; | |
395 | } | |
396 | return 0; | |
397 | } | |
398 | ||
307e3978 DSH |
399 | static int process_test(struct evp_test *t, char *buf, int verbose) |
400 | { | |
4c9b0a03 | 401 | char *keyword = NULL, *value = NULL; |
7a6c9792 | 402 | int rv = 0, add_key = 0; |
4c9b0a03 GK |
403 | long save_pos = 0; |
404 | struct key_list **lst = NULL, *key = NULL; | |
5824cc29 | 405 | EVP_PKEY *pk = NULL; |
4c9b0a03 | 406 | const struct evp_test_method *tmeth = NULL; |
307e3978 DSH |
407 | if (verbose) |
408 | fputs(buf, stdout); | |
409 | if (!parse_line(&keyword, &value, buf)) | |
410 | return 1; | |
86885c28 | 411 | if (strcmp(keyword, "PrivateKey") == 0) { |
5824cc29 DSH |
412 | save_pos = ftell(t->in); |
413 | pk = PEM_read_PrivateKey(t->in, NULL, 0, NULL); | |
7a6c9792 | 414 | if (pk == NULL && !check_unsupported()) { |
5824cc29 DSH |
415 | fprintf(stderr, "Error reading private key %s\n", value); |
416 | ERR_print_errors_fp(stderr); | |
417 | return 0; | |
418 | } | |
419 | lst = &t->private; | |
7a6c9792 | 420 | add_key = 1; |
5824cc29 | 421 | } |
86885c28 | 422 | if (strcmp(keyword, "PublicKey") == 0) { |
5824cc29 DSH |
423 | save_pos = ftell(t->in); |
424 | pk = PEM_read_PUBKEY(t->in, NULL, 0, NULL); | |
7a6c9792 | 425 | if (pk == NULL && !check_unsupported()) { |
5824cc29 DSH |
426 | fprintf(stderr, "Error reading public key %s\n", value); |
427 | ERR_print_errors_fp(stderr); | |
428 | return 0; | |
429 | } | |
430 | lst = &t->public; | |
7a6c9792 | 431 | add_key = 1; |
5824cc29 DSH |
432 | } |
433 | /* If we have a key add to list */ | |
7a6c9792 | 434 | if (add_key) { |
5824cc29 | 435 | char tmpbuf[80]; |
7a6c9792 | 436 | if (find_key(NULL, value, *lst)) { |
5824cc29 DSH |
437 | fprintf(stderr, "Duplicate key %s\n", value); |
438 | return 0; | |
439 | } | |
b4faea50 | 440 | key = OPENSSL_malloc(sizeof(*key)); |
5824cc29 DSH |
441 | if (!key) |
442 | return 0; | |
443 | key->name = BUF_strdup(value); | |
444 | key->key = pk; | |
445 | key->next = *lst; | |
446 | *lst = key; | |
447 | /* Rewind input, read to end and update line numbers */ | |
448 | fseek(t->in, save_pos, SEEK_SET); | |
449 | while (fgets(tmpbuf, sizeof(tmpbuf), t->in)) { | |
450 | t->line++; | |
86885c28 | 451 | if (strncmp(tmpbuf, "-----END", 8) == 0) |
5824cc29 DSH |
452 | return 1; |
453 | } | |
454 | fprintf(stderr, "Can't find key end\n"); | |
455 | return 0; | |
456 | } | |
457 | ||
307e3978 DSH |
458 | /* See if keyword corresponds to a test start */ |
459 | tmeth = evp_find_test(keyword); | |
460 | if (tmeth) { | |
461 | if (!setup_test(t, tmeth)) | |
462 | return 0; | |
463 | t->start_line = t->line; | |
7a6c9792 | 464 | t->skip = 0; |
307e3978 DSH |
465 | if (!tmeth->init(t, value)) { |
466 | fprintf(stderr, "Unknown %s: %s\n", keyword, value); | |
467 | return 0; | |
0f113f3e | 468 | } |
307e3978 | 469 | return 1; |
7a6c9792 DSH |
470 | } else if (t->skip) { |
471 | return 1; | |
86885c28 | 472 | } else if (strcmp(keyword, "Result") == 0) { |
307e3978 DSH |
473 | if (t->expected_err) { |
474 | fprintf(stderr, "Line %d: multiple result lines\n", t->line); | |
475 | return 0; | |
0f113f3e | 476 | } |
307e3978 DSH |
477 | t->expected_err = BUF_strdup(value); |
478 | if (!t->expected_err) | |
479 | return 0; | |
480 | } else { | |
481 | /* Must be test specific line: try to parse it */ | |
482 | if (t->meth) | |
483 | rv = t->meth->parse(t, keyword, value); | |
484 | ||
485 | if (rv == 0) | |
486 | fprintf(stderr, "line %d: unexpected keyword %s\n", | |
487 | t->line, keyword); | |
488 | ||
489 | if (rv < 0) | |
490 | fprintf(stderr, "line %d: error processing keyword %s\n", | |
491 | t->line, keyword); | |
492 | if (rv <= 0) | |
493 | return 0; | |
0f113f3e | 494 | } |
307e3978 DSH |
495 | return 1; |
496 | } | |
0f113f3e | 497 | |
b033e5d5 DSH |
498 | static int check_output(struct evp_test *t, const unsigned char *expected, |
499 | const unsigned char *got, size_t len) | |
500 | { | |
501 | if (!memcmp(expected, got, len)) | |
502 | return 0; | |
503 | t->out_expected = BUF_memdup(expected, len); | |
504 | t->out_got = BUF_memdup(got, len); | |
505 | t->out_len = len; | |
506 | if (t->out_expected == NULL || t->out_got == NULL) { | |
507 | fprintf(stderr, "Memory allocation error!\n"); | |
508 | exit(1); | |
509 | } | |
510 | return 1; | |
511 | } | |
512 | ||
307e3978 DSH |
513 | int main(int argc, char **argv) |
514 | { | |
515 | FILE *in = NULL; | |
516 | char buf[10240]; | |
517 | struct evp_test t; | |
0f113f3e | 518 | |
b033e5d5 DSH |
519 | if (argc != 2) { |
520 | fprintf(stderr, "usage: evp_test testfile.txt\n"); | |
521 | return 1; | |
522 | } | |
523 | ||
d5ec8efc DSH |
524 | CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); |
525 | ||
307e3978 DSH |
526 | ERR_load_crypto_strings(); |
527 | OpenSSL_add_all_algorithms(); | |
1526fea5 | 528 | |
366448ec | 529 | memset(&t, 0, sizeof(t)); |
307e3978 | 530 | t.meth = NULL; |
5824cc29 DSH |
531 | t.public = NULL; |
532 | t.private = NULL; | |
307e3978 DSH |
533 | t.err = NULL; |
534 | t.line = 0; | |
535 | t.start_line = -1; | |
536 | t.errors = 0; | |
537 | t.ntests = 0; | |
b033e5d5 DSH |
538 | t.out_expected = NULL; |
539 | t.out_got = NULL; | |
540 | t.out_len = 0; | |
307e3978 | 541 | in = fopen(argv[1], "r"); |
5824cc29 | 542 | t.in = in; |
307e3978 DSH |
543 | while (fgets(buf, sizeof(buf), in)) { |
544 | t.line++; | |
545 | if (!process_test(&t, buf, 0)) | |
546 | exit(1); | |
547 | } | |
548 | /* Run any final test we have */ | |
549 | if (!setup_test(&t, NULL)) | |
550 | exit(1); | |
7a6c9792 DSH |
551 | fprintf(stderr, "%d tests completed with %d errors, %d skipped\n", |
552 | t.ntests, t.errors, t.nskip); | |
5824cc29 DSH |
553 | free_key_list(t.public); |
554 | free_key_list(t.private); | |
307e3978 | 555 | fclose(in); |
d5ec8efc DSH |
556 | EVP_cleanup(); |
557 | CRYPTO_cleanup_all_ex_data(); | |
558 | ERR_remove_thread_state(NULL); | |
559 | ERR_free_strings(); | |
560 | CRYPTO_mem_leaks_fp(stderr); | |
6906a7c1 DSH |
561 | if (t.errors) |
562 | return 1; | |
307e3978 | 563 | return 0; |
0f113f3e MC |
564 | } |
565 | ||
307e3978 | 566 | static void test_free(void *d) |
0f113f3e | 567 | { |
b548a1f1 | 568 | OPENSSL_free(d); |
307e3978 | 569 | } |
4897dc40 | 570 | |
307e3978 | 571 | /* Message digest tests */ |
4897dc40 | 572 | |
307e3978 DSH |
573 | struct digest_data { |
574 | /* Digest this test is for */ | |
575 | const EVP_MD *digest; | |
576 | /* Input to digest */ | |
577 | unsigned char *input; | |
578 | size_t input_len; | |
618be04e DSH |
579 | /* Repeat count for input */ |
580 | size_t nrpt; | |
307e3978 DSH |
581 | /* Expected output */ |
582 | unsigned char *output; | |
583 | size_t output_len; | |
584 | }; | |
4897dc40 | 585 | |
307e3978 DSH |
586 | static int digest_test_init(struct evp_test *t, const char *alg) |
587 | { | |
588 | const EVP_MD *digest; | |
589 | struct digest_data *mdat = t->data; | |
590 | digest = EVP_get_digestbyname(alg); | |
578ce42d DSH |
591 | if (!digest) { |
592 | /* If alg has an OID assume disabled algorithm */ | |
593 | if (OBJ_sn2nid(alg) != NID_undef || OBJ_ln2nid(alg) != NID_undef) { | |
594 | t->skip = 1; | |
595 | return 1; | |
596 | } | |
307e3978 | 597 | return 0; |
578ce42d | 598 | } |
b4faea50 | 599 | mdat = OPENSSL_malloc(sizeof(*mdat)); |
307e3978 DSH |
600 | mdat->digest = digest; |
601 | mdat->input = NULL; | |
602 | mdat->output = NULL; | |
618be04e | 603 | mdat->nrpt = 1; |
307e3978 | 604 | t->data = mdat; |
4897dc40 | 605 | return 1; |
0f113f3e | 606 | } |
4897dc40 | 607 | |
307e3978 DSH |
608 | static void digest_test_cleanup(struct evp_test *t) |
609 | { | |
610 | struct digest_data *mdat = t->data; | |
611 | test_free(mdat->input); | |
612 | test_free(mdat->output); | |
613 | } | |
614 | ||
615 | static int digest_test_parse(struct evp_test *t, | |
616 | const char *keyword, const char *value) | |
617 | { | |
618 | struct digest_data *mdata = t->data; | |
86885c28 | 619 | if (strcmp(keyword, "Input") == 0) |
307e3978 | 620 | return test_bin(value, &mdata->input, &mdata->input_len); |
86885c28 | 621 | if (strcmp(keyword, "Output") == 0) |
307e3978 | 622 | return test_bin(value, &mdata->output, &mdata->output_len); |
86885c28 | 623 | if (strcmp(keyword, "Count") == 0) { |
618be04e DSH |
624 | long nrpt = atoi(value); |
625 | if (nrpt <= 0) | |
626 | return 0; | |
627 | mdata->nrpt = (size_t)nrpt; | |
628 | return 1; | |
629 | } | |
307e3978 DSH |
630 | return 0; |
631 | } | |
632 | ||
633 | static int digest_test_run(struct evp_test *t) | |
0f113f3e | 634 | { |
307e3978 | 635 | struct digest_data *mdata = t->data; |
618be04e | 636 | size_t i; |
307e3978 DSH |
637 | const char *err = "INTERNAL_ERROR"; |
638 | EVP_MD_CTX *mctx; | |
4897dc40 | 639 | unsigned char md[EVP_MAX_MD_SIZE]; |
307e3978 DSH |
640 | unsigned int md_len; |
641 | mctx = EVP_MD_CTX_create(); | |
642 | if (!mctx) | |
643 | goto err; | |
644 | err = "DIGESTINIT_ERROR"; | |
645 | if (!EVP_DigestInit_ex(mctx, mdata->digest, NULL)) | |
646 | goto err; | |
647 | err = "DIGESTUPDATE_ERROR"; | |
618be04e DSH |
648 | for (i = 0; i < mdata->nrpt; i++) { |
649 | if (!EVP_DigestUpdate(mctx, mdata->input, mdata->input_len)) | |
650 | goto err; | |
651 | } | |
307e3978 DSH |
652 | err = "DIGESTFINAL_ERROR"; |
653 | if (!EVP_DigestFinal(mctx, md, &md_len)) | |
654 | goto err; | |
655 | err = "DIGEST_LENGTH_MISMATCH"; | |
656 | if (md_len != mdata->output_len) | |
657 | goto err; | |
658 | err = "DIGEST_MISMATCH"; | |
b033e5d5 | 659 | if (check_output(t, mdata->output, md, md_len)) |
307e3978 DSH |
660 | goto err; |
661 | err = NULL; | |
662 | err: | |
663 | if (mctx) | |
664 | EVP_MD_CTX_destroy(mctx); | |
665 | t->err = err; | |
b033e5d5 | 666 | return 1; |
307e3978 | 667 | } |
4897dc40 | 668 | |
307e3978 DSH |
669 | static const struct evp_test_method digest_test_method = { |
670 | "Digest", | |
671 | digest_test_init, | |
672 | digest_test_cleanup, | |
673 | digest_test_parse, | |
674 | digest_test_run | |
675 | }; | |
676 | ||
677 | /* Cipher tests */ | |
678 | struct cipher_data { | |
679 | const EVP_CIPHER *cipher; | |
680 | int enc; | |
2207ba7b | 681 | /* EVP_CIPH_GCM_MODE, EVP_CIPH_CCM_MODE or EVP_CIPH_OCB_MODE if AEAD */ |
307e3978 DSH |
682 | int aead; |
683 | unsigned char *key; | |
684 | size_t key_len; | |
685 | unsigned char *iv; | |
686 | size_t iv_len; | |
687 | unsigned char *plaintext; | |
688 | size_t plaintext_len; | |
689 | unsigned char *ciphertext; | |
690 | size_t ciphertext_len; | |
691 | /* GCM, CCM only */ | |
692 | unsigned char *aad; | |
693 | size_t aad_len; | |
694 | unsigned char *tag; | |
695 | size_t tag_len; | |
696 | }; | |
697 | ||
698 | static int cipher_test_init(struct evp_test *t, const char *alg) | |
699 | { | |
700 | const EVP_CIPHER *cipher; | |
701 | struct cipher_data *cdat = t->data; | |
702 | cipher = EVP_get_cipherbyname(alg); | |
33a89fa6 DSH |
703 | if (!cipher) { |
704 | /* If alg has an OID assume disabled algorithm */ | |
705 | if (OBJ_sn2nid(alg) != NID_undef || OBJ_ln2nid(alg) != NID_undef) { | |
706 | t->skip = 1; | |
707 | return 1; | |
708 | } | |
0f113f3e | 709 | return 0; |
33a89fa6 | 710 | } |
b4faea50 | 711 | cdat = OPENSSL_malloc(sizeof(*cdat)); |
307e3978 DSH |
712 | cdat->cipher = cipher; |
713 | cdat->enc = -1; | |
714 | cdat->key = NULL; | |
715 | cdat->iv = NULL; | |
716 | cdat->ciphertext = NULL; | |
717 | cdat->plaintext = NULL; | |
718 | cdat->aad = NULL; | |
719 | cdat->tag = NULL; | |
720 | t->data = cdat; | |
721 | if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE | |
2207ba7b | 722 | || EVP_CIPHER_mode(cipher) == EVP_CIPH_OCB_MODE |
307e3978 DSH |
723 | || EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE) |
724 | cdat->aead = EVP_CIPHER_mode(cipher); | |
725 | else | |
726 | cdat->aead = 0; | |
4897dc40 | 727 | |
307e3978 DSH |
728 | return 1; |
729 | } | |
4897dc40 | 730 | |
307e3978 DSH |
731 | static void cipher_test_cleanup(struct evp_test *t) |
732 | { | |
733 | struct cipher_data *cdat = t->data; | |
734 | test_free(cdat->key); | |
735 | test_free(cdat->iv); | |
736 | test_free(cdat->ciphertext); | |
737 | test_free(cdat->plaintext); | |
738 | test_free(cdat->aad); | |
739 | test_free(cdat->tag); | |
740 | } | |
4897dc40 | 741 | |
307e3978 DSH |
742 | static int cipher_test_parse(struct evp_test *t, const char *keyword, |
743 | const char *value) | |
744 | { | |
745 | struct cipher_data *cdat = t->data; | |
86885c28 | 746 | if (strcmp(keyword, "Key") == 0) |
307e3978 | 747 | return test_bin(value, &cdat->key, &cdat->key_len); |
86885c28 | 748 | if (strcmp(keyword, "IV") == 0) |
307e3978 | 749 | return test_bin(value, &cdat->iv, &cdat->iv_len); |
86885c28 | 750 | if (strcmp(keyword, "Plaintext") == 0) |
307e3978 | 751 | return test_bin(value, &cdat->plaintext, &cdat->plaintext_len); |
86885c28 | 752 | if (strcmp(keyword, "Ciphertext") == 0) |
307e3978 DSH |
753 | return test_bin(value, &cdat->ciphertext, &cdat->ciphertext_len); |
754 | if (cdat->aead) { | |
86885c28 | 755 | if (strcmp(keyword, "AAD") == 0) |
307e3978 | 756 | return test_bin(value, &cdat->aad, &cdat->aad_len); |
86885c28 | 757 | if (strcmp(keyword, "Tag") == 0) |
307e3978 | 758 | return test_bin(value, &cdat->tag, &cdat->tag_len); |
0f113f3e | 759 | } |
4897dc40 | 760 | |
86885c28 RS |
761 | if (strcmp(keyword, "Operation") == 0) { |
762 | if (strcmp(value, "ENCRYPT") == 0) | |
307e3978 | 763 | cdat->enc = 1; |
86885c28 | 764 | else if (strcmp(value, "DECRYPT") == 0) |
307e3978 DSH |
765 | cdat->enc = 0; |
766 | else | |
767 | return 0; | |
768 | return 1; | |
0f113f3e | 769 | } |
307e3978 | 770 | return 0; |
0f113f3e | 771 | } |
4897dc40 | 772 | |
307e3978 | 773 | static int cipher_test_enc(struct evp_test *t, int enc) |
0f113f3e | 774 | { |
307e3978 DSH |
775 | struct cipher_data *cdat = t->data; |
776 | unsigned char *in, *out, *tmp = NULL; | |
777 | size_t in_len, out_len; | |
778 | int tmplen, tmpflen; | |
779 | EVP_CIPHER_CTX *ctx = NULL; | |
780 | const char *err; | |
781 | err = "INTERNAL_ERROR"; | |
782 | ctx = EVP_CIPHER_CTX_new(); | |
783 | if (!ctx) | |
784 | goto err; | |
785 | EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); | |
786 | if (enc) { | |
787 | in = cdat->plaintext; | |
788 | in_len = cdat->plaintext_len; | |
789 | out = cdat->ciphertext; | |
790 | out_len = cdat->ciphertext_len; | |
791 | } else { | |
792 | in = cdat->ciphertext; | |
793 | in_len = cdat->ciphertext_len; | |
794 | out = cdat->plaintext; | |
795 | out_len = cdat->plaintext_len; | |
0f113f3e | 796 | } |
307e3978 DSH |
797 | tmp = OPENSSL_malloc(in_len + 2 * EVP_MAX_BLOCK_LENGTH); |
798 | if (!tmp) | |
799 | goto err; | |
800 | err = "CIPHERINIT_ERROR"; | |
801 | if (!EVP_CipherInit_ex(ctx, cdat->cipher, NULL, NULL, NULL, enc)) | |
802 | goto err; | |
803 | err = "INVALID_IV_LENGTH"; | |
804 | if (cdat->iv) { | |
2207ba7b DSH |
805 | if (cdat->aead) { |
806 | if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, | |
307e3978 DSH |
807 | cdat->iv_len, 0)) |
808 | goto err; | |
809 | } else if (cdat->iv_len != (size_t)EVP_CIPHER_CTX_iv_length(ctx)) | |
810 | goto err; | |
0f113f3e | 811 | } |
307e3978 DSH |
812 | if (cdat->aead) { |
813 | unsigned char *tag; | |
814 | /* | |
2207ba7b DSH |
815 | * If encrypting or OCB just set tag length initially, otherwise |
816 | * set tag length and value. | |
307e3978 | 817 | */ |
2207ba7b | 818 | if (enc || cdat->aead == EVP_CIPH_OCB_MODE) { |
307e3978 DSH |
819 | err = "TAG_LENGTH_SET_ERROR"; |
820 | tag = NULL; | |
0f113f3e | 821 | } else { |
307e3978 DSH |
822 | err = "TAG_SET_ERROR"; |
823 | tag = cdat->tag; | |
0f113f3e | 824 | } |
2207ba7b DSH |
825 | if (tag || cdat->aead != EVP_CIPH_GCM_MODE) { |
826 | if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, | |
366448ec | 827 | cdat->tag_len, tag)) |
307e3978 | 828 | goto err; |
0f113f3e | 829 | } |
307e3978 | 830 | } |
0f113f3e | 831 | |
307e3978 DSH |
832 | err = "INVALID_KEY_LENGTH"; |
833 | if (!EVP_CIPHER_CTX_set_key_length(ctx, cdat->key_len)) | |
834 | goto err; | |
835 | err = "KEY_SET_ERROR"; | |
836 | if (!EVP_CipherInit_ex(ctx, NULL, NULL, cdat->key, cdat->iv, -1)) | |
837 | goto err; | |
838 | ||
2207ba7b DSH |
839 | if (!enc && cdat->aead == EVP_CIPH_OCB_MODE) { |
840 | if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, | |
841 | cdat->tag_len, cdat->tag)) { | |
366448ec DSH |
842 | err = "TAG_SET_ERROR"; |
843 | goto err; | |
2207ba7b DSH |
844 | } |
845 | } | |
846 | ||
307e3978 DSH |
847 | if (cdat->aead == EVP_CIPH_CCM_MODE) { |
848 | if (!EVP_CipherUpdate(ctx, NULL, &tmplen, NULL, out_len)) { | |
849 | err = "CCM_PLAINTEXT_LENGTH_SET_ERROR"; | |
850 | goto err; | |
0f113f3e MC |
851 | } |
852 | } | |
307e3978 DSH |
853 | if (cdat->aad) { |
854 | if (!EVP_CipherUpdate(ctx, NULL, &tmplen, cdat->aad, cdat->aad_len)) { | |
855 | err = "AAD_SET_ERROR"; | |
856 | goto err; | |
857 | } | |
858 | } | |
859 | EVP_CIPHER_CTX_set_padding(ctx, 0); | |
860 | err = "CIPHERUPDATE_ERROR"; | |
861 | if (!EVP_CipherUpdate(ctx, tmp, &tmplen, in, in_len)) | |
862 | goto err; | |
863 | if (cdat->aead == EVP_CIPH_CCM_MODE) | |
864 | tmpflen = 0; | |
865 | else { | |
866 | err = "CIPHERFINAL_ERROR"; | |
867 | if (!EVP_CipherFinal_ex(ctx, tmp + tmplen, &tmpflen)) | |
868 | goto err; | |
869 | } | |
870 | err = "LENGTH_MISMATCH"; | |
871 | if (out_len != (size_t)(tmplen + tmpflen)) | |
872 | goto err; | |
873 | err = "VALUE_MISMATCH"; | |
b033e5d5 | 874 | if (check_output(t, out, tmp, out_len)) |
307e3978 DSH |
875 | goto err; |
876 | if (enc && cdat->aead) { | |
877 | unsigned char rtag[16]; | |
878 | if (cdat->tag_len > sizeof(rtag)) { | |
879 | err = "TAG_LENGTH_INTERNAL_ERROR"; | |
880 | goto err; | |
881 | } | |
2207ba7b | 882 | if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, |
307e3978 DSH |
883 | cdat->tag_len, rtag)) { |
884 | err = "TAG_RETRIEVE_ERROR"; | |
885 | goto err; | |
886 | } | |
b033e5d5 | 887 | if (check_output(t, cdat->tag, rtag, cdat->tag_len)) { |
307e3978 DSH |
888 | err = "TAG_VALUE_MISMATCH"; |
889 | goto err; | |
890 | } | |
891 | } | |
892 | err = NULL; | |
893 | err: | |
b548a1f1 | 894 | OPENSSL_free(tmp); |
307e3978 DSH |
895 | EVP_CIPHER_CTX_free(ctx); |
896 | t->err = err; | |
897 | return err ? 0 : 1; | |
898 | } | |
0e360199 | 899 | |
307e3978 DSH |
900 | static int cipher_test_run(struct evp_test *t) |
901 | { | |
902 | struct cipher_data *cdat = t->data; | |
903 | int rv; | |
904 | if (!cdat->key) { | |
905 | t->err = "NO_KEY"; | |
906 | return 0; | |
907 | } | |
908 | if (!cdat->iv && EVP_CIPHER_iv_length(cdat->cipher)) { | |
909 | /* IV is optional and usually omitted in wrap mode */ | |
910 | if (EVP_CIPHER_mode(cdat->cipher) != EVP_CIPH_WRAP_MODE) { | |
911 | t->err = "NO_IV"; | |
912 | return 0; | |
913 | } | |
914 | } | |
915 | if (cdat->aead && !cdat->tag) { | |
916 | t->err = "NO_TAG"; | |
917 | return 0; | |
918 | } | |
919 | if (cdat->enc) { | |
920 | rv = cipher_test_enc(t, 1); | |
921 | /* Not fatal errors: return */ | |
922 | if (rv != 1) { | |
923 | if (rv < 0) | |
924 | return 0; | |
925 | return 1; | |
926 | } | |
927 | } | |
928 | if (cdat->enc != 1) { | |
929 | rv = cipher_test_enc(t, 0); | |
930 | /* Not fatal errors: return */ | |
931 | if (rv != 1) { | |
932 | if (rv < 0) | |
933 | return 0; | |
934 | return 1; | |
935 | } | |
936 | } | |
937 | return 1; | |
0f113f3e | 938 | } |
307e3978 DSH |
939 | |
940 | static const struct evp_test_method cipher_test_method = { | |
941 | "Cipher", | |
942 | cipher_test_init, | |
943 | cipher_test_cleanup, | |
944 | cipher_test_parse, | |
945 | cipher_test_run | |
946 | }; | |
83251f39 DSH |
947 | |
948 | struct mac_data { | |
949 | /* MAC type */ | |
950 | int type; | |
951 | /* Algorithm string for this MAC */ | |
952 | char *alg; | |
953 | /* MAC key */ | |
954 | unsigned char *key; | |
955 | size_t key_len; | |
956 | /* Input to MAC */ | |
957 | unsigned char *input; | |
958 | size_t input_len; | |
959 | /* Expected output */ | |
960 | unsigned char *output; | |
961 | size_t output_len; | |
962 | }; | |
963 | ||
964 | static int mac_test_init(struct evp_test *t, const char *alg) | |
965 | { | |
966 | int type; | |
967 | struct mac_data *mdat; | |
86885c28 | 968 | if (strcmp(alg, "HMAC") == 0) |
83251f39 | 969 | type = EVP_PKEY_HMAC; |
86885c28 | 970 | else if (strcmp(alg, "CMAC") == 0) |
83251f39 DSH |
971 | type = EVP_PKEY_CMAC; |
972 | else | |
973 | return 0; | |
974 | ||
b4faea50 | 975 | mdat = OPENSSL_malloc(sizeof(*mdat)); |
83251f39 DSH |
976 | mdat->type = type; |
977 | mdat->alg = NULL; | |
978 | mdat->key = NULL; | |
979 | mdat->input = NULL; | |
980 | mdat->output = NULL; | |
981 | t->data = mdat; | |
982 | return 1; | |
983 | } | |
984 | ||
985 | static void mac_test_cleanup(struct evp_test *t) | |
986 | { | |
987 | struct mac_data *mdat = t->data; | |
988 | test_free(mdat->alg); | |
989 | test_free(mdat->key); | |
990 | test_free(mdat->input); | |
991 | test_free(mdat->output); | |
992 | } | |
993 | ||
994 | static int mac_test_parse(struct evp_test *t, | |
995 | const char *keyword, const char *value) | |
996 | { | |
997 | struct mac_data *mdata = t->data; | |
86885c28 | 998 | if (strcmp(keyword, "Key") == 0) |
83251f39 | 999 | return test_bin(value, &mdata->key, &mdata->key_len); |
86885c28 | 1000 | if (strcmp(keyword, "Algorithm") == 0) { |
83251f39 DSH |
1001 | mdata->alg = BUF_strdup(value); |
1002 | if (!mdata->alg) | |
1003 | return 0; | |
1004 | return 1; | |
1005 | } | |
86885c28 | 1006 | if (strcmp(keyword, "Input") == 0) |
83251f39 | 1007 | return test_bin(value, &mdata->input, &mdata->input_len); |
86885c28 | 1008 | if (strcmp(keyword, "Output") == 0) |
83251f39 DSH |
1009 | return test_bin(value, &mdata->output, &mdata->output_len); |
1010 | return 0; | |
1011 | } | |
1012 | ||
1013 | static int mac_test_run(struct evp_test *t) | |
1014 | { | |
1015 | struct mac_data *mdata = t->data; | |
1016 | const char *err = "INTERNAL_ERROR"; | |
1017 | EVP_MD_CTX *mctx = NULL; | |
1018 | EVP_PKEY_CTX *pctx = NULL, *genctx = NULL; | |
1019 | EVP_PKEY *key = NULL; | |
1020 | const EVP_MD *md = NULL; | |
1021 | unsigned char *mac = NULL; | |
1022 | size_t mac_len; | |
1023 | ||
1024 | err = "MAC_PKEY_CTX_ERROR"; | |
1025 | genctx = EVP_PKEY_CTX_new_id(mdata->type, NULL); | |
1026 | if (!genctx) | |
1027 | goto err; | |
1028 | ||
1029 | err = "MAC_KEYGEN_INIT_ERROR"; | |
1030 | if (EVP_PKEY_keygen_init(genctx) <= 0) | |
1031 | goto err; | |
1032 | if (mdata->type == EVP_PKEY_CMAC) { | |
1033 | err = "MAC_ALGORITHM_SET_ERROR"; | |
1034 | if (EVP_PKEY_CTX_ctrl_str(genctx, "cipher", mdata->alg) <= 0) | |
1035 | goto err; | |
1036 | } | |
1037 | ||
1038 | err = "MAC_KEY_SET_ERROR"; | |
1039 | if (EVP_PKEY_CTX_set_mac_key(genctx, mdata->key, mdata->key_len) <= 0) | |
1040 | goto err; | |
1041 | ||
1042 | err = "MAC_KEY_GENERATE_ERROR"; | |
1043 | if (EVP_PKEY_keygen(genctx, &key) <= 0) | |
1044 | goto err; | |
1045 | if (mdata->type == EVP_PKEY_HMAC) { | |
1046 | err = "MAC_ALGORITHM_SET_ERROR"; | |
1047 | md = EVP_get_digestbyname(mdata->alg); | |
1048 | if (!md) | |
1049 | goto err; | |
1050 | } | |
1051 | mctx = EVP_MD_CTX_create(); | |
1052 | if (!mctx) | |
1053 | goto err; | |
1054 | err = "DIGESTSIGNINIT_ERROR"; | |
1055 | if (!EVP_DigestSignInit(mctx, &pctx, md, NULL, key)) | |
1056 | goto err; | |
1057 | ||
1058 | err = "DIGESTSIGNUPDATE_ERROR"; | |
1059 | if (!EVP_DigestSignUpdate(mctx, mdata->input, mdata->input_len)) | |
1060 | goto err; | |
1061 | err = "DIGESTSIGNFINAL_LENGTH_ERROR"; | |
1062 | if (!EVP_DigestSignFinal(mctx, NULL, &mac_len)) | |
1063 | goto err; | |
1064 | mac = OPENSSL_malloc(mac_len); | |
1065 | if (!mac) { | |
1066 | fprintf(stderr, "Error allocating mac buffer!\n"); | |
1067 | exit(1); | |
1068 | } | |
1069 | if (!EVP_DigestSignFinal(mctx, mac, &mac_len)) | |
1070 | goto err; | |
1071 | err = "MAC_LENGTH_MISMATCH"; | |
1072 | if (mac_len != mdata->output_len) | |
1073 | goto err; | |
1074 | err = "MAC_MISMATCH"; | |
1075 | if (check_output(t, mdata->output, mac, mac_len)) | |
1076 | goto err; | |
1077 | err = NULL; | |
1078 | err: | |
1079 | if (mctx) | |
1080 | EVP_MD_CTX_destroy(mctx); | |
b548a1f1 | 1081 | OPENSSL_free(mac); |
c5ba2d99 RS |
1082 | EVP_PKEY_CTX_free(genctx); |
1083 | EVP_PKEY_free(key); | |
83251f39 DSH |
1084 | t->err = err; |
1085 | return 1; | |
1086 | } | |
1087 | ||
1088 | static const struct evp_test_method mac_test_method = { | |
1089 | "MAC", | |
1090 | mac_test_init, | |
1091 | mac_test_cleanup, | |
1092 | mac_test_parse, | |
1093 | mac_test_run | |
1094 | }; | |
5824cc29 DSH |
1095 | |
1096 | /* | |
1097 | * Public key operations. These are all very similar and can share | |
1098 | * a lot of common code. | |
1099 | */ | |
1100 | ||
1101 | struct pkey_data { | |
1102 | /* Context for this operation */ | |
1103 | EVP_PKEY_CTX *ctx; | |
1104 | /* Key operation to perform */ | |
1105 | int (*keyop) (EVP_PKEY_CTX *ctx, | |
1106 | unsigned char *sig, size_t *siglen, | |
1107 | const unsigned char *tbs, size_t tbslen); | |
1108 | /* Input to MAC */ | |
1109 | unsigned char *input; | |
1110 | size_t input_len; | |
1111 | /* Expected output */ | |
1112 | unsigned char *output; | |
1113 | size_t output_len; | |
1114 | }; | |
1115 | ||
1116 | /* | |
1117 | * Perform public key operation setup: lookup key, allocated ctx and call | |
1118 | * the appropriate initialisation function | |
1119 | */ | |
1120 | static int pkey_test_init(struct evp_test *t, const char *name, | |
1121 | int use_public, | |
1122 | int (*keyopinit) (EVP_PKEY_CTX *ctx), | |
1123 | int (*keyop) (EVP_PKEY_CTX *ctx, | |
1124 | unsigned char *sig, size_t *siglen, | |
1125 | const unsigned char *tbs, | |
1126 | size_t tbslen) | |
1127 | ) | |
1128 | { | |
1129 | struct pkey_data *kdata; | |
1130 | EVP_PKEY *pkey = NULL; | |
7a6c9792 DSH |
1131 | int rv = 0; |
1132 | if (use_public) | |
1133 | rv = find_key(&pkey, name, t->public); | |
1134 | if (!rv) | |
1135 | rv = find_key(&pkey, name, t->private); | |
1136 | if (!rv) | |
1137 | return 0; | |
1138 | if (!pkey) { | |
1139 | t->skip = 1; | |
1140 | return 1; | |
1141 | } | |
1142 | ||
b4faea50 | 1143 | kdata = OPENSSL_malloc(sizeof(*kdata)); |
7a6c9792 DSH |
1144 | if (!kdata) { |
1145 | EVP_PKEY_free(pkey); | |
5824cc29 | 1146 | return 0; |
7a6c9792 | 1147 | } |
5824cc29 DSH |
1148 | kdata->ctx = NULL; |
1149 | kdata->input = NULL; | |
1150 | kdata->output = NULL; | |
1151 | kdata->keyop = keyop; | |
1152 | t->data = kdata; | |
5824cc29 DSH |
1153 | kdata->ctx = EVP_PKEY_CTX_new(pkey, NULL); |
1154 | if (!kdata->ctx) | |
1155 | return 0; | |
1156 | if (keyopinit(kdata->ctx) <= 0) | |
1157 | return 0; | |
1158 | return 1; | |
1159 | } | |
1160 | ||
1161 | static void pkey_test_cleanup(struct evp_test *t) | |
1162 | { | |
1163 | struct pkey_data *kdata = t->data; | |
b548a1f1 RS |
1164 | |
1165 | OPENSSL_free(kdata->input); | |
1166 | OPENSSL_free(kdata->output); | |
c5ba2d99 | 1167 | EVP_PKEY_CTX_free(kdata->ctx); |
5824cc29 DSH |
1168 | } |
1169 | ||
1170 | static int pkey_test_parse(struct evp_test *t, | |
1171 | const char *keyword, const char *value) | |
1172 | { | |
1173 | struct pkey_data *kdata = t->data; | |
86885c28 | 1174 | if (strcmp(keyword, "Input") == 0) |
5824cc29 | 1175 | return test_bin(value, &kdata->input, &kdata->input_len); |
86885c28 | 1176 | if (strcmp(keyword, "Output") == 0) |
5824cc29 | 1177 | return test_bin(value, &kdata->output, &kdata->output_len); |
86885c28 | 1178 | if (strcmp(keyword, "Ctrl") == 0) { |
5824cc29 DSH |
1179 | char *p = strchr(value, ':'); |
1180 | if (p) | |
1181 | *p++ = 0; | |
1182 | if (EVP_PKEY_CTX_ctrl_str(kdata->ctx, value, p) <= 0) | |
1183 | return 0; | |
1184 | return 1; | |
1185 | } | |
1186 | return 0; | |
1187 | } | |
1188 | ||
1189 | static int pkey_test_run(struct evp_test *t) | |
1190 | { | |
1191 | struct pkey_data *kdata = t->data; | |
1192 | unsigned char *out = NULL; | |
1193 | size_t out_len; | |
1194 | const char *err = "KEYOP_LENGTH_ERROR"; | |
1195 | if (kdata->keyop(kdata->ctx, NULL, &out_len, kdata->input, | |
1196 | kdata->input_len) <= 0) | |
1197 | goto err; | |
1198 | out = OPENSSL_malloc(out_len); | |
1199 | if (!out) { | |
1200 | fprintf(stderr, "Error allocating output buffer!\n"); | |
1201 | exit(1); | |
1202 | } | |
1203 | err = "KEYOP_ERROR"; | |
1204 | if (kdata->keyop | |
1205 | (kdata->ctx, out, &out_len, kdata->input, kdata->input_len) <= 0) | |
1206 | goto err; | |
1207 | err = "KEYOP_LENGTH_MISMATCH"; | |
1208 | if (out_len != kdata->output_len) | |
1209 | goto err; | |
1210 | err = "KEYOP_MISMATCH"; | |
1211 | if (check_output(t, kdata->output, out, out_len)) | |
1212 | goto err; | |
1213 | err = NULL; | |
1214 | err: | |
b548a1f1 | 1215 | OPENSSL_free(out); |
5824cc29 DSH |
1216 | t->err = err; |
1217 | return 1; | |
1218 | } | |
1219 | ||
1220 | static int sign_test_init(struct evp_test *t, const char *name) | |
1221 | { | |
1222 | return pkey_test_init(t, name, 0, EVP_PKEY_sign_init, EVP_PKEY_sign); | |
1223 | } | |
1224 | ||
1225 | static const struct evp_test_method psign_test_method = { | |
1226 | "Sign", | |
1227 | sign_test_init, | |
1228 | pkey_test_cleanup, | |
1229 | pkey_test_parse, | |
1230 | pkey_test_run | |
1231 | }; | |
1232 | ||
1233 | static int verify_recover_test_init(struct evp_test *t, const char *name) | |
1234 | { | |
1235 | return pkey_test_init(t, name, 1, EVP_PKEY_verify_recover_init, | |
1236 | EVP_PKEY_verify_recover); | |
1237 | } | |
1238 | ||
1239 | static const struct evp_test_method pverify_recover_test_method = { | |
1240 | "VerifyRecover", | |
1241 | verify_recover_test_init, | |
1242 | pkey_test_cleanup, | |
1243 | pkey_test_parse, | |
1244 | pkey_test_run | |
1245 | }; | |
1246 | ||
1247 | static int decrypt_test_init(struct evp_test *t, const char *name) | |
1248 | { | |
1249 | return pkey_test_init(t, name, 0, EVP_PKEY_decrypt_init, | |
1250 | EVP_PKEY_decrypt); | |
1251 | } | |
1252 | ||
1253 | static const struct evp_test_method pdecrypt_test_method = { | |
1254 | "Decrypt", | |
1255 | decrypt_test_init, | |
1256 | pkey_test_cleanup, | |
1257 | pkey_test_parse, | |
1258 | pkey_test_run | |
1259 | }; | |
1260 | ||
1261 | static int verify_test_init(struct evp_test *t, const char *name) | |
1262 | { | |
1263 | return pkey_test_init(t, name, 1, EVP_PKEY_verify_init, 0); | |
1264 | } | |
1265 | ||
1266 | static int verify_test_run(struct evp_test *t) | |
1267 | { | |
1268 | struct pkey_data *kdata = t->data; | |
1269 | if (EVP_PKEY_verify(kdata->ctx, kdata->output, kdata->output_len, | |
1270 | kdata->input, kdata->input_len) <= 0) | |
1271 | t->err = "VERIFY_ERROR"; | |
1272 | return 1; | |
1273 | } | |
1274 | ||
1275 | static const struct evp_test_method pverify_test_method = { | |
1276 | "Verify", | |
1277 | verify_test_init, | |
1278 | pkey_test_cleanup, | |
1279 | pkey_test_parse, | |
1280 | verify_test_run | |
1281 | }; | |
3b53e18a DSH |
1282 | |
1283 | /* PBE tests */ | |
1284 | ||
1285 | #define PBE_TYPE_SCRYPT 1 | |
1286 | ||
1287 | struct pbe_data { | |
1288 | ||
1289 | int pbe_type; | |
1290 | ||
1291 | /* scrypt parameters */ | |
1292 | uint64_t N, r, p, maxmem; | |
1293 | ||
1294 | /* password */ | |
1295 | unsigned char *pass; | |
1296 | size_t pass_len; | |
1297 | ||
1298 | /* salt */ | |
1299 | unsigned char *salt; | |
1300 | size_t salt_len; | |
1301 | ||
1302 | /* Expected output */ | |
1303 | unsigned char *key; | |
1304 | size_t key_len; | |
1305 | }; | |
1306 | ||
1307 | static int scrypt_test_parse(struct evp_test *t, | |
1308 | const char *keyword, const char *value) | |
1309 | { | |
1310 | struct pbe_data *pdata = t->data; | |
1311 | if (strcmp(keyword, "N") == 0) | |
1312 | return test_uint64(value, &pdata->N); | |
1313 | if (strcmp(keyword, "p") == 0) | |
1314 | return test_uint64(value, &pdata->p); | |
1315 | if (strcmp(keyword, "r") == 0) | |
1316 | return test_uint64(value, &pdata->r); | |
1317 | if (strcmp(keyword, "maxmem") == 0) | |
1318 | return test_uint64(value, &pdata->maxmem); | |
1319 | return 0; | |
1320 | } | |
1321 | ||
1322 | static int scrypt_test_run(struct evp_test *t) | |
1323 | { | |
1324 | struct pbe_data *pdata = t->data; | |
1325 | const char *err = "INTERNAL_ERROR"; | |
1326 | unsigned char *key; | |
1327 | key = OPENSSL_malloc(pdata->key_len); | |
1328 | if (!key) | |
1329 | goto err; | |
1330 | err = "SCRYPT_ERROR"; | |
1331 | if (EVP_PBE_scrypt((const char *)pdata->pass, pdata->pass_len, | |
1332 | pdata->salt, pdata->salt_len, | |
1333 | pdata->N, pdata->r, pdata->p, pdata->maxmem, | |
1334 | key, pdata->key_len) == 0) | |
1335 | goto err; | |
1336 | err = "KEY_MISMATCH"; | |
1337 | if (check_output(t, pdata->key, key, pdata->key_len)) | |
1338 | goto err; | |
1339 | err = NULL; | |
1340 | err: | |
1341 | OPENSSL_free(key); | |
1342 | t->err = err; | |
1343 | return 1; | |
1344 | } | |
1345 | ||
1346 | static int pbe_test_init(struct evp_test *t, const char *alg) | |
1347 | { | |
1348 | struct pbe_data *pdat; | |
1349 | int pbe_type = 0; | |
1350 | if (strcmp(alg, "scrypt") == 0) | |
1351 | pbe_type = PBE_TYPE_SCRYPT; | |
1352 | else | |
1353 | fprintf(stderr, "Unknown pbe algorithm %s\n", alg); | |
1354 | pdat = OPENSSL_malloc(sizeof(*pdat)); | |
1355 | pdat->pbe_type = pbe_type; | |
1356 | pdat->pass = NULL; | |
1357 | pdat->salt = NULL; | |
1358 | pdat->N = 0; | |
1359 | pdat->r = 0; | |
1360 | pdat->p = 0; | |
1361 | pdat->maxmem = 0; | |
1362 | t->data = pdat; | |
1363 | return 1; | |
1364 | } | |
1365 | ||
1366 | static void pbe_test_cleanup(struct evp_test *t) | |
1367 | { | |
1368 | struct pbe_data *pdat = t->data; | |
1369 | test_free(pdat->pass); | |
1370 | test_free(pdat->salt); | |
1371 | test_free(pdat->key); | |
1372 | } | |
1373 | ||
1374 | static int pbe_test_parse(struct evp_test *t, | |
1375 | const char *keyword, const char *value) | |
1376 | { | |
1377 | struct pbe_data *pdata = t->data; | |
1378 | if (strcmp(keyword, "Password") == 0) | |
1379 | return test_bin(value, &pdata->pass, &pdata->pass_len); | |
1380 | if (strcmp(keyword, "Salt") == 0) | |
1381 | return test_bin(value, &pdata->salt, &pdata->salt_len); | |
1382 | if (strcmp(keyword, "Key") == 0) | |
1383 | return test_bin(value, &pdata->key, &pdata->key_len); | |
1384 | if (pdata->pbe_type == PBE_TYPE_SCRYPT) | |
1385 | return scrypt_test_parse(t, keyword, value); | |
1386 | return 0; | |
1387 | } | |
1388 | ||
1389 | static int pbe_test_run(struct evp_test *t) | |
1390 | { | |
1391 | struct pbe_data *pdata = t->data; | |
1392 | if (pdata->pbe_type == PBE_TYPE_SCRYPT) | |
1393 | return scrypt_test_run(t); | |
1394 | return 0; | |
1395 | } | |
1396 | ||
1397 | static const struct evp_test_method pbe_test_method = { | |
1398 | "PBE", | |
1399 | pbe_test_init, | |
1400 | pbe_test_cleanup, | |
1401 | pbe_test_parse, | |
1402 | pbe_test_run | |
1403 | }; |