summaryrefslogtreecommitdiff
path: root/src/regress/lib
diff options
context:
space:
mode:
authorjsing <>2022-11-10 16:38:57 +0000
committerjsing <>2022-11-10 16:38:57 +0000
commitbd20ce990254afb9a42b5f0759a1e0c15541479b (patch)
tree726d0e51fffb71e15cbb656c14caf6f41ee5aed3 /src/regress/lib
parent8bbca4710a981e94365a52a3aad374c251e1d0a5 (diff)
downloadopenbsd-bd20ce990254afb9a42b5f0759a1e0c15541479b.tar.gz
openbsd-bd20ce990254afb9a42b5f0759a1e0c15541479b.tar.bz2
openbsd-bd20ce990254afb9a42b5f0759a1e0c15541479b.zip
Add regress coverage for Ed25519 and X25519 EVP interfaces.
Diffstat (limited to 'src/regress/lib')
-rw-r--r--src/regress/lib/libcrypto/evp/Makefile11
-rw-r--r--src/regress/lib/libcrypto/evp/evp_ecx_test.c829
2 files changed, 838 insertions, 2 deletions
diff --git a/src/regress/lib/libcrypto/evp/Makefile b/src/regress/lib/libcrypto/evp/Makefile
index 8c6fa2305b..956ae8a5e6 100644
--- a/src/regress/lib/libcrypto/evp/Makefile
+++ b/src/regress/lib/libcrypto/evp/Makefile
@@ -1,23 +1,30 @@
1# $OpenBSD: Makefile,v 1.8 2022/11/09 16:13:39 jsing Exp $ 1# $OpenBSD: Makefile,v 1.9 2022/11/10 16:38:57 jsing Exp $
2 2
3PROGS= evptest evp_test evp_pkey_check evp_pkey_cleanup 3PROGS= evptest evp_test evp_ecx_test evp_pkey_check evp_pkey_cleanup
4LDADD= -lcrypto 4LDADD= -lcrypto
5DPADD= ${LIBCRYPTO} 5DPADD= ${LIBCRYPTO}
6WARNINGS= Yes 6WARNINGS= Yes
7CFLAGS+= -DLIBRESSL_INTERNAL -DLIBRESSL_CRYPTO_INTERNAL -Werror 7CFLAGS+= -DLIBRESSL_INTERNAL -DLIBRESSL_CRYPTO_INTERNAL -Werror
8CFLAGS+= -I${.CURDIR}/../../../../lib/libcrypto/curve25519
8CFLAGS+= -I${.CURDIR}/../../../../lib/libcrypto/evp 9CFLAGS+= -I${.CURDIR}/../../../../lib/libcrypto/evp
9 10
10REGRESS_TARGETS+= regress-evptest 11REGRESS_TARGETS+= regress-evptest
11REGRESS_TARGETS+= regress-evp_test 12REGRESS_TARGETS+= regress-evp_test
13REGRESS_TARGETS+= regress-evp_ecx_test
12REGRESS_TARGETS+= regress-evp_pkey_check 14REGRESS_TARGETS+= regress-evp_pkey_check
13REGRESS_TARGETS+= regress-evp_pkey_cleanup 15REGRESS_TARGETS+= regress-evp_pkey_cleanup
14 16
17LDADD_evp_ecx_test = ${CRYPTO_INT}
18
15regress-evptest: evptest 19regress-evptest: evptest
16 ./evptest ${.CURDIR}/evptests.txt 20 ./evptest ${.CURDIR}/evptests.txt
17 21
18regress-evp_test: evp_test 22regress-evp_test: evp_test
19 ./evp_test 23 ./evp_test
20 24
25regress-evp_ecx_test: evp_ecx_test
26 ./evp_ecx_test
27
21regress-evp_pkey_check: evp_pkey_check 28regress-evp_pkey_check: evp_pkey_check
22 ./evp_pkey_check 29 ./evp_pkey_check
23 30
diff --git a/src/regress/lib/libcrypto/evp/evp_ecx_test.c b/src/regress/lib/libcrypto/evp/evp_ecx_test.c
new file mode 100644
index 0000000000..a20902440c
--- /dev/null
+++ b/src/regress/lib/libcrypto/evp/evp_ecx_test.c
@@ -0,0 +1,829 @@
1/* $OpenBSD: evp_ecx_test.c,v 1.1 2022/11/10 16:38:57 jsing 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
27static const uint8_t ed25519_priv_key_1[] = \
28 "-----BEGIN PRIVATE KEY-----\n"
29 "MC4CAQAwBQYDK2VwBCIEIIkDg89yB70IpUXsAZieCcCDE2ig9nin9JJWpDQoCup8\n"
30 "-----END PRIVATE KEY-----\n";
31
32const 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
39static const uint8_t ed25519_pub_key_1[] = \
40 "-----BEGIN PUBLIC KEY-----\n"
41 "MCowBQYDK2VwAyEA1vxPpbnoC7G8vFmRjYVXUU2aln3hUZEgfW1atlTHF/o=\n"
42 "-----END PUBLIC KEY-----\n";
43
44const 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
51static 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
58static 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
69static const uint8_t x25519_priv_key_1[] = \
70 "-----BEGIN PRIVATE KEY-----\n"
71 "MC4CAQAwBQYDK2VuBCIEICi6rzFFJb02mi6sopELeshEi2vr68ul4bzEHPOz+K1o\n"
72 "-----END PRIVATE KEY-----\n";
73
74const 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
81static const uint8_t x25519_pub_key_1[] = \
82 "-----BEGIN PUBLIC KEY-----\n"
83 "MCowBQYDK2VuAyEAu4WHXnAQL2YfonJhuoEO9PM2WwXjveApPmCXSiDnf1M=\n"
84 "-----END PUBLIC KEY-----\n";
85
86static 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
93static const uint8_t x25519_priv_key_2[] = \
94 "-----BEGIN PRIVATE KEY-----\n"
95 "MC4CAQAwBQYDK2VuBCIEIAg9Jbp/Ma0TO4r179WGGiv+VnGxGNRh4VNrHUij7Ql/\n"
96 "-----END PRIVATE KEY-----\n";
97
98static 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
105static const uint8_t x25519_pub_key_2[] = \
106 "-----BEGIN PUBLIC KEY-----\n"
107 "MCowBQYDK2VuAyEABvksGQRgsUXEK5CaniVZ59pPvDoABgBSdAM+EF0Q9Cw=\n"
108 "-----END PUBLIC KEY-----\n";
109
110static 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
117static 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
124static void
125hexdump(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
135static int
136ecx_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
174static int
175ecx_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 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 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
386static int
387ecx_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_PKEY_free(pkey);
444 free(signature);
445
446 return failed;
447}
448
449static int
450ecx_ed25519_verify_test(void)
451{
452 EVP_MD_CTX *md_ctx = NULL;
453 EVP_PKEY *pkey = NULL;
454 BIO *bio = NULL;
455 int failed = 1;
456
457 if ((bio = BIO_new_mem_buf(ed25519_pub_key_1, -1)) == NULL)
458 errx(1, "failed to create BIO for key");
459 if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
460 fprintf(stderr, "FAIL: failed to read public key\n");
461 ERR_print_errors_fp(stderr);
462 goto failure;
463 }
464
465 if ((md_ctx = EVP_MD_CTX_new()) == NULL)
466 errx(1, "failed to create MD_CTX");
467
468 if (!EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, pkey)) {
469 fprintf(stderr, "FAIL: failed to init digest verify\n");
470 ERR_print_errors_fp(stderr);
471 goto failure;
472 }
473 if (!EVP_DigestVerify(md_ctx, signature_1, sizeof(signature_1),
474 message_1, sizeof(message_1))) {
475 fprintf(stderr, "FAIL: failed to digest verify update\n");
476 goto failure;
477 }
478
479 failed = 0;
480
481 failure:
482 BIO_free(bio);
483 EVP_PKEY_free(pkey);
484
485 return failed;
486}
487
488static int
489ecx_x25519_keygen_test(void)
490{
491 EVP_PKEY_CTX *pkey_ctx = NULL;
492 EVP_PKEY *pkey = NULL;
493 BIO *bio = NULL;
494 int failed = 1;
495
496 if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL)) == NULL) {
497 fprintf(stderr, "FAIL: failed to create X25519 context\n");
498 goto failure;
499 }
500
501 if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) {
502 fprintf(stderr, "FAIL: failed to init keygen for X25519\n");
503 goto failure;
504 }
505 if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) {
506 fprintf(stderr, "FAIL: failed to generate X25519 key\n");
507 goto failure;
508 }
509
510 if ((bio = BIO_new(BIO_s_mem())) == NULL)
511 goto failure;
512 if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
513 fprintf(stderr, "FAIL: failed to write X25519 to PEM\n");
514 goto failure;
515 }
516
517 failed = 0;
518
519 failure:
520 BIO_free(bio);
521 EVP_PKEY_CTX_free(pkey_ctx);
522 EVP_PKEY_free(pkey);
523
524 return failed;
525}
526
527static int
528ecx_x25519_derive_test(void)
529{
530 EVP_PKEY_CTX *pkey_ctx = NULL;
531 EVP_PKEY *pkey = NULL, *pkey_peer = NULL;
532 uint8_t *shared_key = NULL;
533 size_t shared_key_len = 0;
534 BIO *bio = NULL;
535 int failed = 1;
536
537 if ((bio = BIO_new_mem_buf(x25519_priv_key_1, -1)) == NULL)
538 errx(1, "failed to create BIO for key");
539 if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) {
540 fprintf(stderr, "FAIL: failed to read private key\n");
541 ERR_print_errors_fp(stderr);
542 goto failure;
543 }
544
545 BIO_free(bio);
546 if ((bio = BIO_new_mem_buf(x25519_pub_key_2, -1)) == NULL)
547 errx(1, "failed to create BIO for key");
548 if ((pkey_peer = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
549 fprintf(stderr, "FAIL: failed to read peer public key\n");
550 ERR_print_errors_fp(stderr);
551 goto failure;
552 }
553
554 if ((pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) {
555 fprintf(stderr, "FAIL: failed to create X25519 context\n");
556 goto failure;
557 }
558 if (EVP_PKEY_derive_init(pkey_ctx) <= 0) {
559 fprintf(stderr, "FAIL: failed to init derive for X25519\n");
560 goto failure;
561 }
562 if (EVP_PKEY_derive_set_peer(pkey_ctx, pkey_peer) <= 0) {
563 fprintf(stderr, "FAIL: failed to set peer key for X25519\n");
564 goto failure;
565 }
566 if (EVP_PKEY_derive(pkey_ctx, NULL, &shared_key_len) <= 0) {
567 fprintf(stderr, "FAIL: failed to derive X25519 key length\n");
568 goto failure;
569 }
570 if ((shared_key = malloc(shared_key_len)) == NULL)
571 errx(1, "failed to malloc shared key");
572 if (EVP_PKEY_derive(pkey_ctx, shared_key, &shared_key_len) <= 0) {
573 fprintf(stderr, "FAIL: failed to derive X25519 key\n");
574 goto failure;
575 }
576
577 if (shared_key_len != sizeof(shared_key_1)) {
578 fprintf(stderr, "FAIL: shared key length differs (%zu != %zu)\n",
579 shared_key_len, sizeof(shared_key_1));
580 goto failure;
581 }
582
583 if (memcmp(shared_key, shared_key_1, shared_key_len) != 0) {
584 fprintf(stderr, "FAIL: X25519 derive failed\n");
585 fprintf(stderr, "Got:\n");
586 hexdump(shared_key, shared_key_len);
587 fprintf(stderr, "Want:\n");
588 hexdump(shared_key_1, sizeof(shared_key_1));
589 goto failure;
590 }
591
592 failed = 0;
593
594 failure:
595 BIO_free(bio);
596 EVP_PKEY_CTX_free(pkey_ctx);
597 EVP_PKEY_free(pkey_peer);
598 EVP_PKEY_free(pkey);
599 freezero(shared_key, shared_key_len);
600
601 return failed;
602}
603
604static int
605ecx_x25519_raw_key_test(void)
606{
607 EVP_PKEY *pkey = NULL;
608 uint8_t *priv_key = NULL;
609 size_t priv_key_len = 0;
610 uint8_t *pub_key = NULL;
611 size_t pub_key_len = 0;
612 const uint8_t *pp;
613 BIO *bio = NULL;
614 int failed = 1;
615
616 /*
617 * Decode private key from PEM and check raw private and raw public.
618 */
619
620 if ((bio = BIO_new_mem_buf(x25519_priv_key_2, -1)) == NULL)
621 errx(1, "failed to create BIO for key");
622 if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) {
623 fprintf(stderr, "FAIL: failed to read private key\n");
624 ERR_print_errors_fp(stderr);
625 goto failure;
626 }
627
628 if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) {
629 fprintf(stderr, "FAIL: failed to get raw private key len\n");
630 goto failure;
631 }
632 if (priv_key_len != sizeof(x25519_raw_priv_key_2)) {
633 fprintf(stderr, "FAIL: raw private key length differs "
634 "(%zu != %zu)\n", priv_key_len,
635 sizeof(x25519_raw_priv_key_2));
636 goto failure;
637 }
638 if ((priv_key = malloc(priv_key_len)) == NULL)
639 errx(1, "failed to malloc priv key");
640 if (!EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) {
641 fprintf(stderr, "FAIL: failed to get raw private key len\n");
642 goto failure;
643 }
644 if (memcmp(priv_key, x25519_raw_priv_key_2, priv_key_len) != 0) {
645 fprintf(stderr, "FAIL: get raw private key failed\n");
646 fprintf(stderr, "Got:\n");
647 hexdump(priv_key, priv_key_len);
648 fprintf(stderr, "Want:\n");
649 hexdump(x25519_raw_priv_key_2, sizeof(x25519_raw_priv_key_2));
650 goto failure;
651 }
652
653 if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) {
654 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
655 goto failure;
656 }
657 if (pub_key_len != sizeof(x25519_raw_pub_key_2)) {
658 fprintf(stderr, "FAIL: raw public key length differs "
659 "(%zu != %zu)\n", pub_key_len,
660 sizeof(x25519_raw_pub_key_2));
661 goto failure;
662 }
663 if ((pub_key = malloc(pub_key_len)) == NULL)
664 errx(1, "failed to malloc private key");
665 if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) {
666 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
667 goto failure;
668 }
669 if (memcmp(pub_key, x25519_raw_pub_key_2, pub_key_len) != 0) {
670 fprintf(stderr, "FAIL: get raw public key failed\n");
671 fprintf(stderr, "Got:\n");
672 hexdump(pub_key, pub_key_len);
673 fprintf(stderr, "Want:\n");
674 hexdump(x25519_raw_pub_key_2, sizeof(x25519_raw_pub_key_2));
675 goto failure;
676 }
677
678 BIO_free(bio);
679 bio = NULL;
680
681 EVP_PKEY_free(pkey);
682 pkey = NULL;
683
684 freezero(priv_key, priv_key_len);
685 priv_key = NULL;
686 priv_key_len = 0;
687
688 freezero(pub_key, pub_key_len);
689 pub_key = NULL;
690 pub_key_len = 0;
691
692 /*
693 * Decode public key from PEM and check raw private and raw public.
694 */
695
696 if ((bio = BIO_new_mem_buf(x25519_pub_key_1, -1)) == NULL)
697 errx(1, "failed to create BIO for key");
698 if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
699 fprintf(stderr, "FAIL: failed to read public key\n");
700 ERR_print_errors_fp(stderr);
701 goto failure;
702 }
703
704 /*
705 * Yet another astounding API design - we cannot tell if the private key
706 * is not present, or if some other failure occurred.
707 */
708 if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) {
709 fprintf(stderr, "FAIL: failed to get raw priv key len\n");
710 goto failure;
711 }
712 if ((priv_key = malloc(priv_key_len)) == NULL)
713 errx(1, "failed to malloc priv key");
714 if (EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) {
715 fprintf(stderr, "FAIL: got raw private key, should fail\n");
716 goto failure;
717 }
718
719 if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) {
720 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
721 goto failure;
722 }
723 if (pub_key_len != sizeof(x25519_raw_pub_key_1)) {
724 fprintf(stderr, "FAIL: raw public key length differs "
725 "(%zu != %zu)\n", pub_key_len,
726 sizeof(x25519_raw_pub_key_2));
727 goto failure;
728 }
729 if ((pub_key = malloc(pub_key_len)) == NULL)
730 errx(1, "failed to malloc private key");
731 if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) {
732 fprintf(stderr, "FAIL: failed to get raw pub key len\n");
733 goto failure;
734 }
735 if (memcmp(pub_key, x25519_raw_pub_key_1, pub_key_len) != 0) {
736 fprintf(stderr, "FAIL: get raw public key failed\n");
737 fprintf(stderr, "Got:\n");
738 hexdump(pub_key, pub_key_len);
739 fprintf(stderr, "Want:\n");
740 hexdump(x25519_raw_pub_key_2, sizeof(x25519_raw_pub_key_2));
741 goto failure;
742 }
743
744 BIO_free(bio);
745 bio = NULL;
746
747 EVP_PKEY_free(pkey);
748 pkey = NULL;
749
750 /*
751 * Create PKEY from raw private, check PEM encoded private and public.
752 */
753 if ((pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
754 x25519_raw_priv_key_2, sizeof(x25519_raw_priv_key_2))) == NULL) {
755 fprintf(stderr, "FAIL: PKEY from raw private key failed");
756 goto failure;
757 }
758 if ((bio = BIO_new(BIO_s_mem())) == NULL)
759 goto failure;
760 if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
761 fprintf(stderr, "FAIL: failed to write X25519 private to PEM\n");
762 goto failure;
763 }
764 BIO_get_mem_data(bio, &pp);
765 if (strcmp(x25519_priv_key_2, pp) != 0) {
766 fprintf(stderr, "FAIL: resulting private key PEM differs\n");
767 goto failure;
768 }
769
770 BIO_reset(bio);
771 if (!PEM_write_bio_PUBKEY(bio, pkey)) {
772 fprintf(stderr, "FAIL: failed to write X25519 public to PEM\n");
773 goto failure;
774 }
775 BIO_get_mem_data(bio, &pp);
776 if (strcmp(x25519_pub_key_2, pp) != 0) {
777 fprintf(stderr, "FAIL: resulting public key PEM differs\n");
778 goto failure;
779 }
780
781 EVP_PKEY_free(pkey);
782 pkey = NULL;
783
784 /*
785 * Create PKEY from raw public, check public key PEM.
786 */
787 if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
788 x25519_raw_pub_key_1, sizeof(x25519_raw_pub_key_1))) == NULL) {
789 fprintf(stderr, "FAIL: PKEY from raw public key failed");
790 goto failure;
791 }
792 BIO_reset(bio);
793 if (!PEM_write_bio_PUBKEY(bio, pkey)) {
794 fprintf(stderr, "FAIL: failed to write X25519 public to PEM\n");
795 goto failure;
796 }
797 BIO_get_mem_data(bio, &pp);
798 if (strcmp(x25519_pub_key_1, pp) != 0) {
799 fprintf(stderr, "FAIL: resulting public key PEM differs\n");
800 goto failure;
801 }
802
803 failed = 0;
804
805 failure:
806 BIO_free(bio);
807 EVP_PKEY_free(pkey);
808 freezero(priv_key, priv_key_len);
809 freezero(pub_key, pub_key_len);
810
811 return failed;
812}
813
814int
815main(int argc, char **argv)
816{
817 int failed = 0;
818
819 failed |= ecx_ed25519_raw_key_test();
820 failed |= ecx_ed25519_keygen_test();
821 failed |= ecx_ed25519_sign_test();
822 failed |= ecx_ed25519_verify_test();
823
824 failed |= ecx_x25519_keygen_test();
825 failed |= ecx_x25519_derive_test();
826 failed |= ecx_x25519_raw_key_test();
827
828 return failed;
829}