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