xref: /openbsd-src/regress/lib/libcrypto/evp/evp_ecx_test.c (revision 2b0849fc840a184fe654e155c9803d984931052c)
1*2b0849fcStb /*	$OpenBSD: evp_ecx_test.c,v 1.5 2023/03/02 20:04:42 tb Exp $ */
29eee0738Sjsing /*
39eee0738Sjsing  * Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
49eee0738Sjsing  *
59eee0738Sjsing  * Permission to use, copy, modify, and distribute this software for any
69eee0738Sjsing  * purpose with or without fee is hereby granted, provided that the above
79eee0738Sjsing  * copyright notice and this permission notice appear in all copies.
89eee0738Sjsing  *
99eee0738Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
109eee0738Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
119eee0738Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
129eee0738Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
139eee0738Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
149eee0738Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
159eee0738Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
169eee0738Sjsing  */
179eee0738Sjsing 
189eee0738Sjsing #include <err.h>
199eee0738Sjsing #include <string.h>
209eee0738Sjsing 
219eee0738Sjsing #include <openssl/err.h>
229eee0738Sjsing #include <openssl/evp.h>
239eee0738Sjsing #include <openssl/pem.h>
249eee0738Sjsing 
259eee0738Sjsing #include "curve25519_internal.h"
269eee0738Sjsing 
27*2b0849fcStb static const uint8_t ed25519_priv_key_1[] =
289eee0738Sjsing     "-----BEGIN PRIVATE KEY-----\n"
299eee0738Sjsing     "MC4CAQAwBQYDK2VwBCIEIIkDg89yB70IpUXsAZieCcCDE2ig9nin9JJWpDQoCup8\n"
309eee0738Sjsing     "-----END PRIVATE KEY-----\n";
319eee0738Sjsing 
329eee0738Sjsing const uint8_t ed25519_raw_priv_key_1[] = {
339eee0738Sjsing 	0x89, 0x03, 0x83, 0xcf, 0x72, 0x07, 0xbd, 0x08,
349eee0738Sjsing 	0xa5, 0x45, 0xec, 0x01, 0x98, 0x9e, 0x09, 0xc0,
359eee0738Sjsing 	0x83, 0x13, 0x68, 0xa0, 0xf6, 0x78, 0xa7, 0xf4,
369eee0738Sjsing 	0x92, 0x56, 0xa4, 0x34, 0x28, 0x0a, 0xea, 0x7c,
379eee0738Sjsing };
389eee0738Sjsing 
39*2b0849fcStb static const uint8_t ed25519_pub_key_1[] =
409eee0738Sjsing     "-----BEGIN PUBLIC KEY-----\n"
419eee0738Sjsing     "MCowBQYDK2VwAyEA1vxPpbnoC7G8vFmRjYVXUU2aln3hUZEgfW1atlTHF/o=\n"
429eee0738Sjsing     "-----END PUBLIC KEY-----\n";
439eee0738Sjsing 
449eee0738Sjsing const uint8_t ed25519_raw_pub_key_1[] = {
459eee0738Sjsing 	0xd6, 0xfc, 0x4f, 0xa5, 0xb9, 0xe8, 0x0b, 0xb1,
469eee0738Sjsing 	0xbc, 0xbc, 0x59, 0x91, 0x8d, 0x85, 0x57, 0x51,
479eee0738Sjsing 	0x4d, 0x9a, 0x96, 0x7d, 0xe1, 0x51, 0x91, 0x20,
489eee0738Sjsing 	0x7d, 0x6d, 0x5a, 0xb6, 0x54, 0xc7, 0x17, 0xfa,
499eee0738Sjsing };
509eee0738Sjsing 
519eee0738Sjsing static const uint8_t message_1[] = {
529eee0738Sjsing 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
539eee0738Sjsing 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
549eee0738Sjsing 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
559eee0738Sjsing 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
569eee0738Sjsing };
579eee0738Sjsing 
589eee0738Sjsing static const uint8_t signature_1[] = {
599eee0738Sjsing 	0x1c, 0xba, 0x71, 0x5a, 0xbc, 0x7f, 0x3b, 0x6b,
609eee0738Sjsing 	0xc1, 0x61, 0x04, 0x02, 0xb6, 0x37, 0x9e, 0xe1,
619eee0738Sjsing 	0xa6, 0x7c, 0xfe, 0xcd, 0xdd, 0x68, 0x59, 0xb5,
629eee0738Sjsing 	0xc8, 0x09, 0xa5, 0x36, 0x66, 0xfb, 0xad, 0xc5,
639eee0738Sjsing 	0x68, 0x31, 0xd1, 0x7a, 0x48, 0x44, 0xaa, 0xa9,
649eee0738Sjsing 	0x9c, 0xf1, 0x1a, 0xbb, 0xd5, 0x49, 0xd5, 0xe8,
659eee0738Sjsing 	0x63, 0xe2, 0x94, 0x77, 0x16, 0x1a, 0x52, 0xfa,
669eee0738Sjsing 	0x33, 0x6b, 0xf3, 0x57, 0x93, 0xd4, 0xc1, 0x07,
679eee0738Sjsing };
689eee0738Sjsing 
69*2b0849fcStb static const uint8_t x25519_priv_key_1[] =
709eee0738Sjsing     "-----BEGIN PRIVATE KEY-----\n"
719eee0738Sjsing     "MC4CAQAwBQYDK2VuBCIEICi6rzFFJb02mi6sopELeshEi2vr68ul4bzEHPOz+K1o\n"
729eee0738Sjsing     "-----END PRIVATE KEY-----\n";
739eee0738Sjsing 
749eee0738Sjsing const uint8_t x25519_raw_priv_key_1[] = {
759eee0738Sjsing 	0x28, 0xba, 0xaf, 0x31, 0x45, 0x25, 0xbd, 0x36,
769eee0738Sjsing 	0x9a, 0x2e, 0xac, 0xa2, 0x91, 0x0b, 0x7a, 0xc8,
779eee0738Sjsing 	0x44, 0x8b, 0x6b, 0xeb, 0xeb, 0xcb, 0xa5, 0xe1,
789eee0738Sjsing 	0xbc, 0xc4, 0x1c, 0xf3, 0xb3, 0xf8, 0xad, 0x68,
799eee0738Sjsing };
809eee0738Sjsing 
81*2b0849fcStb static const uint8_t x25519_pub_key_1[] =
829eee0738Sjsing     "-----BEGIN PUBLIC KEY-----\n"
839eee0738Sjsing     "MCowBQYDK2VuAyEAu4WHXnAQL2YfonJhuoEO9PM2WwXjveApPmCXSiDnf1M=\n"
849eee0738Sjsing     "-----END PUBLIC KEY-----\n";
859eee0738Sjsing 
869eee0738Sjsing static const uint8_t x25519_raw_pub_key_1[] = {
879eee0738Sjsing 	0xbb, 0x85, 0x87, 0x5e, 0x70, 0x10, 0x2f, 0x66,
889eee0738Sjsing 	0x1f, 0xa2, 0x72, 0x61, 0xba, 0x81, 0x0e, 0xf4,
899eee0738Sjsing 	0xf3, 0x36, 0x5b, 0x05, 0xe3, 0xbd, 0xe0, 0x29,
909eee0738Sjsing 	0x3e, 0x60, 0x97, 0x4a, 0x20, 0xe7, 0x7f, 0x53,
919eee0738Sjsing };
929eee0738Sjsing 
93*2b0849fcStb static const uint8_t x25519_priv_key_2[] =
949eee0738Sjsing     "-----BEGIN PRIVATE KEY-----\n"
959eee0738Sjsing     "MC4CAQAwBQYDK2VuBCIEIAg9Jbp/Ma0TO4r179WGGiv+VnGxGNRh4VNrHUij7Ql/\n"
969eee0738Sjsing     "-----END PRIVATE KEY-----\n";
979eee0738Sjsing 
989eee0738Sjsing static const uint8_t x25519_raw_priv_key_2[] = {
999eee0738Sjsing 	0x08, 0x3d, 0x25, 0xba, 0x7f, 0x31, 0xad, 0x13,
1009eee0738Sjsing 	0x3b, 0x8a, 0xf5, 0xef, 0xd5, 0x86, 0x1a, 0x2b,
1019eee0738Sjsing 	0xfe, 0x56, 0x71, 0xb1, 0x18, 0xd4, 0x61, 0xe1,
1029eee0738Sjsing 	0x53, 0x6b, 0x1d, 0x48, 0xa3, 0xed, 0x09, 0x7f,
1039eee0738Sjsing };
1049eee0738Sjsing 
105*2b0849fcStb static const uint8_t x25519_pub_key_2[] =
1069eee0738Sjsing     "-----BEGIN PUBLIC KEY-----\n"
1079eee0738Sjsing     "MCowBQYDK2VuAyEABvksGQRgsUXEK5CaniVZ59pPvDoABgBSdAM+EF0Q9Cw=\n"
1089eee0738Sjsing     "-----END PUBLIC KEY-----\n";
1099eee0738Sjsing 
1109eee0738Sjsing static const uint8_t x25519_raw_pub_key_2[] = {
1119eee0738Sjsing 	0x06, 0xf9, 0x2c, 0x19, 0x04, 0x60, 0xb1, 0x45,
1129eee0738Sjsing 	0xc4, 0x2b, 0x90, 0x9a, 0x9e, 0x25, 0x59, 0xe7,
1139eee0738Sjsing 	0xda, 0x4f, 0xbc, 0x3a, 0x00, 0x06, 0x00, 0x52,
1149eee0738Sjsing 	0x74, 0x03, 0x3e, 0x10, 0x5d, 0x10, 0xf4, 0x2c,
1159eee0738Sjsing };
1169eee0738Sjsing 
1179eee0738Sjsing static const uint8_t shared_key_1[] = {
1189eee0738Sjsing 	0xa2, 0x61, 0xf5, 0x91, 0x2e, 0x82, 0xbc, 0x98,
1199eee0738Sjsing 	0x6c, 0x85, 0xb6, 0x51, 0x1f, 0x69, 0xdb, 0xfa,
1209eee0738Sjsing 	0x88, 0x6c, 0x4b, 0x9e, 0x3b, 0xb0, 0x71, 0xd1,
1219eee0738Sjsing 	0xf3, 0xea, 0x2a, 0xd0, 0xef, 0xf6, 0xa5, 0x5a,
1229eee0738Sjsing };
1239eee0738Sjsing 
1249eee0738Sjsing static void
hexdump(const unsigned char * buf,size_t len)1259eee0738Sjsing hexdump(const unsigned char *buf, size_t len)
1269eee0738Sjsing {
1279eee0738Sjsing 	size_t i;
1289eee0738Sjsing 
1299eee0738Sjsing 	for (i = 1; i <= len; i++)
1309eee0738Sjsing 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
1319eee0738Sjsing 
1329eee0738Sjsing 	fprintf(stderr, "\n");
1339eee0738Sjsing }
1349eee0738Sjsing 
1359eee0738Sjsing static int
ecx_ed25519_keygen_test(void)1369eee0738Sjsing ecx_ed25519_keygen_test(void)
1379eee0738Sjsing {
1389eee0738Sjsing 	EVP_PKEY_CTX *pkey_ctx = NULL;
1399eee0738Sjsing 	EVP_PKEY *pkey = NULL;
1409eee0738Sjsing 	BIO *bio = NULL;
1419eee0738Sjsing 	int failed = 1;
1429eee0738Sjsing 
1439eee0738Sjsing 	if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL)) == NULL) {
1449eee0738Sjsing 		fprintf(stderr, "FAIL: failed to create ED25519 context\n");
1459eee0738Sjsing 		goto failure;
1469eee0738Sjsing 	}
1479eee0738Sjsing 
1489eee0738Sjsing 	if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) {
1499eee0738Sjsing 		fprintf(stderr, "FAIL: failed to init keygen for ED25519\n");
1509eee0738Sjsing 		goto failure;
1519eee0738Sjsing 	}
1529eee0738Sjsing 	if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) {
1539eee0738Sjsing 		fprintf(stderr, "FAIL: failed to generate ED25519 key\n");
1549eee0738Sjsing 		goto failure;
1559eee0738Sjsing 	}
1569eee0738Sjsing 
1579eee0738Sjsing 	if ((bio = BIO_new(BIO_s_mem())) == NULL)
1589eee0738Sjsing 		goto failure;
1599eee0738Sjsing 	if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
1609eee0738Sjsing 		fprintf(stderr, "FAIL: failed to write ED25519 to PEM\n");
1619eee0738Sjsing 		goto failure;
1629eee0738Sjsing 	}
1639eee0738Sjsing 
1649eee0738Sjsing 	failed = 0;
1659eee0738Sjsing 
1669eee0738Sjsing  failure:
1679eee0738Sjsing 	BIO_free(bio);
1689eee0738Sjsing 	EVP_PKEY_CTX_free(pkey_ctx);
1699eee0738Sjsing 	EVP_PKEY_free(pkey);
1709eee0738Sjsing 
1719eee0738Sjsing 	return failed;
1729eee0738Sjsing }
1739eee0738Sjsing 
1749eee0738Sjsing static int
ecx_ed25519_raw_key_test(void)1759eee0738Sjsing ecx_ed25519_raw_key_test(void)
1769eee0738Sjsing {
1779eee0738Sjsing 	EVP_PKEY *pkey = NULL;
1789eee0738Sjsing 	uint8_t *priv_key = NULL;
1799eee0738Sjsing 	size_t priv_key_len = 0;
1809eee0738Sjsing 	uint8_t *pub_key = NULL;
1819eee0738Sjsing 	size_t pub_key_len = 0;
1829eee0738Sjsing 	const uint8_t *pp;
1839eee0738Sjsing 	BIO *bio = NULL;
1849eee0738Sjsing 	int failed = 1;
1859eee0738Sjsing 
1869eee0738Sjsing 	/*
1879eee0738Sjsing 	 * Decode private key from PEM and check raw private and raw public.
1889eee0738Sjsing 	 */
1899eee0738Sjsing 
1909eee0738Sjsing 	if ((bio = BIO_new_mem_buf(ed25519_priv_key_1, -1)) == NULL)
1919eee0738Sjsing 		errx(1, "failed to create BIO for key");
1929eee0738Sjsing 	if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) {
1939eee0738Sjsing 		fprintf(stderr, "FAIL: failed to read private key\n");
1949eee0738Sjsing 		ERR_print_errors_fp(stderr);
1959eee0738Sjsing 		goto failure;
1969eee0738Sjsing 	}
1979eee0738Sjsing 
1989eee0738Sjsing 	if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) {
1999eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw private key len\n");
2009eee0738Sjsing 		goto failure;
2019eee0738Sjsing 	}
2029eee0738Sjsing 	if (priv_key_len != sizeof(ed25519_raw_priv_key_1)) {
2039eee0738Sjsing 		fprintf(stderr, "FAIL: raw private key length differs "
2049eee0738Sjsing 		    "(%zu != %zu)\n", priv_key_len,
2059eee0738Sjsing 		    sizeof(ed25519_raw_priv_key_1));
2069eee0738Sjsing 		goto failure;
2079eee0738Sjsing 	}
2089eee0738Sjsing 	if ((priv_key = malloc(priv_key_len)) == NULL)
2099eee0738Sjsing 		errx(1, "failed to malloc priv key");
2109eee0738Sjsing 	if (!EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) {
2119eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw private key len\n");
2129eee0738Sjsing 		goto failure;
2139eee0738Sjsing 	}
2149eee0738Sjsing 	if (memcmp(priv_key, ed25519_raw_priv_key_1, priv_key_len) != 0) {
2159eee0738Sjsing 		fprintf(stderr, "FAIL: get raw private key failed\n");
2169eee0738Sjsing 		fprintf(stderr, "Got:\n");
2179eee0738Sjsing 		hexdump(priv_key, priv_key_len);
2189eee0738Sjsing 		fprintf(stderr, "Want:\n");
2199eee0738Sjsing 		hexdump(ed25519_raw_priv_key_1, sizeof(ed25519_raw_priv_key_1));
2209eee0738Sjsing 		goto failure;
2219eee0738Sjsing 	}
2229eee0738Sjsing 
2239eee0738Sjsing 	if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) {
2249eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw pub key len\n");
2259eee0738Sjsing 		goto failure;
2269eee0738Sjsing 	}
2279eee0738Sjsing 	if (pub_key_len != sizeof(ed25519_raw_pub_key_1)) {
2289eee0738Sjsing 		fprintf(stderr, "FAIL: raw public key length differs "
2299eee0738Sjsing 		    "(%zu != %zu)\n", pub_key_len,
2309eee0738Sjsing 		    sizeof(ed25519_raw_pub_key_1));
2319eee0738Sjsing 		goto failure;
2329eee0738Sjsing 	}
2339eee0738Sjsing 	if ((pub_key = malloc(pub_key_len)) == NULL)
2349eee0738Sjsing 		errx(1, "failed to malloc private key");
2359eee0738Sjsing 	if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) {
2369eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw pub key len\n");
2379eee0738Sjsing 		goto failure;
2389eee0738Sjsing 	}
2399eee0738Sjsing 	if (memcmp(pub_key, ed25519_raw_pub_key_1, pub_key_len) != 0) {
2409eee0738Sjsing 		fprintf(stderr, "FAIL: get raw public key failed\n");
2419eee0738Sjsing 		fprintf(stderr, "Got:\n");
2429eee0738Sjsing 		hexdump(pub_key, pub_key_len);
2439eee0738Sjsing 		fprintf(stderr, "Want:\n");
2449eee0738Sjsing 		hexdump(ed25519_raw_pub_key_1, sizeof(ed25519_raw_pub_key_1));
2459eee0738Sjsing 		goto failure;
2469eee0738Sjsing 	}
2479eee0738Sjsing 
2489eee0738Sjsing 	BIO_free(bio);
2499eee0738Sjsing 	bio = NULL;
2509eee0738Sjsing 
2519eee0738Sjsing 	EVP_PKEY_free(pkey);
2529eee0738Sjsing 	pkey = NULL;
2539eee0738Sjsing 
2549eee0738Sjsing 	freezero(priv_key, priv_key_len);
2559eee0738Sjsing 	priv_key = NULL;
2569eee0738Sjsing 	priv_key_len = 0;
2579eee0738Sjsing 
2589eee0738Sjsing 	freezero(pub_key, pub_key_len);
2599eee0738Sjsing 	pub_key = NULL;
2609eee0738Sjsing 	pub_key_len = 0;
2619eee0738Sjsing 
2629eee0738Sjsing 	/*
2639eee0738Sjsing 	 * Decode public key from PEM and check raw private and raw public.
2649eee0738Sjsing 	 */
2659eee0738Sjsing 
2669eee0738Sjsing 	if ((bio = BIO_new_mem_buf(ed25519_pub_key_1, -1)) == NULL)
2679eee0738Sjsing 		errx(1, "failed to create BIO for key");
2689eee0738Sjsing 	if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
2699eee0738Sjsing 		fprintf(stderr, "FAIL: failed to read public key\n");
2709eee0738Sjsing 		ERR_print_errors_fp(stderr);
2719eee0738Sjsing 		goto failure;
2729eee0738Sjsing 	}
2739eee0738Sjsing 
2749eee0738Sjsing 	/*
2759eee0738Sjsing 	 * Yet another astounding API design - we cannot tell if the private key
2769eee0738Sjsing 	 * is not present, or if some other failure occurred.
2779eee0738Sjsing 	 */
2789eee0738Sjsing 	if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) {
2799eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw priv key len\n");
2809eee0738Sjsing 		goto failure;
2819eee0738Sjsing 	}
2829eee0738Sjsing 	if ((priv_key = malloc(priv_key_len)) == NULL)
2839eee0738Sjsing 		errx(1, "failed to malloc priv key");
2849eee0738Sjsing 	if (EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) {
2859eee0738Sjsing 		fprintf(stderr, "FAIL: got raw private key, should fail\n");
2869eee0738Sjsing 		goto failure;
2879eee0738Sjsing 	}
2889eee0738Sjsing 
2899eee0738Sjsing 	if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) {
2909eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw pub key len\n");
2919eee0738Sjsing 		goto failure;
2929eee0738Sjsing 	}
2939eee0738Sjsing 	if (pub_key_len != sizeof(ed25519_raw_pub_key_1)) {
2949eee0738Sjsing 		fprintf(stderr, "FAIL: raw public key length differs "
2959eee0738Sjsing 		    "(%zu != %zu)\n", pub_key_len,
2969eee0738Sjsing 		    sizeof(ed25519_raw_pub_key_1));
2979eee0738Sjsing 		goto failure;
2989eee0738Sjsing 	}
2999eee0738Sjsing 	if ((pub_key = malloc(pub_key_len)) == NULL)
3009eee0738Sjsing 		errx(1, "failed to malloc private key");
3019eee0738Sjsing 	if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) {
3029eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw pub key len\n");
3039eee0738Sjsing 		goto failure;
3049eee0738Sjsing 	}
3059eee0738Sjsing 	if (memcmp(pub_key, ed25519_raw_pub_key_1, pub_key_len) != 0) {
3069eee0738Sjsing 		fprintf(stderr, "FAIL: get raw public key failed\n");
3079eee0738Sjsing 		fprintf(stderr, "Got:\n");
3089eee0738Sjsing 		hexdump(pub_key, pub_key_len);
3099eee0738Sjsing 		fprintf(stderr, "Want:\n");
3109eee0738Sjsing 		hexdump(ed25519_raw_pub_key_1, sizeof(ed25519_raw_pub_key_1));
3119eee0738Sjsing 		goto failure;
3129eee0738Sjsing 	}
3139eee0738Sjsing 
3149eee0738Sjsing 	BIO_free(bio);
3159eee0738Sjsing 	bio = NULL;
3169eee0738Sjsing 
3179eee0738Sjsing 	EVP_PKEY_free(pkey);
3189eee0738Sjsing 	pkey = NULL;
3199eee0738Sjsing 
3209eee0738Sjsing 	/*
3219eee0738Sjsing 	 * Create PKEY from raw private, check PEM encoded private and public.
3229eee0738Sjsing 	 */
3239eee0738Sjsing 	if ((pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
3249eee0738Sjsing 	    ed25519_raw_priv_key_1, sizeof(ed25519_raw_priv_key_1))) == NULL) {
3259eee0738Sjsing 		fprintf(stderr, "FAIL: PKEY from raw private key failed");
3269eee0738Sjsing 		goto failure;
3279eee0738Sjsing 	}
3289eee0738Sjsing 	if ((bio = BIO_new(BIO_s_mem())) == NULL)
3299eee0738Sjsing 		goto failure;
3309eee0738Sjsing 	if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
3319eee0738Sjsing 		fprintf(stderr, "FAIL: failed to write ED25519 private to PEM\n");
3329eee0738Sjsing 		goto failure;
3339eee0738Sjsing 	}
3349eee0738Sjsing 	BIO_get_mem_data(bio, &pp);
3359eee0738Sjsing 	if (strcmp(ed25519_priv_key_1, pp) != 0) {
3369eee0738Sjsing 		fprintf(stderr, "FAIL: resulting private key PEM differs\n");
3379eee0738Sjsing 		goto failure;
3389eee0738Sjsing 	}
3399eee0738Sjsing 
340b507a39dStb 	(void)BIO_reset(bio);
3419eee0738Sjsing 	if (!PEM_write_bio_PUBKEY(bio, pkey)) {
3429eee0738Sjsing 		fprintf(stderr, "FAIL: failed to write ED25519 public to PEM\n");
3439eee0738Sjsing 		goto failure;
3449eee0738Sjsing 	}
3459eee0738Sjsing 	BIO_get_mem_data(bio, &pp);
3469eee0738Sjsing 	if (strcmp(ed25519_pub_key_1, pp) != 0) {
3479eee0738Sjsing 		fprintf(stderr, "FAIL: resulting public key PEM differs\n");
3489eee0738Sjsing 		fprintf(stderr, "%s\n", ed25519_pub_key_1);
3499eee0738Sjsing 		fprintf(stderr, "%s\n", pp);
3509eee0738Sjsing 		//goto failure;
3519eee0738Sjsing 	}
3529eee0738Sjsing 
3539eee0738Sjsing 	EVP_PKEY_free(pkey);
3549eee0738Sjsing 	pkey = NULL;
3559eee0738Sjsing 
3569eee0738Sjsing 	/*
3579eee0738Sjsing 	 * Create PKEY from raw public, check public key PEM.
3589eee0738Sjsing 	 */
3599eee0738Sjsing 	if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
3609eee0738Sjsing 	    ed25519_raw_pub_key_1, sizeof(ed25519_raw_pub_key_1))) == NULL) {
3619eee0738Sjsing 		fprintf(stderr, "FAIL: PKEY from raw public key failed");
3629eee0738Sjsing 		goto failure;
3639eee0738Sjsing 	}
364b507a39dStb 	(void)BIO_reset(bio);
3659eee0738Sjsing 	if (!PEM_write_bio_PUBKEY(bio, pkey)) {
3669eee0738Sjsing 		fprintf(stderr, "FAIL: failed to write ED25519 public to PEM\n");
3679eee0738Sjsing 		goto failure;
3689eee0738Sjsing 	}
3699eee0738Sjsing 	BIO_get_mem_data(bio, &pp);
3709eee0738Sjsing 	if (strcmp(ed25519_pub_key_1, pp) != 0) {
3719eee0738Sjsing 		fprintf(stderr, "FAIL: resulting public key PEM differs\n");
3729eee0738Sjsing 		goto failure;
3739eee0738Sjsing 	}
3749eee0738Sjsing 
3759eee0738Sjsing 	failed = 0;
3769eee0738Sjsing 
3779eee0738Sjsing  failure:
3789eee0738Sjsing 	BIO_free(bio);
3799eee0738Sjsing 	EVP_PKEY_free(pkey);
3809eee0738Sjsing 	freezero(priv_key, priv_key_len);
3819eee0738Sjsing 	freezero(pub_key, pub_key_len);
3829eee0738Sjsing 
3839eee0738Sjsing 	return failed;
3849eee0738Sjsing }
3859eee0738Sjsing 
3869eee0738Sjsing static int
ecx_ed25519_sign_test(void)3879eee0738Sjsing ecx_ed25519_sign_test(void)
3889eee0738Sjsing {
3899eee0738Sjsing 	EVP_MD_CTX *md_ctx = NULL;
3909eee0738Sjsing 	EVP_PKEY *pkey = NULL;
3919eee0738Sjsing 	uint8_t *signature = NULL;
3929eee0738Sjsing 	size_t signature_len = 0;
3939eee0738Sjsing 	BIO *bio = NULL;
3949eee0738Sjsing 	int failed = 1;
3959eee0738Sjsing 
3969eee0738Sjsing 	if ((bio = BIO_new_mem_buf(ed25519_priv_key_1, -1)) == NULL)
3979eee0738Sjsing 		errx(1, "failed to create BIO for key");
3989eee0738Sjsing 	if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) {
3999eee0738Sjsing 		fprintf(stderr, "FAIL: failed to read private key\n");
4009eee0738Sjsing 		ERR_print_errors_fp(stderr);
4019eee0738Sjsing 		goto failure;
4029eee0738Sjsing 	}
4039eee0738Sjsing 
4049eee0738Sjsing 	if ((md_ctx = EVP_MD_CTX_new()) == NULL)
4059eee0738Sjsing 		errx(1, "failed to create MD_CTX");
4069eee0738Sjsing 
4079eee0738Sjsing 	if (!EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, pkey)) {
4089eee0738Sjsing 		fprintf(stderr, "FAIL: failed to init digest sign\n");
4099eee0738Sjsing 		ERR_print_errors_fp(stderr);
4109eee0738Sjsing 		goto failure;
4119eee0738Sjsing 	}
4129eee0738Sjsing 	if (!EVP_DigestSign(md_ctx, NULL, &signature_len, NULL, 0)) {
4139eee0738Sjsing 		fprintf(stderr, "FAIL: failed to digest sign update\n");
4149eee0738Sjsing 		goto failure;
4159eee0738Sjsing 	}
4169eee0738Sjsing 	if ((signature = calloc(1, signature_len)) == NULL)
4179eee0738Sjsing 		errx(1, "failed to allocate signature");
4189eee0738Sjsing 	if (!EVP_DigestSign(md_ctx, signature, &signature_len, message_1,
4199eee0738Sjsing 	    sizeof(message_1))) {
4209eee0738Sjsing 		fprintf(stderr, "FAIL: failed to digest sign update\n");
4219eee0738Sjsing 		goto failure;
4229eee0738Sjsing 	}
4239eee0738Sjsing 
4249eee0738Sjsing 	if (signature_len != sizeof(signature_1)) {
4259eee0738Sjsing 		fprintf(stderr, "FAIL: signature length differs (%zu != %zu)\n",
4269eee0738Sjsing 		    signature_len, sizeof(signature_1));
4279eee0738Sjsing 		goto failure;
4289eee0738Sjsing 	}
4299eee0738Sjsing 
4309eee0738Sjsing 	if (memcmp(signature, signature_1, signature_len) != 0) {
4319eee0738Sjsing 		fprintf(stderr, "FAIL: Ed25519 sign failed\n");
4329eee0738Sjsing 		fprintf(stderr, "Got:\n");
4339eee0738Sjsing 		hexdump(signature, signature_len);
4349eee0738Sjsing 		fprintf(stderr, "Want:\n");
4359eee0738Sjsing 		hexdump(signature_1, sizeof(signature_1));
4369eee0738Sjsing 		goto failure;
4379eee0738Sjsing 	}
4389eee0738Sjsing 
4399eee0738Sjsing 	failed = 0;
4409eee0738Sjsing 
4419eee0738Sjsing  failure:
4429eee0738Sjsing 	BIO_free(bio);
4433409f3adStb 	EVP_MD_CTX_free(md_ctx);
4449eee0738Sjsing 	EVP_PKEY_free(pkey);
4459eee0738Sjsing 	free(signature);
4469eee0738Sjsing 
4479eee0738Sjsing 	return failed;
4489eee0738Sjsing }
4499eee0738Sjsing 
4509eee0738Sjsing static int
ecx_ed25519_verify_test(void)4519eee0738Sjsing ecx_ed25519_verify_test(void)
4529eee0738Sjsing {
4539eee0738Sjsing 	EVP_MD_CTX *md_ctx = NULL;
4549eee0738Sjsing 	EVP_PKEY *pkey = NULL;
4559eee0738Sjsing 	BIO *bio = NULL;
4569eee0738Sjsing 	int failed = 1;
4579eee0738Sjsing 
4589eee0738Sjsing 	if ((bio = BIO_new_mem_buf(ed25519_pub_key_1, -1)) == NULL)
4599eee0738Sjsing 		errx(1, "failed to create BIO for key");
4609eee0738Sjsing 	if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
4619eee0738Sjsing 		fprintf(stderr, "FAIL: failed to read public key\n");
4629eee0738Sjsing 		ERR_print_errors_fp(stderr);
4639eee0738Sjsing 		goto failure;
4649eee0738Sjsing 	}
4659eee0738Sjsing 
4669eee0738Sjsing 	if ((md_ctx = EVP_MD_CTX_new()) == NULL)
4679eee0738Sjsing 		errx(1, "failed to create MD_CTX");
4689eee0738Sjsing 
4699eee0738Sjsing 	if (!EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, pkey)) {
4709eee0738Sjsing 		fprintf(stderr, "FAIL: failed to init digest verify\n");
4719eee0738Sjsing 		ERR_print_errors_fp(stderr);
4729eee0738Sjsing 		goto failure;
4739eee0738Sjsing 	}
4749eee0738Sjsing 	if (!EVP_DigestVerify(md_ctx, signature_1, sizeof(signature_1),
4759eee0738Sjsing 	    message_1, sizeof(message_1))) {
4769eee0738Sjsing 		fprintf(stderr, "FAIL: failed to digest verify update\n");
4779eee0738Sjsing 		goto failure;
4789eee0738Sjsing 	}
4799eee0738Sjsing 
4809eee0738Sjsing 	failed = 0;
4819eee0738Sjsing 
4829eee0738Sjsing  failure:
4839eee0738Sjsing 	BIO_free(bio);
4843409f3adStb 	EVP_MD_CTX_free(md_ctx);
4859eee0738Sjsing 	EVP_PKEY_free(pkey);
4869eee0738Sjsing 
4879eee0738Sjsing 	return failed;
4889eee0738Sjsing }
4899eee0738Sjsing 
4909eee0738Sjsing static int
ecx_x25519_keygen_test(void)4919eee0738Sjsing ecx_x25519_keygen_test(void)
4929eee0738Sjsing {
4939eee0738Sjsing 	EVP_PKEY_CTX *pkey_ctx = NULL;
4949eee0738Sjsing 	EVP_PKEY *pkey = NULL;
4959eee0738Sjsing 	BIO *bio = NULL;
4969eee0738Sjsing 	int failed = 1;
4979eee0738Sjsing 
4989eee0738Sjsing 	if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL)) == NULL) {
4999eee0738Sjsing 		fprintf(stderr, "FAIL: failed to create X25519 context\n");
5009eee0738Sjsing 		goto failure;
5019eee0738Sjsing 	}
5029eee0738Sjsing 
5039eee0738Sjsing 	if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) {
5049eee0738Sjsing 		fprintf(stderr, "FAIL: failed to init keygen for X25519\n");
5059eee0738Sjsing 		goto failure;
5069eee0738Sjsing 	}
5079eee0738Sjsing 	if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) {
5089eee0738Sjsing 		fprintf(stderr, "FAIL: failed to generate X25519 key\n");
5099eee0738Sjsing 		goto failure;
5109eee0738Sjsing 	}
5119eee0738Sjsing 
5129eee0738Sjsing 	if ((bio = BIO_new(BIO_s_mem())) == NULL)
5139eee0738Sjsing 		goto failure;
5149eee0738Sjsing 	if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
5159eee0738Sjsing 		fprintf(stderr, "FAIL: failed to write X25519 to PEM\n");
5169eee0738Sjsing 		goto failure;
5179eee0738Sjsing 	}
5189eee0738Sjsing 
5199eee0738Sjsing 	failed = 0;
5209eee0738Sjsing 
5219eee0738Sjsing  failure:
5229eee0738Sjsing 	BIO_free(bio);
5239eee0738Sjsing 	EVP_PKEY_CTX_free(pkey_ctx);
5249eee0738Sjsing 	EVP_PKEY_free(pkey);
5259eee0738Sjsing 
5269eee0738Sjsing 	return failed;
5279eee0738Sjsing }
5289eee0738Sjsing 
5299eee0738Sjsing static int
ecx_x25519_derive_test(void)5309eee0738Sjsing ecx_x25519_derive_test(void)
5319eee0738Sjsing {
5329eee0738Sjsing 	EVP_PKEY_CTX *pkey_ctx = NULL;
5339eee0738Sjsing 	EVP_PKEY *pkey = NULL, *pkey_peer = NULL;
5349eee0738Sjsing 	uint8_t *shared_key = NULL;
5359eee0738Sjsing 	size_t shared_key_len = 0;
5369eee0738Sjsing 	BIO *bio = NULL;
5379eee0738Sjsing 	int failed = 1;
5389eee0738Sjsing 
5399eee0738Sjsing 	if ((bio = BIO_new_mem_buf(x25519_priv_key_1, -1)) == NULL)
5409eee0738Sjsing 		errx(1, "failed to create BIO for key");
5419eee0738Sjsing 	if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) {
5429eee0738Sjsing 		fprintf(stderr, "FAIL: failed to read private key\n");
5439eee0738Sjsing 		ERR_print_errors_fp(stderr);
5449eee0738Sjsing 		goto failure;
5459eee0738Sjsing 	}
5469eee0738Sjsing 
5479eee0738Sjsing 	BIO_free(bio);
5489eee0738Sjsing 	if ((bio = BIO_new_mem_buf(x25519_pub_key_2, -1)) == NULL)
5499eee0738Sjsing 		errx(1, "failed to create BIO for key");
5509eee0738Sjsing 	if ((pkey_peer = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
5519eee0738Sjsing 		fprintf(stderr, "FAIL: failed to read peer public key\n");
5529eee0738Sjsing 		ERR_print_errors_fp(stderr);
5539eee0738Sjsing 		goto failure;
5549eee0738Sjsing 	}
5559eee0738Sjsing 
5569eee0738Sjsing 	if ((pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) {
5579eee0738Sjsing 		fprintf(stderr, "FAIL: failed to create X25519 context\n");
5589eee0738Sjsing 		goto failure;
5599eee0738Sjsing 	}
5609eee0738Sjsing 	if (EVP_PKEY_derive_init(pkey_ctx) <= 0) {
5619eee0738Sjsing 		fprintf(stderr, "FAIL: failed to init derive for X25519\n");
5629eee0738Sjsing 		goto failure;
5639eee0738Sjsing 	}
5649eee0738Sjsing 	if (EVP_PKEY_derive_set_peer(pkey_ctx, pkey_peer) <= 0) {
5659eee0738Sjsing 		fprintf(stderr, "FAIL: failed to set peer key for X25519\n");
5669eee0738Sjsing 		goto failure;
5679eee0738Sjsing 	}
5689eee0738Sjsing 	if (EVP_PKEY_derive(pkey_ctx, NULL, &shared_key_len) <= 0) {
5699eee0738Sjsing 		fprintf(stderr, "FAIL: failed to derive X25519 key length\n");
5709eee0738Sjsing 		goto failure;
5719eee0738Sjsing 	}
5729eee0738Sjsing 	if ((shared_key = malloc(shared_key_len)) == NULL)
5739eee0738Sjsing 		errx(1, "failed to malloc shared key");
5749eee0738Sjsing 	if (EVP_PKEY_derive(pkey_ctx, shared_key, &shared_key_len) <= 0) {
5759eee0738Sjsing 		fprintf(stderr, "FAIL: failed to derive X25519 key\n");
5769eee0738Sjsing 		goto failure;
5779eee0738Sjsing 	}
5789eee0738Sjsing 
5799eee0738Sjsing 	if (shared_key_len != sizeof(shared_key_1)) {
5809eee0738Sjsing 		fprintf(stderr, "FAIL: shared key length differs (%zu != %zu)\n",
5819eee0738Sjsing 		    shared_key_len, sizeof(shared_key_1));
5829eee0738Sjsing 		goto failure;
5839eee0738Sjsing 	}
5849eee0738Sjsing 
5859eee0738Sjsing 	if (memcmp(shared_key, shared_key_1, shared_key_len) != 0) {
5869eee0738Sjsing 		fprintf(stderr, "FAIL: X25519 derive failed\n");
5879eee0738Sjsing 		fprintf(stderr, "Got:\n");
5889eee0738Sjsing 		hexdump(shared_key, shared_key_len);
5899eee0738Sjsing 		fprintf(stderr, "Want:\n");
5909eee0738Sjsing 		hexdump(shared_key_1, sizeof(shared_key_1));
5919eee0738Sjsing 		goto failure;
5929eee0738Sjsing 	}
5939eee0738Sjsing 
5949eee0738Sjsing 	failed = 0;
5959eee0738Sjsing 
5969eee0738Sjsing  failure:
5979eee0738Sjsing 	BIO_free(bio);
5989eee0738Sjsing 	EVP_PKEY_CTX_free(pkey_ctx);
5999eee0738Sjsing 	EVP_PKEY_free(pkey_peer);
6009eee0738Sjsing 	EVP_PKEY_free(pkey);
6019eee0738Sjsing 	freezero(shared_key, shared_key_len);
6029eee0738Sjsing 
6039eee0738Sjsing 	return failed;
6049eee0738Sjsing }
6059eee0738Sjsing 
6069eee0738Sjsing static int
ecx_x25519_raw_key_test(void)6079eee0738Sjsing ecx_x25519_raw_key_test(void)
6089eee0738Sjsing {
6099eee0738Sjsing 	EVP_PKEY *pkey = NULL;
6109eee0738Sjsing 	uint8_t *priv_key = NULL;
6119eee0738Sjsing 	size_t priv_key_len = 0;
6129eee0738Sjsing 	uint8_t *pub_key = NULL;
6139eee0738Sjsing 	size_t pub_key_len = 0;
6149eee0738Sjsing 	const uint8_t *pp;
6159eee0738Sjsing 	BIO *bio = NULL;
6169eee0738Sjsing 	int failed = 1;
6179eee0738Sjsing 
6189eee0738Sjsing 	/*
6199eee0738Sjsing 	 * Decode private key from PEM and check raw private and raw public.
6209eee0738Sjsing 	 */
6219eee0738Sjsing 
6229eee0738Sjsing 	if ((bio = BIO_new_mem_buf(x25519_priv_key_2, -1)) == NULL)
6239eee0738Sjsing 		errx(1, "failed to create BIO for key");
6249eee0738Sjsing 	if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) {
6259eee0738Sjsing 		fprintf(stderr, "FAIL: failed to read private key\n");
6269eee0738Sjsing 		ERR_print_errors_fp(stderr);
6279eee0738Sjsing 		goto failure;
6289eee0738Sjsing 	}
6299eee0738Sjsing 
6309eee0738Sjsing 	if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) {
6319eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw private key len\n");
6329eee0738Sjsing 		goto failure;
6339eee0738Sjsing 	}
6349eee0738Sjsing 	if (priv_key_len != sizeof(x25519_raw_priv_key_2)) {
6359eee0738Sjsing 		fprintf(stderr, "FAIL: raw private key length differs "
6369eee0738Sjsing 		    "(%zu != %zu)\n", priv_key_len,
6379eee0738Sjsing 		    sizeof(x25519_raw_priv_key_2));
6389eee0738Sjsing 		goto failure;
6399eee0738Sjsing 	}
6409eee0738Sjsing 	if ((priv_key = malloc(priv_key_len)) == NULL)
6419eee0738Sjsing 		errx(1, "failed to malloc priv key");
6429eee0738Sjsing 	if (!EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) {
6439eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw private key len\n");
6449eee0738Sjsing 		goto failure;
6459eee0738Sjsing 	}
6469eee0738Sjsing 	if (memcmp(priv_key, x25519_raw_priv_key_2, priv_key_len) != 0) {
6479eee0738Sjsing 		fprintf(stderr, "FAIL: get raw private key failed\n");
6489eee0738Sjsing 		fprintf(stderr, "Got:\n");
6499eee0738Sjsing 		hexdump(priv_key, priv_key_len);
6509eee0738Sjsing 		fprintf(stderr, "Want:\n");
6519eee0738Sjsing 		hexdump(x25519_raw_priv_key_2, sizeof(x25519_raw_priv_key_2));
6529eee0738Sjsing 		goto failure;
6539eee0738Sjsing 	}
6549eee0738Sjsing 
6559eee0738Sjsing 	if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) {
6569eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw pub key len\n");
6579eee0738Sjsing 		goto failure;
6589eee0738Sjsing 	}
6599eee0738Sjsing 	if (pub_key_len != sizeof(x25519_raw_pub_key_2)) {
6609eee0738Sjsing 		fprintf(stderr, "FAIL: raw public key length differs "
6619eee0738Sjsing 		    "(%zu != %zu)\n", pub_key_len,
6629eee0738Sjsing 		    sizeof(x25519_raw_pub_key_2));
6639eee0738Sjsing 		goto failure;
6649eee0738Sjsing 	}
6659eee0738Sjsing 	if ((pub_key = malloc(pub_key_len)) == NULL)
6669eee0738Sjsing 		errx(1, "failed to malloc private key");
6679eee0738Sjsing 	if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) {
6689eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw pub key len\n");
6699eee0738Sjsing 		goto failure;
6709eee0738Sjsing 	}
6719eee0738Sjsing 	if (memcmp(pub_key, x25519_raw_pub_key_2, pub_key_len) != 0) {
6729eee0738Sjsing 		fprintf(stderr, "FAIL: get raw public key failed\n");
6739eee0738Sjsing 		fprintf(stderr, "Got:\n");
6749eee0738Sjsing 		hexdump(pub_key, pub_key_len);
6759eee0738Sjsing 		fprintf(stderr, "Want:\n");
6769eee0738Sjsing 		hexdump(x25519_raw_pub_key_2, sizeof(x25519_raw_pub_key_2));
6779eee0738Sjsing 		goto failure;
6789eee0738Sjsing 	}
6799eee0738Sjsing 
6809eee0738Sjsing 	BIO_free(bio);
6819eee0738Sjsing 	bio = NULL;
6829eee0738Sjsing 
6839eee0738Sjsing 	EVP_PKEY_free(pkey);
6849eee0738Sjsing 	pkey = NULL;
6859eee0738Sjsing 
6869eee0738Sjsing 	freezero(priv_key, priv_key_len);
6879eee0738Sjsing 	priv_key = NULL;
6889eee0738Sjsing 	priv_key_len = 0;
6899eee0738Sjsing 
6909eee0738Sjsing 	freezero(pub_key, pub_key_len);
6919eee0738Sjsing 	pub_key = NULL;
6929eee0738Sjsing 	pub_key_len = 0;
6939eee0738Sjsing 
6949eee0738Sjsing 	/*
6959eee0738Sjsing 	 * Decode public key from PEM and check raw private and raw public.
6969eee0738Sjsing 	 */
6979eee0738Sjsing 
6989eee0738Sjsing 	if ((bio = BIO_new_mem_buf(x25519_pub_key_1, -1)) == NULL)
6999eee0738Sjsing 		errx(1, "failed to create BIO for key");
7009eee0738Sjsing 	if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
7019eee0738Sjsing 		fprintf(stderr, "FAIL: failed to read public key\n");
7029eee0738Sjsing 		ERR_print_errors_fp(stderr);
7039eee0738Sjsing 		goto failure;
7049eee0738Sjsing 	}
7059eee0738Sjsing 
7069eee0738Sjsing 	/*
7079eee0738Sjsing 	 * Yet another astounding API design - we cannot tell if the private key
7089eee0738Sjsing 	 * is not present, or if some other failure occurred.
7099eee0738Sjsing 	 */
7109eee0738Sjsing 	if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) {
7119eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw priv key len\n");
7129eee0738Sjsing 		goto failure;
7139eee0738Sjsing 	}
7149eee0738Sjsing 	if ((priv_key = malloc(priv_key_len)) == NULL)
7159eee0738Sjsing 		errx(1, "failed to malloc priv key");
7169eee0738Sjsing 	if (EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) {
7179eee0738Sjsing 		fprintf(stderr, "FAIL: got raw private key, should fail\n");
7189eee0738Sjsing 		goto failure;
7199eee0738Sjsing 	}
7209eee0738Sjsing 
7219eee0738Sjsing 	if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) {
7229eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw pub key len\n");
7239eee0738Sjsing 		goto failure;
7249eee0738Sjsing 	}
7259eee0738Sjsing 	if (pub_key_len != sizeof(x25519_raw_pub_key_1)) {
7269eee0738Sjsing 		fprintf(stderr, "FAIL: raw public key length differs "
7279eee0738Sjsing 		    "(%zu != %zu)\n", pub_key_len,
728b17a0400Stb 		    sizeof(x25519_raw_pub_key_1));
7299eee0738Sjsing 		goto failure;
7309eee0738Sjsing 	}
7319eee0738Sjsing 	if ((pub_key = malloc(pub_key_len)) == NULL)
7329eee0738Sjsing 		errx(1, "failed to malloc private key");
7339eee0738Sjsing 	if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) {
7349eee0738Sjsing 		fprintf(stderr, "FAIL: failed to get raw pub key len\n");
7359eee0738Sjsing 		goto failure;
7369eee0738Sjsing 	}
7379eee0738Sjsing 	if (memcmp(pub_key, x25519_raw_pub_key_1, pub_key_len) != 0) {
7389eee0738Sjsing 		fprintf(stderr, "FAIL: get raw public key failed\n");
7399eee0738Sjsing 		fprintf(stderr, "Got:\n");
7409eee0738Sjsing 		hexdump(pub_key, pub_key_len);
7419eee0738Sjsing 		fprintf(stderr, "Want:\n");
742b17a0400Stb 		hexdump(x25519_raw_pub_key_1, sizeof(x25519_raw_pub_key_1));
7439eee0738Sjsing 		goto failure;
7449eee0738Sjsing 	}
7459eee0738Sjsing 
7469eee0738Sjsing 	BIO_free(bio);
7479eee0738Sjsing 	bio = NULL;
7489eee0738Sjsing 
7499eee0738Sjsing 	EVP_PKEY_free(pkey);
7509eee0738Sjsing 	pkey = NULL;
7519eee0738Sjsing 
7529eee0738Sjsing 	/*
7539eee0738Sjsing 	 * Create PKEY from raw private, check PEM encoded private and public.
7549eee0738Sjsing 	 */
7559eee0738Sjsing 	if ((pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
7569eee0738Sjsing 	    x25519_raw_priv_key_2, sizeof(x25519_raw_priv_key_2))) == NULL) {
7579eee0738Sjsing 		fprintf(stderr, "FAIL: PKEY from raw private key failed");
7589eee0738Sjsing 		goto failure;
7599eee0738Sjsing 	}
7609eee0738Sjsing 	if ((bio = BIO_new(BIO_s_mem())) == NULL)
7619eee0738Sjsing 		goto failure;
7629eee0738Sjsing 	if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
7639eee0738Sjsing 		fprintf(stderr, "FAIL: failed to write X25519 private to PEM\n");
7649eee0738Sjsing 		goto failure;
7659eee0738Sjsing 	}
7669eee0738Sjsing 	BIO_get_mem_data(bio, &pp);
7679eee0738Sjsing 	if (strcmp(x25519_priv_key_2, pp) != 0) {
7689eee0738Sjsing 		fprintf(stderr, "FAIL: resulting private key PEM differs\n");
7699eee0738Sjsing 		goto failure;
7709eee0738Sjsing 	}
7719eee0738Sjsing 
772b507a39dStb 	(void)BIO_reset(bio);
7739eee0738Sjsing 	if (!PEM_write_bio_PUBKEY(bio, pkey)) {
7749eee0738Sjsing 		fprintf(stderr, "FAIL: failed to write X25519 public to PEM\n");
7759eee0738Sjsing 		goto failure;
7769eee0738Sjsing 	}
7779eee0738Sjsing 	BIO_get_mem_data(bio, &pp);
7789eee0738Sjsing 	if (strcmp(x25519_pub_key_2, pp) != 0) {
7799eee0738Sjsing 		fprintf(stderr, "FAIL: resulting public key PEM differs\n");
7809eee0738Sjsing 		goto failure;
7819eee0738Sjsing 	}
7829eee0738Sjsing 
7839eee0738Sjsing 	EVP_PKEY_free(pkey);
7849eee0738Sjsing 	pkey = NULL;
7859eee0738Sjsing 
7869eee0738Sjsing 	/*
7879eee0738Sjsing 	 * Create PKEY from raw public, check public key PEM.
7889eee0738Sjsing 	 */
7899eee0738Sjsing 	if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
7909eee0738Sjsing 	    x25519_raw_pub_key_1, sizeof(x25519_raw_pub_key_1))) == NULL) {
7919eee0738Sjsing 		fprintf(stderr, "FAIL: PKEY from raw public key failed");
7929eee0738Sjsing 		goto failure;
7939eee0738Sjsing 	}
794b507a39dStb 	(void)BIO_reset(bio);
7959eee0738Sjsing 	if (!PEM_write_bio_PUBKEY(bio, pkey)) {
7969eee0738Sjsing 		fprintf(stderr, "FAIL: failed to write X25519 public to PEM\n");
7979eee0738Sjsing 		goto failure;
7989eee0738Sjsing 	}
7999eee0738Sjsing 	BIO_get_mem_data(bio, &pp);
8009eee0738Sjsing 	if (strcmp(x25519_pub_key_1, pp) != 0) {
8019eee0738Sjsing 		fprintf(stderr, "FAIL: resulting public key PEM differs\n");
8029eee0738Sjsing 		goto failure;
8039eee0738Sjsing 	}
8049eee0738Sjsing 
8059eee0738Sjsing 	failed = 0;
8069eee0738Sjsing 
8079eee0738Sjsing  failure:
8089eee0738Sjsing 	BIO_free(bio);
8099eee0738Sjsing 	EVP_PKEY_free(pkey);
8109eee0738Sjsing 	freezero(priv_key, priv_key_len);
8119eee0738Sjsing 	freezero(pub_key, pub_key_len);
8129eee0738Sjsing 
8139eee0738Sjsing 	return failed;
8149eee0738Sjsing }
8159eee0738Sjsing 
8169eee0738Sjsing int
main(int argc,char ** argv)8179eee0738Sjsing main(int argc, char **argv)
8189eee0738Sjsing {
8199eee0738Sjsing 	int failed = 0;
8209eee0738Sjsing 
8219eee0738Sjsing 	failed |= ecx_ed25519_raw_key_test();
8229eee0738Sjsing 	failed |= ecx_ed25519_keygen_test();
8239eee0738Sjsing 	failed |= ecx_ed25519_sign_test();
8249eee0738Sjsing 	failed |= ecx_ed25519_verify_test();
8259eee0738Sjsing 
8269eee0738Sjsing 	failed |= ecx_x25519_keygen_test();
8279eee0738Sjsing 	failed |= ecx_x25519_derive_test();
8289eee0738Sjsing 	failed |= ecx_x25519_raw_key_test();
8299eee0738Sjsing 
8309eee0738Sjsing 	return failed;
8319eee0738Sjsing }
832