1 /* $OpenBSD: evp_ecx_test.c,v 1.5 2023/03/02 20:04:42 tb Exp $ */
2 /*
3 * Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <err.h>
19 #include <string.h>
20
21 #include <openssl/err.h>
22 #include <openssl/evp.h>
23 #include <openssl/pem.h>
24
25 #include "curve25519_internal.h"
26
27 static const uint8_t ed25519_priv_key_1[] =
28 "-----BEGIN PRIVATE KEY-----\n"
29 "MC4CAQAwBQYDK2VwBCIEIIkDg89yB70IpUXsAZieCcCDE2ig9nin9JJWpDQoCup8\n"
30 "-----END PRIVATE KEY-----\n";
31
32 const uint8_t ed25519_raw_priv_key_1[] = {
33 0x89, 0x03, 0x83, 0xcf, 0x72, 0x07, 0xbd, 0x08,
34 0xa5, 0x45, 0xec, 0x01, 0x98, 0x9e, 0x09, 0xc0,
35 0x83, 0x13, 0x68, 0xa0, 0xf6, 0x78, 0xa7, 0xf4,
36 0x92, 0x56, 0xa4, 0x34, 0x28, 0x0a, 0xea, 0x7c,
37 };
38
39 static const uint8_t ed25519_pub_key_1[] =
40 "-----BEGIN PUBLIC KEY-----\n"
41 "MCowBQYDK2VwAyEA1vxPpbnoC7G8vFmRjYVXUU2aln3hUZEgfW1atlTHF/o=\n"
42 "-----END PUBLIC KEY-----\n";
43
44 const uint8_t ed25519_raw_pub_key_1[] = {
45 0xd6, 0xfc, 0x4f, 0xa5, 0xb9, 0xe8, 0x0b, 0xb1,
46 0xbc, 0xbc, 0x59, 0x91, 0x8d, 0x85, 0x57, 0x51,
47 0x4d, 0x9a, 0x96, 0x7d, 0xe1, 0x51, 0x91, 0x20,
48 0x7d, 0x6d, 0x5a, 0xb6, 0x54, 0xc7, 0x17, 0xfa,
49 };
50
51 static const uint8_t message_1[] = {
52 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
53 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
54 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
55 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
56 };
57
58 static const uint8_t signature_1[] = {
59 0x1c, 0xba, 0x71, 0x5a, 0xbc, 0x7f, 0x3b, 0x6b,
60 0xc1, 0x61, 0x04, 0x02, 0xb6, 0x37, 0x9e, 0xe1,
61 0xa6, 0x7c, 0xfe, 0xcd, 0xdd, 0x68, 0x59, 0xb5,
62 0xc8, 0x09, 0xa5, 0x36, 0x66, 0xfb, 0xad, 0xc5,
63 0x68, 0x31, 0xd1, 0x7a, 0x48, 0x44, 0xaa, 0xa9,
64 0x9c, 0xf1, 0x1a, 0xbb, 0xd5, 0x49, 0xd5, 0xe8,
65 0x63, 0xe2, 0x94, 0x77, 0x16, 0x1a, 0x52, 0xfa,
66 0x33, 0x6b, 0xf3, 0x57, 0x93, 0xd4, 0xc1, 0x07,
67 };
68
69 static const uint8_t x25519_priv_key_1[] =
70 "-----BEGIN PRIVATE KEY-----\n"
71 "MC4CAQAwBQYDK2VuBCIEICi6rzFFJb02mi6sopELeshEi2vr68ul4bzEHPOz+K1o\n"
72 "-----END PRIVATE KEY-----\n";
73
74 const uint8_t x25519_raw_priv_key_1[] = {
75 0x28, 0xba, 0xaf, 0x31, 0x45, 0x25, 0xbd, 0x36,
76 0x9a, 0x2e, 0xac, 0xa2, 0x91, 0x0b, 0x7a, 0xc8,
77 0x44, 0x8b, 0x6b, 0xeb, 0xeb, 0xcb, 0xa5, 0xe1,
78 0xbc, 0xc4, 0x1c, 0xf3, 0xb3, 0xf8, 0xad, 0x68,
79 };
80
81 static const uint8_t x25519_pub_key_1[] =
82 "-----BEGIN PUBLIC KEY-----\n"
83 "MCowBQYDK2VuAyEAu4WHXnAQL2YfonJhuoEO9PM2WwXjveApPmCXSiDnf1M=\n"
84 "-----END PUBLIC KEY-----\n";
85
86 static const uint8_t x25519_raw_pub_key_1[] = {
87 0xbb, 0x85, 0x87, 0x5e, 0x70, 0x10, 0x2f, 0x66,
88 0x1f, 0xa2, 0x72, 0x61, 0xba, 0x81, 0x0e, 0xf4,
89 0xf3, 0x36, 0x5b, 0x05, 0xe3, 0xbd, 0xe0, 0x29,
90 0x3e, 0x60, 0x97, 0x4a, 0x20, 0xe7, 0x7f, 0x53,
91 };
92
93 static const uint8_t x25519_priv_key_2[] =
94 "-----BEGIN PRIVATE KEY-----\n"
95 "MC4CAQAwBQYDK2VuBCIEIAg9Jbp/Ma0TO4r179WGGiv+VnGxGNRh4VNrHUij7Ql/\n"
96 "-----END PRIVATE KEY-----\n";
97
98 static const uint8_t x25519_raw_priv_key_2[] = {
99 0x08, 0x3d, 0x25, 0xba, 0x7f, 0x31, 0xad, 0x13,
100 0x3b, 0x8a, 0xf5, 0xef, 0xd5, 0x86, 0x1a, 0x2b,
101 0xfe, 0x56, 0x71, 0xb1, 0x18, 0xd4, 0x61, 0xe1,
102 0x53, 0x6b, 0x1d, 0x48, 0xa3, 0xed, 0x09, 0x7f,
103 };
104
105 static const uint8_t x25519_pub_key_2[] =
106 "-----BEGIN PUBLIC KEY-----\n"
107 "MCowBQYDK2VuAyEABvksGQRgsUXEK5CaniVZ59pPvDoABgBSdAM+EF0Q9Cw=\n"
108 "-----END PUBLIC KEY-----\n";
109
110 static const uint8_t x25519_raw_pub_key_2[] = {
111 0x06, 0xf9, 0x2c, 0x19, 0x04, 0x60, 0xb1, 0x45,
112 0xc4, 0x2b, 0x90, 0x9a, 0x9e, 0x25, 0x59, 0xe7,
113 0xda, 0x4f, 0xbc, 0x3a, 0x00, 0x06, 0x00, 0x52,
114 0x74, 0x03, 0x3e, 0x10, 0x5d, 0x10, 0xf4, 0x2c,
115 };
116
117 static const uint8_t shared_key_1[] = {
118 0xa2, 0x61, 0xf5, 0x91, 0x2e, 0x82, 0xbc, 0x98,
119 0x6c, 0x85, 0xb6, 0x51, 0x1f, 0x69, 0xdb, 0xfa,
120 0x88, 0x6c, 0x4b, 0x9e, 0x3b, 0xb0, 0x71, 0xd1,
121 0xf3, 0xea, 0x2a, 0xd0, 0xef, 0xf6, 0xa5, 0x5a,
122 };
123
124 static void
hexdump(const unsigned char * buf,size_t len)125 hexdump(const unsigned char *buf, size_t len)
126 {
127 size_t i;
128
129 for (i = 1; i <= len; i++)
130 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
131
132 fprintf(stderr, "\n");
133 }
134
135 static int
ecx_ed25519_keygen_test(void)136 ecx_ed25519_keygen_test(void)
137 {
138 EVP_PKEY_CTX *pkey_ctx = NULL;
139 EVP_PKEY *pkey = NULL;
140 BIO *bio = NULL;
141 int failed = 1;
142
143 if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL)) == NULL) {
144 fprintf(stderr, "FAIL: failed to create ED25519 context\n");
145 goto failure;
146 }
147
148 if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) {
149 fprintf(stderr, "FAIL: failed to init keygen for ED25519\n");
150 goto failure;
151 }
152 if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) {
153 fprintf(stderr, "FAIL: failed to generate ED25519 key\n");
154 goto failure;
155 }
156
157 if ((bio = BIO_new(BIO_s_mem())) == NULL)
158 goto failure;
159 if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
160 fprintf(stderr, "FAIL: failed to write ED25519 to PEM\n");
161 goto failure;
162 }
163
164 failed = 0;
165
166 failure:
167 BIO_free(bio);
168 EVP_PKEY_CTX_free(pkey_ctx);
169 EVP_PKEY_free(pkey);
170
171 return failed;
172 }
173
174 static int
ecx_ed25519_raw_key_test(void)175 ecx_ed25519_raw_key_test(void)
176 {
177 EVP_PKEY *pkey = NULL;
178 uint8_t *priv_key = NULL;
179 size_t priv_key_len = 0;
180 uint8_t *pub_key = NULL;
181 size_t pub_key_len = 0;
182 const uint8_t *pp;
183 BIO *bio = NULL;
184 int failed = 1;
185
186 /*
187 * Decode private key from PEM and check raw private and raw public.
188 */
189
190 if ((bio = BIO_new_mem_buf(ed25519_priv_key_1, -1)) == NULL)
191 errx(1, "failed to create BIO for key");
192 if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) {
193 fprintf(stderr, "FAIL: failed to read private key\n");
194 ERR_print_errors_fp(stderr);
195 goto failure;
196 }
197
198 if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) {
199 fprintf(stderr, "FAIL: failed to get raw private key len\n");
200 goto failure;
201 }
202 if (priv_key_len != sizeof(ed25519_raw_priv_key_1)) {
203 fprintf(stderr, "FAIL: raw private key length differs "
204 "(%zu != %zu)\n", priv_key_len,
205 sizeof(ed25519_raw_priv_key_1));
206 goto failure;
207 }
208 if ((priv_key = malloc(priv_key_len)) == NULL)
209 errx(1, "failed to malloc priv key");
210 if (!EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) {
211 fprintf(stderr, "FAIL: failed to get raw private key len\n");
212 goto failure;
213 }
214 if (memcmp(priv_key, ed25519_raw_priv_key_1, priv_key_len) != 0) {
215 fprintf(stderr, "FAIL: get raw private key failed\n");
216 fprintf(stderr, "Got:\n");
217 hexdump(priv_key, priv_key_len);
218 fprintf(stderr, "Want:\n");
219 hexdump(ed25519_raw_priv_key_1, sizeof(ed25519_raw_priv_key_1));
220 goto failure;
221 }
222
223 if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) {
224 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
225 goto failure;
226 }
227 if (pub_key_len != sizeof(ed25519_raw_pub_key_1)) {
228 fprintf(stderr, "FAIL: raw public key length differs "
229 "(%zu != %zu)\n", pub_key_len,
230 sizeof(ed25519_raw_pub_key_1));
231 goto failure;
232 }
233 if ((pub_key = malloc(pub_key_len)) == NULL)
234 errx(1, "failed to malloc private key");
235 if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) {
236 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
237 goto failure;
238 }
239 if (memcmp(pub_key, ed25519_raw_pub_key_1, pub_key_len) != 0) {
240 fprintf(stderr, "FAIL: get raw public key failed\n");
241 fprintf(stderr, "Got:\n");
242 hexdump(pub_key, pub_key_len);
243 fprintf(stderr, "Want:\n");
244 hexdump(ed25519_raw_pub_key_1, sizeof(ed25519_raw_pub_key_1));
245 goto failure;
246 }
247
248 BIO_free(bio);
249 bio = NULL;
250
251 EVP_PKEY_free(pkey);
252 pkey = NULL;
253
254 freezero(priv_key, priv_key_len);
255 priv_key = NULL;
256 priv_key_len = 0;
257
258 freezero(pub_key, pub_key_len);
259 pub_key = NULL;
260 pub_key_len = 0;
261
262 /*
263 * Decode public key from PEM and check raw private and raw public.
264 */
265
266 if ((bio = BIO_new_mem_buf(ed25519_pub_key_1, -1)) == NULL)
267 errx(1, "failed to create BIO for key");
268 if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
269 fprintf(stderr, "FAIL: failed to read public key\n");
270 ERR_print_errors_fp(stderr);
271 goto failure;
272 }
273
274 /*
275 * Yet another astounding API design - we cannot tell if the private key
276 * is not present, or if some other failure occurred.
277 */
278 if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) {
279 fprintf(stderr, "FAIL: failed to get raw priv key len\n");
280 goto failure;
281 }
282 if ((priv_key = malloc(priv_key_len)) == NULL)
283 errx(1, "failed to malloc priv key");
284 if (EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) {
285 fprintf(stderr, "FAIL: got raw private key, should fail\n");
286 goto failure;
287 }
288
289 if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) {
290 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
291 goto failure;
292 }
293 if (pub_key_len != sizeof(ed25519_raw_pub_key_1)) {
294 fprintf(stderr, "FAIL: raw public key length differs "
295 "(%zu != %zu)\n", pub_key_len,
296 sizeof(ed25519_raw_pub_key_1));
297 goto failure;
298 }
299 if ((pub_key = malloc(pub_key_len)) == NULL)
300 errx(1, "failed to malloc private key");
301 if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) {
302 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
303 goto failure;
304 }
305 if (memcmp(pub_key, ed25519_raw_pub_key_1, pub_key_len) != 0) {
306 fprintf(stderr, "FAIL: get raw public key failed\n");
307 fprintf(stderr, "Got:\n");
308 hexdump(pub_key, pub_key_len);
309 fprintf(stderr, "Want:\n");
310 hexdump(ed25519_raw_pub_key_1, sizeof(ed25519_raw_pub_key_1));
311 goto failure;
312 }
313
314 BIO_free(bio);
315 bio = NULL;
316
317 EVP_PKEY_free(pkey);
318 pkey = NULL;
319
320 /*
321 * Create PKEY from raw private, check PEM encoded private and public.
322 */
323 if ((pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
324 ed25519_raw_priv_key_1, sizeof(ed25519_raw_priv_key_1))) == NULL) {
325 fprintf(stderr, "FAIL: PKEY from raw private key failed");
326 goto failure;
327 }
328 if ((bio = BIO_new(BIO_s_mem())) == NULL)
329 goto failure;
330 if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
331 fprintf(stderr, "FAIL: failed to write ED25519 private to PEM\n");
332 goto failure;
333 }
334 BIO_get_mem_data(bio, &pp);
335 if (strcmp(ed25519_priv_key_1, pp) != 0) {
336 fprintf(stderr, "FAIL: resulting private key PEM differs\n");
337 goto failure;
338 }
339
340 (void)BIO_reset(bio);
341 if (!PEM_write_bio_PUBKEY(bio, pkey)) {
342 fprintf(stderr, "FAIL: failed to write ED25519 public to PEM\n");
343 goto failure;
344 }
345 BIO_get_mem_data(bio, &pp);
346 if (strcmp(ed25519_pub_key_1, pp) != 0) {
347 fprintf(stderr, "FAIL: resulting public key PEM differs\n");
348 fprintf(stderr, "%s\n", ed25519_pub_key_1);
349 fprintf(stderr, "%s\n", pp);
350 //goto failure;
351 }
352
353 EVP_PKEY_free(pkey);
354 pkey = NULL;
355
356 /*
357 * Create PKEY from raw public, check public key PEM.
358 */
359 if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
360 ed25519_raw_pub_key_1, sizeof(ed25519_raw_pub_key_1))) == NULL) {
361 fprintf(stderr, "FAIL: PKEY from raw public key failed");
362 goto failure;
363 }
364 (void)BIO_reset(bio);
365 if (!PEM_write_bio_PUBKEY(bio, pkey)) {
366 fprintf(stderr, "FAIL: failed to write ED25519 public to PEM\n");
367 goto failure;
368 }
369 BIO_get_mem_data(bio, &pp);
370 if (strcmp(ed25519_pub_key_1, pp) != 0) {
371 fprintf(stderr, "FAIL: resulting public key PEM differs\n");
372 goto failure;
373 }
374
375 failed = 0;
376
377 failure:
378 BIO_free(bio);
379 EVP_PKEY_free(pkey);
380 freezero(priv_key, priv_key_len);
381 freezero(pub_key, pub_key_len);
382
383 return failed;
384 }
385
386 static int
ecx_ed25519_sign_test(void)387 ecx_ed25519_sign_test(void)
388 {
389 EVP_MD_CTX *md_ctx = NULL;
390 EVP_PKEY *pkey = NULL;
391 uint8_t *signature = NULL;
392 size_t signature_len = 0;
393 BIO *bio = NULL;
394 int failed = 1;
395
396 if ((bio = BIO_new_mem_buf(ed25519_priv_key_1, -1)) == NULL)
397 errx(1, "failed to create BIO for key");
398 if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) {
399 fprintf(stderr, "FAIL: failed to read private key\n");
400 ERR_print_errors_fp(stderr);
401 goto failure;
402 }
403
404 if ((md_ctx = EVP_MD_CTX_new()) == NULL)
405 errx(1, "failed to create MD_CTX");
406
407 if (!EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, pkey)) {
408 fprintf(stderr, "FAIL: failed to init digest sign\n");
409 ERR_print_errors_fp(stderr);
410 goto failure;
411 }
412 if (!EVP_DigestSign(md_ctx, NULL, &signature_len, NULL, 0)) {
413 fprintf(stderr, "FAIL: failed to digest sign update\n");
414 goto failure;
415 }
416 if ((signature = calloc(1, signature_len)) == NULL)
417 errx(1, "failed to allocate signature");
418 if (!EVP_DigestSign(md_ctx, signature, &signature_len, message_1,
419 sizeof(message_1))) {
420 fprintf(stderr, "FAIL: failed to digest sign update\n");
421 goto failure;
422 }
423
424 if (signature_len != sizeof(signature_1)) {
425 fprintf(stderr, "FAIL: signature length differs (%zu != %zu)\n",
426 signature_len, sizeof(signature_1));
427 goto failure;
428 }
429
430 if (memcmp(signature, signature_1, signature_len) != 0) {
431 fprintf(stderr, "FAIL: Ed25519 sign failed\n");
432 fprintf(stderr, "Got:\n");
433 hexdump(signature, signature_len);
434 fprintf(stderr, "Want:\n");
435 hexdump(signature_1, sizeof(signature_1));
436 goto failure;
437 }
438
439 failed = 0;
440
441 failure:
442 BIO_free(bio);
443 EVP_MD_CTX_free(md_ctx);
444 EVP_PKEY_free(pkey);
445 free(signature);
446
447 return failed;
448 }
449
450 static int
ecx_ed25519_verify_test(void)451 ecx_ed25519_verify_test(void)
452 {
453 EVP_MD_CTX *md_ctx = NULL;
454 EVP_PKEY *pkey = NULL;
455 BIO *bio = NULL;
456 int failed = 1;
457
458 if ((bio = BIO_new_mem_buf(ed25519_pub_key_1, -1)) == NULL)
459 errx(1, "failed to create BIO for key");
460 if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
461 fprintf(stderr, "FAIL: failed to read public key\n");
462 ERR_print_errors_fp(stderr);
463 goto failure;
464 }
465
466 if ((md_ctx = EVP_MD_CTX_new()) == NULL)
467 errx(1, "failed to create MD_CTX");
468
469 if (!EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, pkey)) {
470 fprintf(stderr, "FAIL: failed to init digest verify\n");
471 ERR_print_errors_fp(stderr);
472 goto failure;
473 }
474 if (!EVP_DigestVerify(md_ctx, signature_1, sizeof(signature_1),
475 message_1, sizeof(message_1))) {
476 fprintf(stderr, "FAIL: failed to digest verify update\n");
477 goto failure;
478 }
479
480 failed = 0;
481
482 failure:
483 BIO_free(bio);
484 EVP_MD_CTX_free(md_ctx);
485 EVP_PKEY_free(pkey);
486
487 return failed;
488 }
489
490 static int
ecx_x25519_keygen_test(void)491 ecx_x25519_keygen_test(void)
492 {
493 EVP_PKEY_CTX *pkey_ctx = NULL;
494 EVP_PKEY *pkey = NULL;
495 BIO *bio = NULL;
496 int failed = 1;
497
498 if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL)) == NULL) {
499 fprintf(stderr, "FAIL: failed to create X25519 context\n");
500 goto failure;
501 }
502
503 if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) {
504 fprintf(stderr, "FAIL: failed to init keygen for X25519\n");
505 goto failure;
506 }
507 if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) {
508 fprintf(stderr, "FAIL: failed to generate X25519 key\n");
509 goto failure;
510 }
511
512 if ((bio = BIO_new(BIO_s_mem())) == NULL)
513 goto failure;
514 if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
515 fprintf(stderr, "FAIL: failed to write X25519 to PEM\n");
516 goto failure;
517 }
518
519 failed = 0;
520
521 failure:
522 BIO_free(bio);
523 EVP_PKEY_CTX_free(pkey_ctx);
524 EVP_PKEY_free(pkey);
525
526 return failed;
527 }
528
529 static int
ecx_x25519_derive_test(void)530 ecx_x25519_derive_test(void)
531 {
532 EVP_PKEY_CTX *pkey_ctx = NULL;
533 EVP_PKEY *pkey = NULL, *pkey_peer = NULL;
534 uint8_t *shared_key = NULL;
535 size_t shared_key_len = 0;
536 BIO *bio = NULL;
537 int failed = 1;
538
539 if ((bio = BIO_new_mem_buf(x25519_priv_key_1, -1)) == NULL)
540 errx(1, "failed to create BIO for key");
541 if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) {
542 fprintf(stderr, "FAIL: failed to read private key\n");
543 ERR_print_errors_fp(stderr);
544 goto failure;
545 }
546
547 BIO_free(bio);
548 if ((bio = BIO_new_mem_buf(x25519_pub_key_2, -1)) == NULL)
549 errx(1, "failed to create BIO for key");
550 if ((pkey_peer = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
551 fprintf(stderr, "FAIL: failed to read peer public key\n");
552 ERR_print_errors_fp(stderr);
553 goto failure;
554 }
555
556 if ((pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) {
557 fprintf(stderr, "FAIL: failed to create X25519 context\n");
558 goto failure;
559 }
560 if (EVP_PKEY_derive_init(pkey_ctx) <= 0) {
561 fprintf(stderr, "FAIL: failed to init derive for X25519\n");
562 goto failure;
563 }
564 if (EVP_PKEY_derive_set_peer(pkey_ctx, pkey_peer) <= 0) {
565 fprintf(stderr, "FAIL: failed to set peer key for X25519\n");
566 goto failure;
567 }
568 if (EVP_PKEY_derive(pkey_ctx, NULL, &shared_key_len) <= 0) {
569 fprintf(stderr, "FAIL: failed to derive X25519 key length\n");
570 goto failure;
571 }
572 if ((shared_key = malloc(shared_key_len)) == NULL)
573 errx(1, "failed to malloc shared key");
574 if (EVP_PKEY_derive(pkey_ctx, shared_key, &shared_key_len) <= 0) {
575 fprintf(stderr, "FAIL: failed to derive X25519 key\n");
576 goto failure;
577 }
578
579 if (shared_key_len != sizeof(shared_key_1)) {
580 fprintf(stderr, "FAIL: shared key length differs (%zu != %zu)\n",
581 shared_key_len, sizeof(shared_key_1));
582 goto failure;
583 }
584
585 if (memcmp(shared_key, shared_key_1, shared_key_len) != 0) {
586 fprintf(stderr, "FAIL: X25519 derive failed\n");
587 fprintf(stderr, "Got:\n");
588 hexdump(shared_key, shared_key_len);
589 fprintf(stderr, "Want:\n");
590 hexdump(shared_key_1, sizeof(shared_key_1));
591 goto failure;
592 }
593
594 failed = 0;
595
596 failure:
597 BIO_free(bio);
598 EVP_PKEY_CTX_free(pkey_ctx);
599 EVP_PKEY_free(pkey_peer);
600 EVP_PKEY_free(pkey);
601 freezero(shared_key, shared_key_len);
602
603 return failed;
604 }
605
606 static int
ecx_x25519_raw_key_test(void)607 ecx_x25519_raw_key_test(void)
608 {
609 EVP_PKEY *pkey = NULL;
610 uint8_t *priv_key = NULL;
611 size_t priv_key_len = 0;
612 uint8_t *pub_key = NULL;
613 size_t pub_key_len = 0;
614 const uint8_t *pp;
615 BIO *bio = NULL;
616 int failed = 1;
617
618 /*
619 * Decode private key from PEM and check raw private and raw public.
620 */
621
622 if ((bio = BIO_new_mem_buf(x25519_priv_key_2, -1)) == NULL)
623 errx(1, "failed to create BIO for key");
624 if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) {
625 fprintf(stderr, "FAIL: failed to read private key\n");
626 ERR_print_errors_fp(stderr);
627 goto failure;
628 }
629
630 if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) {
631 fprintf(stderr, "FAIL: failed to get raw private key len\n");
632 goto failure;
633 }
634 if (priv_key_len != sizeof(x25519_raw_priv_key_2)) {
635 fprintf(stderr, "FAIL: raw private key length differs "
636 "(%zu != %zu)\n", priv_key_len,
637 sizeof(x25519_raw_priv_key_2));
638 goto failure;
639 }
640 if ((priv_key = malloc(priv_key_len)) == NULL)
641 errx(1, "failed to malloc priv key");
642 if (!EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) {
643 fprintf(stderr, "FAIL: failed to get raw private key len\n");
644 goto failure;
645 }
646 if (memcmp(priv_key, x25519_raw_priv_key_2, priv_key_len) != 0) {
647 fprintf(stderr, "FAIL: get raw private key failed\n");
648 fprintf(stderr, "Got:\n");
649 hexdump(priv_key, priv_key_len);
650 fprintf(stderr, "Want:\n");
651 hexdump(x25519_raw_priv_key_2, sizeof(x25519_raw_priv_key_2));
652 goto failure;
653 }
654
655 if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) {
656 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
657 goto failure;
658 }
659 if (pub_key_len != sizeof(x25519_raw_pub_key_2)) {
660 fprintf(stderr, "FAIL: raw public key length differs "
661 "(%zu != %zu)\n", pub_key_len,
662 sizeof(x25519_raw_pub_key_2));
663 goto failure;
664 }
665 if ((pub_key = malloc(pub_key_len)) == NULL)
666 errx(1, "failed to malloc private key");
667 if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) {
668 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
669 goto failure;
670 }
671 if (memcmp(pub_key, x25519_raw_pub_key_2, pub_key_len) != 0) {
672 fprintf(stderr, "FAIL: get raw public key failed\n");
673 fprintf(stderr, "Got:\n");
674 hexdump(pub_key, pub_key_len);
675 fprintf(stderr, "Want:\n");
676 hexdump(x25519_raw_pub_key_2, sizeof(x25519_raw_pub_key_2));
677 goto failure;
678 }
679
680 BIO_free(bio);
681 bio = NULL;
682
683 EVP_PKEY_free(pkey);
684 pkey = NULL;
685
686 freezero(priv_key, priv_key_len);
687 priv_key = NULL;
688 priv_key_len = 0;
689
690 freezero(pub_key, pub_key_len);
691 pub_key = NULL;
692 pub_key_len = 0;
693
694 /*
695 * Decode public key from PEM and check raw private and raw public.
696 */
697
698 if ((bio = BIO_new_mem_buf(x25519_pub_key_1, -1)) == NULL)
699 errx(1, "failed to create BIO for key");
700 if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
701 fprintf(stderr, "FAIL: failed to read public key\n");
702 ERR_print_errors_fp(stderr);
703 goto failure;
704 }
705
706 /*
707 * Yet another astounding API design - we cannot tell if the private key
708 * is not present, or if some other failure occurred.
709 */
710 if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) {
711 fprintf(stderr, "FAIL: failed to get raw priv key len\n");
712 goto failure;
713 }
714 if ((priv_key = malloc(priv_key_len)) == NULL)
715 errx(1, "failed to malloc priv key");
716 if (EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) {
717 fprintf(stderr, "FAIL: got raw private key, should fail\n");
718 goto failure;
719 }
720
721 if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) {
722 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
723 goto failure;
724 }
725 if (pub_key_len != sizeof(x25519_raw_pub_key_1)) {
726 fprintf(stderr, "FAIL: raw public key length differs "
727 "(%zu != %zu)\n", pub_key_len,
728 sizeof(x25519_raw_pub_key_1));
729 goto failure;
730 }
731 if ((pub_key = malloc(pub_key_len)) == NULL)
732 errx(1, "failed to malloc private key");
733 if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) {
734 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
735 goto failure;
736 }
737 if (memcmp(pub_key, x25519_raw_pub_key_1, pub_key_len) != 0) {
738 fprintf(stderr, "FAIL: get raw public key failed\n");
739 fprintf(stderr, "Got:\n");
740 hexdump(pub_key, pub_key_len);
741 fprintf(stderr, "Want:\n");
742 hexdump(x25519_raw_pub_key_1, sizeof(x25519_raw_pub_key_1));
743 goto failure;
744 }
745
746 BIO_free(bio);
747 bio = NULL;
748
749 EVP_PKEY_free(pkey);
750 pkey = NULL;
751
752 /*
753 * Create PKEY from raw private, check PEM encoded private and public.
754 */
755 if ((pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
756 x25519_raw_priv_key_2, sizeof(x25519_raw_priv_key_2))) == NULL) {
757 fprintf(stderr, "FAIL: PKEY from raw private key failed");
758 goto failure;
759 }
760 if ((bio = BIO_new(BIO_s_mem())) == NULL)
761 goto failure;
762 if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
763 fprintf(stderr, "FAIL: failed to write X25519 private to PEM\n");
764 goto failure;
765 }
766 BIO_get_mem_data(bio, &pp);
767 if (strcmp(x25519_priv_key_2, pp) != 0) {
768 fprintf(stderr, "FAIL: resulting private key PEM differs\n");
769 goto failure;
770 }
771
772 (void)BIO_reset(bio);
773 if (!PEM_write_bio_PUBKEY(bio, pkey)) {
774 fprintf(stderr, "FAIL: failed to write X25519 public to PEM\n");
775 goto failure;
776 }
777 BIO_get_mem_data(bio, &pp);
778 if (strcmp(x25519_pub_key_2, pp) != 0) {
779 fprintf(stderr, "FAIL: resulting public key PEM differs\n");
780 goto failure;
781 }
782
783 EVP_PKEY_free(pkey);
784 pkey = NULL;
785
786 /*
787 * Create PKEY from raw public, check public key PEM.
788 */
789 if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
790 x25519_raw_pub_key_1, sizeof(x25519_raw_pub_key_1))) == NULL) {
791 fprintf(stderr, "FAIL: PKEY from raw public key failed");
792 goto failure;
793 }
794 (void)BIO_reset(bio);
795 if (!PEM_write_bio_PUBKEY(bio, pkey)) {
796 fprintf(stderr, "FAIL: failed to write X25519 public to PEM\n");
797 goto failure;
798 }
799 BIO_get_mem_data(bio, &pp);
800 if (strcmp(x25519_pub_key_1, pp) != 0) {
801 fprintf(stderr, "FAIL: resulting public key PEM differs\n");
802 goto failure;
803 }
804
805 failed = 0;
806
807 failure:
808 BIO_free(bio);
809 EVP_PKEY_free(pkey);
810 freezero(priv_key, priv_key_len);
811 freezero(pub_key, pub_key_len);
812
813 return failed;
814 }
815
816 int
main(int argc,char ** argv)817 main(int argc, char **argv)
818 {
819 int failed = 0;
820
821 failed |= ecx_ed25519_raw_key_test();
822 failed |= ecx_ed25519_keygen_test();
823 failed |= ecx_ed25519_sign_test();
824 failed |= ecx_ed25519_verify_test();
825
826 failed |= ecx_x25519_keygen_test();
827 failed |= ecx_x25519_derive_test();
828 failed |= ecx_x25519_raw_key_test();
829
830 return failed;
831 }
832