xref: /freebsd/contrib/libfido2/regress/eddsa.c (revision 60a517b66a69b8c011b04063ef63a938738719bd)
12ccfa855SEd Maste /*
22ccfa855SEd Maste  * Copyright (c) 2022 Yubico AB. All rights reserved.
32ccfa855SEd Maste  * Use of this source code is governed by a BSD-style
42ccfa855SEd Maste  * license that can be found in the LICENSE file.
52ccfa855SEd Maste  * SPDX-License-Identifier: BSD-2-Clause
62ccfa855SEd Maste  */
72ccfa855SEd Maste 
82ccfa855SEd Maste #undef NDEBUG
92ccfa855SEd Maste 
102ccfa855SEd Maste #include <assert.h>
112ccfa855SEd Maste #include <string.h>
122ccfa855SEd Maste 
132ccfa855SEd Maste #define _FIDO_INTERNAL
142ccfa855SEd Maste 
152ccfa855SEd Maste #include <fido.h>
162ccfa855SEd Maste #include <fido/eddsa.h>
172ccfa855SEd Maste 
182ccfa855SEd Maste #include <openssl/bio.h>
192ccfa855SEd Maste #include <openssl/pem.h>
202ccfa855SEd Maste 
212ccfa855SEd Maste #define ASSERT_NOT_NULL(e)	assert((e) != NULL)
222ccfa855SEd Maste #define ASSERT_NULL(e)		assert((e) == NULL)
232ccfa855SEd Maste #define ASSERT_INVAL(e)		assert((e) == FIDO_ERR_INVALID_ARGUMENT)
242ccfa855SEd Maste #define ASSERT_OK(e)		assert((e) == FIDO_OK)
252ccfa855SEd Maste 
262ccfa855SEd Maste static const char ecdsa[] = \
272ccfa855SEd Maste "-----BEGIN PUBLIC KEY-----\n"
282ccfa855SEd Maste "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOwiq14c80b7C1Jzsx5w1zMvk2GgW\n"
292ccfa855SEd Maste "5kfGMOKXjwF/U+51ZfBDKehs3ivdeXAJBkxIh7E3iA32s+HyNqk+ntl9fg==\n"
302ccfa855SEd Maste "-----END PUBLIC KEY-----\n";
312ccfa855SEd Maste 
322ccfa855SEd Maste static const char eddsa[] = \
332ccfa855SEd Maste "-----BEGIN PUBLIC KEY-----\n"
342ccfa855SEd Maste "MCowBQYDK2VwAyEADt/RHErAxAHxH9FUmsjOhQ2ALl6Y8nE0m3zQxkEE2iM=\n"
352ccfa855SEd Maste "-----END PUBLIC KEY-----\n";
362ccfa855SEd Maste 
372ccfa855SEd Maste static const unsigned char eddsa_raw[] = {
382ccfa855SEd Maste 	0x0e, 0xdf, 0xd1, 0x1c, 0x4a, 0xc0, 0xc4, 0x01,
392ccfa855SEd Maste 	0xf1, 0x1f, 0xd1, 0x54, 0x9a, 0xc8, 0xce, 0x85,
402ccfa855SEd Maste 	0x0d, 0x80, 0x2e, 0x5e, 0x98, 0xf2, 0x71, 0x34,
412ccfa855SEd Maste 	0x9b, 0x7c, 0xd0, 0xc6, 0x41, 0x04, 0xda, 0x23,
422ccfa855SEd Maste };
432ccfa855SEd Maste 
442ccfa855SEd Maste static EVP_PKEY *
452ccfa855SEd Maste EVP_PKEY_from_PEM(const char *ptr, size_t len)
462ccfa855SEd Maste {
472ccfa855SEd Maste 	BIO *bio = NULL;
482ccfa855SEd Maste 	EVP_PKEY *pkey = NULL;
492ccfa855SEd Maste 
502ccfa855SEd Maste 	if ((bio = BIO_new(BIO_s_mem())) == NULL) {
512ccfa855SEd Maste 		warnx("BIO_new");
522ccfa855SEd Maste 		goto out;
532ccfa855SEd Maste 	}
542ccfa855SEd Maste 	if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) {
552ccfa855SEd Maste 		warnx("BIO_write");
562ccfa855SEd Maste 		goto out;
572ccfa855SEd Maste 	}
582ccfa855SEd Maste 	if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL)
592ccfa855SEd Maste 		warnx("PEM_read_bio_PUBKEY");
602ccfa855SEd Maste out:
612ccfa855SEd Maste 	BIO_free(bio);
622ccfa855SEd Maste 
632ccfa855SEd Maste 	return pkey;
642ccfa855SEd Maste }
652ccfa855SEd Maste 
662ccfa855SEd Maste static int
672ccfa855SEd Maste eddsa_pk_cmp(const char *ptr, size_t len)
682ccfa855SEd Maste {
692ccfa855SEd Maste 	EVP_PKEY *pkA = NULL;
702ccfa855SEd Maste 	EVP_PKEY *pkB = NULL;
712ccfa855SEd Maste 	eddsa_pk_t *k = NULL;
722ccfa855SEd Maste 	int r, ok = -1;
732ccfa855SEd Maste 
742ccfa855SEd Maste 	if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) {
752ccfa855SEd Maste 		warnx("EVP_PKEY_from_PEM");
762ccfa855SEd Maste 		goto out;
772ccfa855SEd Maste 	}
782ccfa855SEd Maste 	if ((k = eddsa_pk_new()) == NULL) {
792ccfa855SEd Maste 		warnx("eddsa_pk_new");
802ccfa855SEd Maste 		goto out;
812ccfa855SEd Maste 	}
822ccfa855SEd Maste 	if ((r = eddsa_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) {
832ccfa855SEd Maste 		warnx("eddsa_pk_from_EVP_PKEY: 0x%x", r);
842ccfa855SEd Maste 		goto out;
852ccfa855SEd Maste 	}
862ccfa855SEd Maste 	if ((pkB = eddsa_pk_to_EVP_PKEY(k)) == NULL) {
872ccfa855SEd Maste 		warnx("eddsa_pk_to_EVP_PKEY");
882ccfa855SEd Maste 		goto out;
892ccfa855SEd Maste 	}
902ccfa855SEd Maste 	if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) {
912ccfa855SEd Maste 		warnx("EVP_PKEY_cmp: %d", r);
922ccfa855SEd Maste 		goto out;
932ccfa855SEd Maste 	}
942ccfa855SEd Maste 
952ccfa855SEd Maste 	ok = 0;
962ccfa855SEd Maste out:
972ccfa855SEd Maste 	EVP_PKEY_free(pkA);
982ccfa855SEd Maste 	EVP_PKEY_free(pkB);
992ccfa855SEd Maste 	eddsa_pk_free(&k);
1002ccfa855SEd Maste 
1012ccfa855SEd Maste 	return ok;
1022ccfa855SEd Maste }
1032ccfa855SEd Maste 
1042ccfa855SEd Maste static void
1052ccfa855SEd Maste invalid_key(void)
1062ccfa855SEd Maste {
1072ccfa855SEd Maste 	EVP_PKEY *pkey;
1082ccfa855SEd Maste 	eddsa_pk_t *pk;
1092ccfa855SEd Maste 
1102ccfa855SEd Maste 	ASSERT_NOT_NULL((pkey = EVP_PKEY_from_PEM(ecdsa, sizeof(ecdsa))));
1112ccfa855SEd Maste 	ASSERT_NOT_NULL((pk = eddsa_pk_new()));
1122ccfa855SEd Maste 	ASSERT_INVAL(eddsa_pk_from_EVP_PKEY(pk, pkey));
1132ccfa855SEd Maste 
1142ccfa855SEd Maste 	EVP_PKEY_free(pkey);
1152ccfa855SEd Maste 	eddsa_pk_free(&pk);
1162ccfa855SEd Maste }
1172ccfa855SEd Maste 
1182ccfa855SEd Maste static void
1192ccfa855SEd Maste valid_key(void)
1202ccfa855SEd Maste {
1212ccfa855SEd Maste 	EVP_PKEY *pkeyA = NULL;
1222ccfa855SEd Maste 	EVP_PKEY *pkeyB = NULL;
1232ccfa855SEd Maste 	eddsa_pk_t *pkA = NULL;
1242ccfa855SEd Maste 	eddsa_pk_t *pkB = NULL;
1252ccfa855SEd Maste 
126*60a517b6SEd Maste #if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3070000f
1272ccfa855SEd Maste 	/* incomplete support; test what we can */
1282ccfa855SEd Maste 	ASSERT_NULL(EVP_PKEY_from_PEM(eddsa, sizeof(eddsa)));
1292ccfa855SEd Maste 	ASSERT_NOT_NULL((pkB = eddsa_pk_new()));
1302ccfa855SEd Maste 	ASSERT_INVAL(eddsa_pk_from_ptr(pkB, eddsa_raw, sizeof(eddsa_raw)));
1312ccfa855SEd Maste 	ASSERT_NULL(eddsa_pk_to_EVP_PKEY((const eddsa_pk_t *)eddsa_raw));
1322ccfa855SEd Maste 	assert(eddsa_pk_cmp(eddsa, sizeof(eddsa)) < 0);
1332ccfa855SEd Maste #else
1342ccfa855SEd Maste 	ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(eddsa, sizeof(eddsa))));
1352ccfa855SEd Maste 	ASSERT_NOT_NULL((pkA = eddsa_pk_new()));
1362ccfa855SEd Maste 	ASSERT_NOT_NULL((pkB = eddsa_pk_new()));
1372ccfa855SEd Maste 	ASSERT_OK(eddsa_pk_from_EVP_PKEY(pkA, pkeyA));
1382ccfa855SEd Maste 	ASSERT_OK(eddsa_pk_from_ptr(pkB, eddsa_raw, sizeof(eddsa_raw)));
1392ccfa855SEd Maste 	ASSERT_NOT_NULL((pkeyB = eddsa_pk_to_EVP_PKEY((const eddsa_pk_t *)eddsa_raw)));
1402ccfa855SEd Maste 	assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1);
1412ccfa855SEd Maste 	assert(eddsa_pk_cmp(eddsa, sizeof(eddsa)) == 0);
1422ccfa855SEd Maste #endif
1432ccfa855SEd Maste 
1442ccfa855SEd Maste 	EVP_PKEY_free(pkeyA);
1452ccfa855SEd Maste 	EVP_PKEY_free(pkeyB);
1462ccfa855SEd Maste 	eddsa_pk_free(&pkA);
1472ccfa855SEd Maste 	eddsa_pk_free(&pkB);
1482ccfa855SEd Maste }
1492ccfa855SEd Maste 
1502ccfa855SEd Maste int
1512ccfa855SEd Maste main(void)
1522ccfa855SEd Maste {
1532ccfa855SEd Maste 	fido_init(0);
1542ccfa855SEd Maste 
1552ccfa855SEd Maste 	invalid_key();
1562ccfa855SEd Maste 	valid_key();
1572ccfa855SEd Maste 
1582ccfa855SEd Maste 	exit(0);
1592ccfa855SEd Maste }
160