commit: 01f543064ebecd8f70ce0437df48debad2dbd354
parent 3fe24c73976047fe76b74b32fca2e6c1d35eac4c
Author: Michael Forney <mforney@mforney.org>
Date: Tue, 14 Apr 2020 20:16:00 -0700
libfido2: Port to BearSSL
Diffstat:
3 files changed, 1800 insertions(+), 3 deletions(-)
diff --git a/pkg/libfido2/gen.lua b/pkg/libfido2/gen.lua
@@ -3,8 +3,8 @@ cflags{
'-include $outdir/config.h',
'-D _DEFAULT_SOURCE',
'-D _FIDO_INTERNAL',
+ '-I $builddir/pkg/bearssl/include',
'-I $builddir/pkg/libcbor/include',
- '-I $builddir/pkg/libressl/include',
'-I $builddir/pkg/linux-headers/include',
'-I $srcdir/src',
'-I $basedir/pkg/openbsd/include',
@@ -18,8 +18,8 @@ pkg.hdrs = copy('$outdir/include', '$srcdir/src', {
})
pkg.deps = {
'$outdir/config.h',
+ 'pkg/bearssl/headers',
'pkg/libcbor/headers',
- 'pkg/libressl/headers',
'pkg/linux-headers/headers',
}
@@ -56,6 +56,7 @@ lib('libfido2.a', [[
hid_linux.c
)
+ $builddir/pkg/bearssl/libbearssl.a
$builddir/pkg/libcbor/libcbor.a
]])
diff --git a/pkg/libfido2/patch/0008-port-to-BearSSL.patch b/pkg/libfido2/patch/0008-port-to-BearSSL.patch
@@ -0,0 +1,1796 @@
+From 4f9ada2c0e453adf51c66afe11ce29cf5e41000f Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Mon, 18 Nov 2019 23:46:22 -0800
+Subject: [PATCH] port to BearSSL
+
+---
+ CMakeLists.txt | 32 +++---
+ src/CMakeLists.txt | 4 +-
+ src/aes256.c | 61 +++++------
+ src/assert.c | 135 +++++++++----------------
+ src/cbor.c | 98 +++++++-----------
+ src/cred.c | 94 ++++++++---------
+ src/credman.c | 16 +--
+ src/ecdh.c | 55 ++++------
+ src/eddsa.c | 84 ---------------
+ src/es256.c | 247 +++++++--------------------------------------
+ src/fido.h | 3 -
+ src/fido/eddsa.h | 22 ----
+ src/fido/es256.h | 5 -
+ src/fido/rs256.h | 4 -
+ src/rs256.c | 117 +--------------------
+ src/u2f.c | 109 ++++++++++----------
+ 16 files changed, 286 insertions(+), 800 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 402220e..bdabd3a 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -52,13 +52,13 @@ endif()
+
+ if(MSVC)
+ if((NOT CBOR_INCLUDE_DIRS) OR (NOT CBOR_LIBRARY_DIRS) OR
+- (NOT CRYPTO_INCLUDE_DIRS) OR (NOT CRYPTO_LIBRARY_DIRS))
++ (NOT BEARSSL_INCLUDE_DIRS) OR (NOT BEARSSL_LIBRARY_DIRS))
+ message(FATAL_ERROR "please provide definitions for "
+- "{CBOR,CRYPTO}_{INCLUDE,LIBRARY}_DIRS when building "
++ "{CBOR,BEARSSL}_{INCLUDE,LIBRARY}_DIRS when building "
+ "under msvc")
+ endif()
+ set(CBOR_LIBRARIES cbor)
+- set(CRYPTO_LIBRARIES crypto-45)
++ set(BEARSSL_LIBRARIES bearssl)
+ set(MSVC_DISABLED_WARNINGS_LIST
+ "C4200" # nonstandard extension used: zero-sized array in
+ # struct/union;
+@@ -79,15 +79,19 @@ if(MSVC)
+ else()
+ include(FindPkgConfig)
+ pkg_search_module(CBOR libcbor)
+- pkg_search_module(CRYPTO libcrypto REQUIRED)
++ find_library(BEARSSL_LIBRARIES bearssl)
++ find_path(BEARSSL_INCLUDE_DIRS bearssl.h)
++ if(NOT BEARSSL_LIBRARIES OR NOT BEARSSL_INCLUDE_DIRS)
++ message(FATAL_ERROR "could not find BearSSL")
++ endif()
+
+ # XXX workaround libcbor's missing .pc file
+ if(NOT CBOR_FOUND)
+- check_include_files(cbor.h HAVE_CBOR_H)
+- if(NOT HAVE_CBOR_H)
+- message(FATAL_ERROR "could not find cbor header files")
++ find_library(CBOR_LIBRARIES cbor)
++ find_path(CBOR_INCLUDE_DIRS cbor.h)
++ if(NOT CBOR_LIBRARIES OR NOT CBOR_INCLUDE_DIRS)
++ message(FATAL_ERROR "could not find libcbor")
+ endif()
+- set(CBOR_LIBRARIES "cbor")
+ endif()
+
+ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+@@ -325,10 +329,9 @@ endif()
+
+ include_directories(${CMAKE_SOURCE_DIR}/src)
+ include_directories(${CBOR_INCLUDE_DIRS})
+-include_directories(${CRYPTO_INCLUDE_DIRS})
++include_directories(${BEARSSL_INCLUDE_DIRS})
+
+ link_directories(${CBOR_LIBRARY_DIRS})
+-link_directories(${CRYPTO_LIBRARY_DIRS})
+
+ message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
+ message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}")
+@@ -338,9 +341,8 @@ message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
+ message(STATUS "CBOR_INCLUDE_DIRS: ${CBOR_INCLUDE_DIRS}")
+ message(STATUS "CBOR_LIBRARY_DIRS: ${CBOR_LIBRARY_DIRS}")
+ message(STATUS "CBOR_LIBRARIES: ${CBOR_LIBRARIES}")
+-message(STATUS "CRYPTO_INCLUDE_DIRS: ${CRYPTO_INCLUDE_DIRS}")
+-message(STATUS "CRYPTO_LIBRARY_DIRS: ${CRYPTO_LIBRARY_DIRS}")
+-message(STATUS "CRYPTO_LIBRARIES: ${CRYPTO_LIBRARIES}")
++message(STATUS "BEARSSL_INCLUDE_DIRS: ${BEARSSL_INCLUDE_DIRS}")
++message(STATUS "BEARSSL_LIBRARIES: ${BEARSSL_LIBRARIES}")
+ message(STATUS "BASE_LIBRARIES: ${BASE_LIBRARIES}")
+ message(STATUS "VERSION: ${FIDO_VERSION}")
+ message(STATUS "LIB_VERSION: ${LIB_VERSION}")
+@@ -361,8 +363,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ endif()
+
+ subdirs(src)
+-subdirs(examples)
+-subdirs(tools)
++#subdirs(examples)
++#subdirs(tools)
+ subdirs(man)
+
+ if(NOT WIN32)
+diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
+index 926e7f2..69ab5e0 100644
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -55,7 +55,7 @@ list(APPEND COMPAT_SOURCES
+
+ # static library
+ add_library(fido2 STATIC ${FIDO_SOURCES} ${COMPAT_SOURCES})
+-target_link_libraries(fido2 ${CBOR_LIBRARIES} ${CRYPTO_LIBRARIES}
++target_link_libraries(fido2 ${CBOR_LIBRARIES} ${BEARSSL_LIBRARIES}
+ ${UDEV_LIBRARIES} ${BASE_LIBRARIES})
+ if(WIN32)
+ if (MINGW)
+@@ -73,7 +73,7 @@ install(TARGETS fido2 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+
+ # dynamic library
+ add_library(fido2_shared SHARED ${FIDO_SOURCES} ${COMPAT_SOURCES})
+-target_link_libraries(fido2_shared ${CBOR_LIBRARIES} ${CRYPTO_LIBRARIES}
++target_link_libraries(fido2_shared ${CBOR_LIBRARIES} ${BEARSSL_LIBRARIES}
+ ${UDEV_LIBRARIES} ${BASE_LIBRARIES})
+ if(WIN32)
+ if (MINGW)
+diff --git a/src/aes256.c b/src/aes256.c
+index 767cdb2..baacc0a 100644
+--- a/src/aes256.c
++++ b/src/aes256.c
+@@ -4,7 +4,8 @@
+ * license that can be found in the LICENSE file.
+ */
+
+-#include <openssl/evp.h>
++#include <bearssl.h>
++
+ #include <string.h>
+
+ #include "fido.h"
+@@ -12,38 +13,33 @@
+ int
+ aes256_cbc_enc(const fido_blob_t *key, const fido_blob_t *in, fido_blob_t *out)
+ {
+- EVP_CIPHER_CTX *ctx = NULL;
+- unsigned char iv[32];
+- int len;
+- int ok = -1;
++ br_aes_ct64_cbcenc_keys ctx;
++ unsigned char iv[32];
++ int ok = -1;
+
+ memset(iv, 0, sizeof(iv));
+ out->ptr = NULL;
+ out->len = 0;
+
+ /* sanity check */
+- if (in->len > INT_MAX || (in->len % 16) != 0 ||
+- (out->ptr = calloc(1, in->len)) == NULL) {
++ if ((in->len % 16) != 0 || (out->ptr = calloc(1, in->len)) == NULL) {
+ fido_log_debug("%s: in->len=%zu", __func__, in->len);
+ goto fail;
+ }
+-
+- if ((ctx = EVP_CIPHER_CTX_new()) == NULL || key->len != 32 ||
+- !EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key->ptr, iv) ||
+- !EVP_CIPHER_CTX_set_padding(ctx, 0) ||
+- !EVP_EncryptUpdate(ctx, out->ptr, &len, in->ptr, (int)in->len) ||
+- len < 0 || (size_t)len != in->len) {
+- fido_log_debug("%s: EVP_Encrypt", __func__);
++ if (key->len != 32) {
++ fido_log_debug("%s: key->len=%zu", __func__, key->len);
+ goto fail;
+ }
+
+- out->len = (size_t)len;
++ memcpy(out->ptr, in->ptr, in->len);
++ br_aes_ct64_cbcenc_init(&ctx, key->ptr, key->len);
++ br_aes_ct64_cbcenc_run(&ctx, iv, out->ptr, out->len);
++ explicit_bzero(&ctx, sizeof(ctx));
++
++ out->len = in->len;
+
+ ok = 0;
+ fail:
+- if (ctx != NULL)
+- EVP_CIPHER_CTX_free(ctx);
+-
+ if (ok < 0) {
+ free(out->ptr);
+ out->ptr = NULL;
+@@ -56,38 +52,33 @@ fail:
+ int
+ aes256_cbc_dec(const fido_blob_t *key, const fido_blob_t *in, fido_blob_t *out)
+ {
+- EVP_CIPHER_CTX *ctx = NULL;
+- unsigned char iv[32];
+- int len;
+- int ok = -1;
++ br_aes_ct64_cbcdec_keys ctx;
++ unsigned char iv[32];
++ int ok = -1;
+
+ memset(iv, 0, sizeof(iv));
+ out->ptr = NULL;
+ out->len = 0;
+
+ /* sanity check */
+- if (in->len > INT_MAX || (in->len % 16) != 0 ||
+- (out->ptr = calloc(1, in->len)) == NULL) {
++ if ((in->len % 16) != 0 || (out->ptr = calloc(1, in->len)) == NULL) {
+ fido_log_debug("%s: in->len=%zu", __func__, in->len);
+ goto fail;
+ }
+-
+- if ((ctx = EVP_CIPHER_CTX_new()) == NULL || key->len != 32 ||
+- !EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key->ptr, iv) ||
+- !EVP_CIPHER_CTX_set_padding(ctx, 0) ||
+- !EVP_DecryptUpdate(ctx, out->ptr, &len, in->ptr, (int)in->len) ||
+- len < 0 || (size_t)len > in->len + 32) {
+- fido_log_debug("%s: EVP_Decrypt", __func__);
++ if (key->len != 32) {
++ fido_log_debug("%s: key->len=%zu", __func__, key->len);
+ goto fail;
+ }
+
+- out->len = (size_t)len;
++ memcpy(out->ptr, in->ptr, in->len);
++ br_aes_ct64_cbcdec_init(&ctx, key->ptr, key->len);
++ br_aes_ct64_cbcdec_run(&ctx, iv, out->ptr, out->len);
++ explicit_bzero(&ctx, sizeof(ctx));
++
++ out->len = in->len;
+
+ ok = 0;
+ fail:
+- if (ctx != NULL)
+- EVP_CIPHER_CTX_free(ctx);
+-
+ if (ok < 0) {
+ free(out->ptr);
+ out->ptr = NULL;
+diff --git a/src/assert.c b/src/assert.c
+index a21b308..fd60037 100644
+--- a/src/assert.c
++++ b/src/assert.c
+@@ -4,10 +4,7 @@
+ * license that can be found in the LICENSE file.
+ */
+
+-#include <openssl/ec.h>
+-#include <openssl/ecdsa.h>
+-#include <openssl/evp.h>
+-#include <openssl/sha.h>
++#include <bearssl.h>
+
+ #include <string.h>
+ #include "fido.h"
+@@ -371,7 +368,7 @@ get_signed_hash(int cose_alg, fido_blob_t *dgst, const fido_blob_t *clientdata,
+ unsigned char *authdata_ptr = NULL;
+ size_t authdata_len;
+ struct cbor_load_result cbor;
+- SHA256_CTX ctx;
++ br_sha256_context ctx;
+ int ok = -1;
+
+ if ((item = cbor_load(authdata_cbor->ptr, authdata_cbor->len,
+@@ -385,14 +382,15 @@ get_signed_hash(int cose_alg, fido_blob_t *dgst, const fido_blob_t *clientdata,
+ authdata_len = cbor_bytestring_length(item);
+
+ if (cose_alg != COSE_EDDSA) {
+- if (dgst->len < SHA256_DIGEST_LENGTH || SHA256_Init(&ctx) == 0 ||
+- SHA256_Update(&ctx, authdata_ptr, authdata_len) == 0 ||
+- SHA256_Update(&ctx, clientdata->ptr, clientdata->len) == 0 ||
+- SHA256_Final(dgst->ptr, &ctx) == 0) {
++ if (dgst->len < br_sha256_SIZE) {
+ fido_log_debug("%s: sha256", __func__);
+ goto fail;
+ }
+- dgst->len = SHA256_DIGEST_LENGTH;
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, authdata_ptr, authdata_len);
++ br_sha256_update(&ctx, clientdata->ptr, clientdata->len);
++ br_sha256_out(&ctx, dgst->ptr);
++ dgst->len = br_sha256_SIZE;
+ } else {
+ if (SIZE_MAX - authdata_len < clientdata->len ||
+ dgst->len < authdata_len + clientdata->len) {
+@@ -417,34 +415,25 @@ int
+ fido_verify_sig_es256(const fido_blob_t *dgst, const es256_pk_t *pk,
+ const fido_blob_t *sig)
+ {
+- EVP_PKEY *pkey = NULL;
+- EC_KEY *ec = NULL;
+- int ok = -1;
+-
+- /* ECDSA_verify needs ints */
+- if (dgst->len > INT_MAX || sig->len > INT_MAX) {
+- fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__,
+- dgst->len, sig->len);
+- return (-1);
+- }
++ unsigned char q[BR_EC_KBUF_PUB_MAX_SIZE];
++ br_ec_public_key pkey;
++ int ok = -1;
+
+- if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL ||
+- (ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) {
+- fido_log_debug("%s: pk -> ec", __func__);
+- goto fail;
+- }
++ /* BearSSL needs uncompressed format */
++ q[0] = 4;
++ memcpy(q + 1, pk->x, 32);
++ memcpy(q + 1 + 32, pk->y, 32);
++ pkey.q = q;
++ pkey.qlen = 1 + 32 + 32;
+
+- if (ECDSA_verify(0, dgst->ptr, (int)dgst->len, sig->ptr,
+- (int)sig->len, ec) != 1) {
+- fido_log_debug("%s: ECDSA_verify", __func__);
++ if (br_ecdsa_vrfy_asn1_get_default()(br_ec_get_default(), dgst->ptr,
++ dgst->len, &pkey, sig->ptr, sig->len) == 0) {
++ fido_log_debug("%s: ECDSA verify", __func__);
+ goto fail;
+ }
+
+ ok = 0;
+ fail:
+- if (pkey != NULL)
+- EVP_PKEY_free(pkey);
+-
+ return (ok);
+ }
+
+@@ -452,34 +441,37 @@ int
+ fido_verify_sig_rs256(const fido_blob_t *dgst, const rs256_pk_t *pk,
+ const fido_blob_t *sig)
+ {
+- EVP_PKEY *pkey = NULL;
+- RSA *rsa = NULL;
+- int ok = -1;
+-
+- /* RSA_verify needs unsigned ints */
+- if (dgst->len > UINT_MAX || sig->len > UINT_MAX) {
+- fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__,
+- dgst->len, sig->len);
++ br_rsa_public_key pkey;
++ unsigned char hash[br_sha256_SIZE];
++ int ok = -1;
++
++ /* RSA verify needs SHA256-sized hash */
++ if (dgst->len != br_sha256_SIZE) {
++ fido_log_debug("%s: dgst->len=%zu", __func__, dgst->len);
+ return (-1);
+ }
+
+- if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL ||
+- (rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) {
+- fido_log_debug("%s: pk -> ec", __func__);
+- goto fail;
+- }
++#ifdef __GNUC__
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wcast-qual"
++#endif
++ pkey.n = (unsigned char *)pk->n;
++ pkey.nlen = sizeof(pk->n);
++ pkey.e = (unsigned char *)pk->e;
++ pkey.elen = sizeof(pk->e);
++#ifdef __GNUC__
++#pragma GCC diagnostic pop
++#endif
+
+- if (RSA_verify(NID_sha256, dgst->ptr, (unsigned int)dgst->len, sig->ptr,
+- (unsigned int)sig->len, rsa) != 1) {
++ if (br_rsa_pkcs1_vrfy_get_default()(sig->ptr, sig->len,
++ BR_HASH_OID_SHA256, dgst->len, &pkey, hash) != 1 ||
++ memcmp(dgst->ptr, hash, sizeof(hash)) != 0) {
+ fido_log_debug("%s: RSA_verify", __func__);
+ goto fail;
+ }
+
+ ok = 0;
+ fail:
+- if (pkey != NULL)
+- EVP_PKEY_free(pkey);
+-
+ return (ok);
+ }
+
+@@ -487,47 +479,12 @@ int
+ fido_verify_sig_eddsa(const fido_blob_t *dgst, const eddsa_pk_t *pk,
+ const fido_blob_t *sig)
+ {
+- EVP_PKEY *pkey = NULL;
+- EVP_MD_CTX *mdctx = NULL;
+- int ok = -1;
+-
+- /* EVP_DigestVerify needs ints */
+- if (dgst->len > INT_MAX || sig->len > INT_MAX) {
+- fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__,
+- dgst->len, sig->len);
+- return (-1);
+- }
++ (void)dgst;
++ (void)pk;
++ (void)sig;
+
+- if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) {
+- fido_log_debug("%s: pk -> pkey", __func__);
+- goto fail;
+- }
+-
+- if ((mdctx = EVP_MD_CTX_new()) == NULL) {
+- fido_log_debug("%s: EVP_MD_CTX_new", __func__);
+- goto fail;
+- }
+-
+- if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey) != 1) {
+- fido_log_debug("%s: EVP_DigestVerifyInit", __func__);
+- goto fail;
+- }
+-
+- if (EVP_DigestVerify(mdctx, sig->ptr, sig->len, dgst->ptr,
+- dgst->len) != 1) {
+- fido_log_debug("%s: EVP_DigestVerify", __func__);
+- goto fail;
+- }
+-
+- ok = 0;
+-fail:
+- if (mdctx != NULL)
+- EVP_MD_CTX_free(mdctx);
+-
+- if (pkey != NULL)
+- EVP_PKEY_free(pkey);
+-
+- return (ok);
++ fido_log_debug("%s: EdDSA not implemented", __func__);
++ return (-1);
+ }
+
+ int
+diff --git a/src/cbor.c b/src/cbor.c
+index e60e5e3..22d2f8a 100644
+--- a/src/cbor.c
++++ b/src/cbor.c
+@@ -4,9 +4,7 @@
+ * license that can be found in the LICENSE file.
+ */
+
+-#include <openssl/evp.h>
+-#include <openssl/hmac.h>
+-#include <openssl/sha.h>
++#include <bearssl.h>
+
+ #include <string.h>
+ #include "fido.h"
+@@ -590,14 +588,16 @@ cbor_encode_assert_options(fido_opt_t up, fido_opt_t uv)
+ cbor_item_t *
+ cbor_encode_pin_auth(const fido_blob_t *hmac_key, const fido_blob_t *data)
+ {
+- const EVP_MD *md = NULL;
+- unsigned char dgst[SHA256_DIGEST_LENGTH];
+- unsigned int dgst_len;
++ br_hmac_context ctx;
++ br_hmac_key_context kc;
++ unsigned char dgst[br_sha256_SIZE];
+
+- if ((md = EVP_sha256()) == NULL || HMAC(md, hmac_key->ptr,
+- (int)hmac_key->len, data->ptr, (int)data->len, dgst,
+- &dgst_len) == NULL || dgst_len != SHA256_DIGEST_LENGTH)
+- return (NULL);
++ br_hmac_key_init(&kc, &br_sha256_vtable, hmac_key->ptr, hmac_key->len);
++ br_hmac_init(&ctx, &kc, 0);
++ br_hmac_update(&ctx, data->ptr, data->len);
++ br_hmac_out(&ctx, dgst);
++ explicit_bzero(&kc, sizeof(kc));
++ explicit_bzero(&ctx, sizeof(ctx));
+
+ return (cbor_build_bytestring(dgst, 16));
+ }
+@@ -626,17 +626,16 @@ cbor_encode_pin_enc(const fido_blob_t *key, const fido_blob_t *pin)
+ static int
+ sha256(const unsigned char *data, size_t data_len, fido_blob_t *digest)
+ {
+- if ((digest->ptr = calloc(1, SHA256_DIGEST_LENGTH)) == NULL)
++ br_sha256_context ctx;
++
++ if ((digest->ptr = calloc(1, br_sha256_SIZE)) == NULL)
+ return (-1);
+
+- digest->len = SHA256_DIGEST_LENGTH;
++ digest->len = br_sha256_SIZE;
+
+- if (SHA256(data, data_len, digest->ptr) != digest->ptr) {
+- free(digest->ptr);
+- digest->ptr = NULL;
+- digest->len = 0;
+- return (-1);
+- }
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, data, data_len);
++ br_sha256_out(&ctx, digest->ptr);
+
+ return (0);
+ }
+@@ -645,15 +644,10 @@ cbor_item_t *
+ cbor_encode_change_pin_auth(const fido_blob_t *key, const fido_blob_t *new_pin,
+ const fido_blob_t *pin)
+ {
+- unsigned char dgst[SHA256_DIGEST_LENGTH];
+- unsigned int dgst_len;
++ unsigned char dgst[br_sha256_SIZE];
+ cbor_item_t *item = NULL;
+- const EVP_MD *md = NULL;
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+- HMAC_CTX ctx;
+-#else
+- HMAC_CTX *ctx = NULL;
+-#endif
++ br_hmac_context ctx;
++ br_hmac_key_context kc;
+ fido_blob_t *npe = NULL; /* new pin, encrypted */
+ fido_blob_t *ph = NULL; /* pin hash */
+ fido_blob_t *phe = NULL; /* pin hash, encrypted */
+@@ -681,28 +675,13 @@ cbor_encode_change_pin_auth(const fido_blob_t *key, const fido_blob_t *new_pin,
+ goto fail;
+ }
+
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+- HMAC_CTX_init(&ctx);
+-
+- if ((md = EVP_sha256()) == NULL ||
+- HMAC_Init_ex(&ctx, key->ptr, (int)key->len, md, NULL) == 0 ||
+- HMAC_Update(&ctx, npe->ptr, (int)npe->len) == 0 ||
+- HMAC_Update(&ctx, phe->ptr, (int)phe->len) == 0 ||
+- HMAC_Final(&ctx, dgst, &dgst_len) == 0 || dgst_len != 32) {
+- fido_log_debug("%s: HMAC", __func__);
+- goto fail;
+- }
+-#else
+- if ((ctx = HMAC_CTX_new()) == NULL ||
+- (md = EVP_sha256()) == NULL ||
+- HMAC_Init_ex(ctx, key->ptr, (int)key->len, md, NULL) == 0 ||
+- HMAC_Update(ctx, npe->ptr, (int)npe->len) == 0 ||
+- HMAC_Update(ctx, phe->ptr, (int)phe->len) == 0 ||
+- HMAC_Final(ctx, dgst, &dgst_len) == 0 || dgst_len != 32) {
+- fido_log_debug("%s: HMAC", __func__);
+- goto fail;
+- }
+-#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
++ br_hmac_key_init(&kc, &br_sha256_vtable, key->ptr, key->len);
++ br_hmac_init(&ctx, &kc, 0);
++ br_hmac_update(&ctx, npe->ptr, npe->len);
++ br_hmac_update(&ctx, phe->ptr, phe->len);
++ br_hmac_out(&ctx, dgst);
++ explicit_bzero(&kc, sizeof(kc));
++ explicit_bzero(&ctx, sizeof(ctx));
+
+ if ((item = cbor_build_bytestring(dgst, 16)) == NULL) {
+ fido_log_debug("%s: cbor_build_bytestring", __func__);
+@@ -715,11 +694,6 @@ fail:
+ fido_blob_free(&ph);
+ fido_blob_free(&phe);
+
+-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+- if (ctx != NULL)
+- HMAC_CTX_free(ctx);
+-#endif
+-
+ if (ok < 0) {
+ if (item != NULL) {
+ cbor_decref(&item);
+@@ -733,9 +707,9 @@ fail:
+ cbor_item_t *
+ cbor_encode_set_pin_auth(const fido_blob_t *key, const fido_blob_t *pin)
+ {
+- const EVP_MD *md = NULL;
+- unsigned char dgst[SHA256_DIGEST_LENGTH];
+- unsigned int dgst_len;
++ br_hmac_context ctx;
++ br_hmac_key_context kc;
++ unsigned char dgst[br_sha256_SIZE];
+ cbor_item_t *item = NULL;
+ fido_blob_t *pe = NULL;
+
+@@ -747,12 +721,12 @@ cbor_encode_set_pin_auth(const fido_blob_t *key, const fido_blob_t *pin)
+ goto fail;
+ }
+
+- if ((md = EVP_sha256()) == NULL || key->len != 32 || HMAC(md, key->ptr,
+- (int)key->len, pe->ptr, (int)pe->len, dgst, &dgst_len) == NULL ||
+- dgst_len != SHA256_DIGEST_LENGTH) {
+- fido_log_debug("%s: HMAC", __func__);
+- goto fail;
+- }
++ br_hmac_key_init(&kc, &br_sha256_vtable, key->ptr, key->len);
++ br_hmac_init(&ctx, &kc, 0);
++ br_hmac_update(&ctx, pe->ptr, pe->len);
++ br_hmac_out(&ctx, dgst);
++ explicit_bzero(&kc, sizeof(kc));
++ explicit_bzero(&ctx, sizeof(ctx));
+
+ item = cbor_build_bytestring(dgst, 16);
+ fail:
+diff --git a/src/cred.c b/src/cred.c
+index c4e1edb..77d1615 100644
+--- a/src/cred.c
++++ b/src/cred.c
+@@ -4,10 +4,7 @@
+ * license that can be found in the LICENSE file.
+ */
+
+-#include <openssl/ec.h>
+-#include <openssl/evp.h>
+-#include <openssl/sha.h>
+-#include <openssl/x509.h>
++#include <bearssl.h>
+
+ #include <string.h>
+ #include "fido.h"
+@@ -193,18 +190,17 @@ check_extensions(int authdata_ext, int ext)
+ int
+ fido_check_rp_id(const char *id, const unsigned char *obtained_hash)
+ {
+- unsigned char expected_hash[SHA256_DIGEST_LENGTH];
++ br_sha256_context ctx;
++ unsigned char expected_hash[br_sha256_SIZE];
+
+ explicit_bzero(expected_hash, sizeof(expected_hash));
+
+- if (SHA256((const unsigned char *)id, strlen(id),
+- expected_hash) != expected_hash) {
+- fido_log_debug("%s: sha256", __func__);
+- return (-1);
+- }
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, id, strlen(id));
++ br_sha256_out(&ctx, expected_hash);
+
+ return (timingsafe_bcmp(expected_hash, obtained_hash,
+- SHA256_DIGEST_LENGTH));
++ br_sha256_SIZE));
+ }
+
+ static int
+@@ -215,7 +211,7 @@ get_signed_hash_packed(fido_blob_t *dgst, const fido_blob_t *clientdata,
+ unsigned char *authdata_ptr = NULL;
+ size_t authdata_len;
+ struct cbor_load_result cbor;
+- SHA256_CTX ctx;
++ br_sha256_context ctx;
+ int ok = -1;
+
+ if ((item = cbor_load(authdata_cbor->ptr, authdata_cbor->len,
+@@ -233,13 +229,14 @@ get_signed_hash_packed(fido_blob_t *dgst, const fido_blob_t *clientdata,
+ authdata_ptr = cbor_bytestring_handle(item);
+ authdata_len = cbor_bytestring_length(item);
+
+- if (dgst->len != SHA256_DIGEST_LENGTH || SHA256_Init(&ctx) == 0 ||
+- SHA256_Update(&ctx, authdata_ptr, authdata_len) == 0 ||
+- SHA256_Update(&ctx, clientdata->ptr, clientdata->len) == 0 ||
+- SHA256_Final(dgst->ptr, &ctx) == 0) {
++ if (dgst->len != br_sha256_SIZE) {
+ fido_log_debug("%s: sha256", __func__);
+ goto fail;
+ }
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, authdata_ptr, authdata_len);
++ br_sha256_update(&ctx, clientdata->ptr, clientdata->len);
++ br_sha256_out(&ctx, dgst->ptr);
+
+ ok = 0;
+ fail:
+@@ -256,21 +253,23 @@ get_signed_hash_u2f(fido_blob_t *dgst, const unsigned char *rp_id,
+ {
+ const uint8_t zero = 0;
+ const uint8_t four = 4; /* uncompressed point */
+- SHA256_CTX ctx;
+-
+- if (dgst->len != SHA256_DIGEST_LENGTH || SHA256_Init(&ctx) == 0 ||
+- SHA256_Update(&ctx, &zero, sizeof(zero)) == 0 ||
+- SHA256_Update(&ctx, rp_id, rp_id_len) == 0 ||
+- SHA256_Update(&ctx, clientdata->ptr, clientdata->len) == 0 ||
+- SHA256_Update(&ctx, id->ptr, id->len) == 0 ||
+- SHA256_Update(&ctx, &four, sizeof(four)) == 0 ||
+- SHA256_Update(&ctx, pk->x, sizeof(pk->x)) == 0 ||
+- SHA256_Update(&ctx, pk->y, sizeof(pk->y)) == 0 ||
+- SHA256_Final(dgst->ptr, &ctx) == 0) {
++ br_sha256_context ctx;
++
++ if (dgst->len != br_sha256_SIZE) {
+ fido_log_debug("%s: sha256", __func__);
+ return (-1);
+ }
+
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, &zero, sizeof(zero));
++ br_sha256_update(&ctx, rp_id, rp_id_len);
++ br_sha256_update(&ctx, clientdata->ptr, clientdata->len);
++ br_sha256_update(&ctx, id->ptr, id->len);
++ br_sha256_update(&ctx, &four, sizeof(four));
++ br_sha256_update(&ctx, pk->x, sizeof(pk->x));
++ br_sha256_update(&ctx, pk->y, sizeof(pk->y));
++ br_sha256_out(&ctx, dgst->ptr);
++
+ return (0);
+ }
+
+@@ -278,42 +277,29 @@ static int
+ verify_sig(const fido_blob_t *dgst, const fido_blob_t *x5c,
+ const fido_blob_t *sig)
+ {
+- BIO *rawcert = NULL;
+- X509 *cert = NULL;
+- EVP_PKEY *pkey = NULL;
+- EC_KEY *ec;
+- int ok = -1;
+-
+- /* openssl needs ints */
+- if (dgst->len > INT_MAX || x5c->len > INT_MAX || sig->len > INT_MAX) {
+- fido_log_debug("%s: dgst->len=%zu, x5c->len=%zu, sig->len=%zu",
+- __func__, dgst->len, x5c->len, sig->len);
+- return (-1);
+- }
++ br_x509_decoder_context ctx;
++ br_x509_pkey *pkey;
++ int ok = -1;
+
+ /* fetch key from x509 */
+- if ((rawcert = BIO_new_mem_buf(x5c->ptr, (int)x5c->len)) == NULL ||
+- (cert = d2i_X509_bio(rawcert, NULL)) == NULL ||
+- (pkey = X509_get_pubkey(cert)) == NULL ||
+- (ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) {
++ br_x509_decoder_init(&ctx, NULL, NULL);
++ br_x509_decoder_push(&ctx, x5c->ptr, x5c->len);
++ if (br_x509_decoder_last_error(&ctx) != 0 ||
++ (pkey = br_x509_decoder_get_pkey(&ctx)) == NULL ||
++ pkey->key_type != BR_KEYTYPE_EC) {
+ fido_log_debug("%s: x509 key", __func__);
+ goto fail;
+ }
+
+- if (ECDSA_verify(0, dgst->ptr, (int)dgst->len, sig->ptr,
+- (int)sig->len, ec) != 1) {
+- fido_log_debug("%s: ECDSA_verify", __func__);
++ if (br_ecdsa_vrfy_asn1_get_default()(br_ec_get_default(), dgst->ptr,
++ dgst->len, &pkey->key.ec, sig->ptr, sig->len) == 0) {
++ fido_log_debug("%s: ECDSA verify", __func__);
+ goto fail;
+ }
+
+ ok = 0;
+ fail:
+- if (rawcert != NULL)
+- BIO_free(rawcert);
+- if (cert != NULL)
+- X509_free(cert);
+- if (pkey != NULL)
+- EVP_PKEY_free(pkey);
++ explicit_bzero(&ctx, sizeof(ctx));
+
+ return (ok);
+ }
+@@ -321,7 +307,7 @@ fail:
+ int
+ fido_cred_verify(const fido_cred_t *cred)
+ {
+- unsigned char buf[SHA256_DIGEST_LENGTH];
++ unsigned char buf[br_sha256_SIZE];
+ fido_blob_t dgst;
+ int r;
+
+@@ -395,7 +381,7 @@ out:
+ int
+ fido_cred_verify_self(const fido_cred_t *cred)
+ {
+- unsigned char buf[SHA256_DIGEST_LENGTH];
++ unsigned char buf[br_sha256_SIZE];
+ fido_blob_t dgst;
+ int ok = -1;
+ int r;
+diff --git a/src/credman.c b/src/credman.c
+index 76327e5..6b8eeed 100644
+--- a/src/credman.c
++++ b/src/credman.c
+@@ -4,7 +4,7 @@
+ * license that can be found in the LICENSE file.
+ */
+
+-#include <openssl/sha.h>
++#include <bearssl.h>
+
+ #include <string.h>
+
+@@ -369,14 +369,14 @@ static int
+ credman_get_rk_wait(fido_dev_t *dev, const char *rp_id, fido_credman_rk_t *rk,
+ const char *pin, int ms)
+ {
+- fido_blob_t rp_dgst;
+- uint8_t dgst[SHA256_DIGEST_LENGTH];
+- int r;
++ fido_blob_t rp_dgst;
++ br_sha256_context ctx;
++ uint8_t dgst[br_sha256_SIZE];
++ int r;
+
+- if (SHA256((const unsigned char *)rp_id, strlen(rp_id), dgst) != dgst) {
+- fido_log_debug("%s: sha256", __func__);
+- return (FIDO_ERR_INTERNAL);
+- }
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, rp_id, strlen(rp_id));
++ br_sha256_out(&ctx, dgst);
+
+ rp_dgst.ptr = dgst;
+ rp_dgst.len = sizeof(dgst);
+diff --git a/src/ecdh.c b/src/ecdh.c
+index 7f25c7b..7576ae4 100644
+--- a/src/ecdh.c
++++ b/src/ecdh.c
+@@ -4,8 +4,7 @@
+ * license that can be found in the LICENSE file.
+ */
+
+-#include <openssl/evp.h>
+-#include <openssl/sha.h>
++#include <bearssl.h>
+
+ #include "fido.h"
+ #include "fido/es256.h"
+@@ -13,63 +12,43 @@
+ static int
+ do_ecdh(const es256_sk_t *sk, const es256_pk_t *pk, fido_blob_t **ecdh)
+ {
+- EVP_PKEY *pk_evp = NULL;
+- EVP_PKEY *sk_evp = NULL;
+- EVP_PKEY_CTX *ctx = NULL;
+- fido_blob_t *secret = NULL;
+- int ok = -1;
++ unsigned char q[65];
++ br_sha256_context ctx;
++ int ok = -1;
+
+ *ecdh = NULL;
+
+ /* allocate blobs for secret & ecdh */
+- if ((secret = fido_blob_new()) == NULL ||
+- (*ecdh = fido_blob_new()) == NULL)
++ if ((*ecdh = fido_blob_new()) == NULL)
+ goto fail;
+
+- /* wrap the keys as openssl objects */
+- if ((pk_evp = es256_pk_to_EVP_PKEY(pk)) == NULL ||
+- (sk_evp = es256_sk_to_EVP_PKEY(sk)) == NULL) {
+- fido_log_debug("%s: es256_to_EVP_PKEY", __func__);
+- goto fail;
+- }
+-
+- /* set ecdh parameters */
+- if ((ctx = EVP_PKEY_CTX_new(sk_evp, NULL)) == NULL ||
+- EVP_PKEY_derive_init(ctx) <= 0 ||
+- EVP_PKEY_derive_set_peer(ctx, pk_evp) <= 0) {
+- fido_log_debug("%s: EVP_PKEY_derive_init", __func__);
+- goto fail;
+- }
++ q[0] = 4;
++ memcpy(q + 1, pk->x, 32);
++ memcpy(q + 1 + 32, pk->y, 32);
+
+ /* perform ecdh */
+- if (EVP_PKEY_derive(ctx, NULL, &secret->len) <= 0 ||
+- (secret->ptr = calloc(1, secret->len)) == NULL ||
+- EVP_PKEY_derive(ctx, secret->ptr, &secret->len) <= 0) {
+- fido_log_debug("%s: EVP_PKEY_derive", __func__);
++ if (br_ec_get_default()->mul(q, sizeof(q), sk->d, sizeof(sk->d),
++ BR_EC_secp256r1) != 1) {
++ fido_log_debug("%s: ECDH", __func__);
+ goto fail;
+ }
+
+ /* use sha256 as a kdf on the resulting secret */
+- (*ecdh)->len = SHA256_DIGEST_LENGTH;
+- if (((*ecdh)->ptr = calloc(1, (*ecdh)->len)) == NULL ||
+- SHA256(secret->ptr, secret->len, (*ecdh)->ptr) != (*ecdh)->ptr) {
++ (*ecdh)->len = br_sha256_SIZE;
++ if (((*ecdh)->ptr = calloc(1, (*ecdh)->len)) == NULL) {
+ fido_log_debug("%s: sha256", __func__);
+ goto fail;
+ }
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, q + 1, 32);
++ br_sha256_out(&ctx, (*ecdh)->ptr);
+
+ ok = 0;
+ fail:
+- if (pk_evp != NULL)
+- EVP_PKEY_free(pk_evp);
+- if (sk_evp != NULL)
+- EVP_PKEY_free(sk_evp);
+- if (ctx != NULL)
+- EVP_PKEY_CTX_free(ctx);
++ explicit_bzero(q, sizeof(q));
+ if (ok < 0)
+ fido_blob_free(ecdh);
+
+- fido_blob_free(&secret);
+-
+ return (ok);
+ }
+
+diff --git a/src/eddsa.c b/src/eddsa.c
+index 92a0222..252e7ec 100644
+--- a/src/eddsa.c
++++ b/src/eddsa.c
+@@ -4,67 +4,10 @@
+ * license that can be found in the LICENSE file.
+ */
+
+-#include <openssl/bn.h>
+-#include <openssl/ec.h>
+-#include <openssl/evp.h>
+-#include <openssl/obj_mac.h>
+-
+ #include <string.h>
+ #include "fido.h"
+ #include "fido/eddsa.h"
+
+-#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10101000L
+-EVP_PKEY *
+-EVP_PKEY_new_raw_public_key(int type, ENGINE *e, const unsigned char *key,
+- size_t keylen)
+-{
+- (void)type;
+- (void)e;
+- (void)key;
+- (void)keylen;
+-
+- return (NULL);
+-}
+-
+-int
+-EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
+- size_t *len)
+-{
+- (void)pkey;
+- (void)pub;
+- (void)len;
+-
+- return (0);
+-}
+-
+-int
+-EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, size_t siglen,
+- const unsigned char *tbs, size_t tbslen)
+-{
+- (void)ctx;
+- (void)sigret;
+- (void)siglen;
+- (void)tbs;
+- (void)tbslen;
+-
+- return (0);
+-}
+-#endif /* LIBRESSL_VERSION_NUMBER || OPENSSL_VERSION_NUMBER < 0x10101000L */
+-
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+-EVP_MD_CTX *
+-EVP_MD_CTX_new(void)
+-{
+- return (NULL);
+-}
+-
+-void
+-EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+-{
+- (void)ctx;
+-}
+-#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+-
+ static int
+ decode_coord(const cbor_item_t *item, void *xy, size_t xy_len)
+ {
+@@ -140,30 +83,3 @@ eddsa_pk_from_ptr(eddsa_pk_t *pk, const void *ptr, size_t len)
+
+ return (FIDO_OK);
+ }
+-
+-EVP_PKEY *
+-eddsa_pk_to_EVP_PKEY(const eddsa_pk_t *k)
+-{
+- EVP_PKEY *pkey = NULL;
+-
+- if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, k->x,
+- sizeof(k->x))) == NULL)
+- fido_log_debug("%s: EVP_PKEY_new_raw_public_key", __func__);
+-
+- return (pkey);
+-}
+-
+-int
+-eddsa_pk_from_EVP_PKEY(eddsa_pk_t *pk, const EVP_PKEY *pkey)
+-{
+- size_t len = 0;
+-
+- if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1 ||
+- len != sizeof(pk->x))
+- return (FIDO_ERR_INTERNAL);
+- if (EVP_PKEY_get_raw_public_key(pkey, pk->x, &len) != 1 ||
+- len != sizeof(pk->x))
+- return (FIDO_ERR_INTERNAL);
+-
+- return (FIDO_OK);
+-}
+diff --git a/src/es256.c b/src/es256.c
+index c8fd9f4..4b04a6b 100644
+--- a/src/es256.c
++++ b/src/es256.c
+@@ -4,10 +4,7 @@
+ * license that can be found in the LICENSE file.
+ */
+
+-#include <openssl/bn.h>
+-#include <openssl/ec.h>
+-#include <openssl/evp.h>
+-#include <openssl/obj_mac.h>
++#include <bearssl.h>
+
+ #include <string.h>
+ #include "fido.h"
+@@ -203,232 +200,64 @@ es256_pk_set_y(es256_pk_t *pk, const unsigned char *y)
+ int
+ es256_sk_create(es256_sk_t *key)
+ {
+- EVP_PKEY_CTX *pctx = NULL;
+- EVP_PKEY_CTX *kctx = NULL;
+- EVP_PKEY *p = NULL;
+- EVP_PKEY *k = NULL;
+- const EC_KEY *ec;
+- const BIGNUM *d;
+- const int nid = NID_X9_62_prime256v1;
+- int n;
+- int ok = -1;
+-
+- if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL ||
+- EVP_PKEY_paramgen_init(pctx) <= 0 ||
+- EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) <= 0 ||
+- EVP_PKEY_paramgen(pctx, &p) <= 0) {
+- fido_log_debug("%s: EVP_PKEY_paramgen", __func__);
+- goto fail;
+- }
+-
+- if ((kctx = EVP_PKEY_CTX_new(p, NULL)) == NULL ||
+- EVP_PKEY_keygen_init(kctx) <= 0 || EVP_PKEY_keygen(kctx, &k) <= 0) {
+- fido_log_debug("%s: EVP_PKEY_keygen", __func__);
+- goto fail;
+- }
+-
+- if ((ec = EVP_PKEY_get0_EC_KEY(k)) == NULL ||
+- (d = EC_KEY_get0_private_key(ec)) == NULL ||
+- (n = BN_num_bytes(d)) < 0 || (size_t)n > sizeof(key->d) ||
+- (n = BN_bn2bin(d, key->d)) < 0 || (size_t)n > sizeof(key->d)) {
+- fido_log_debug("%s: EC_KEY_get0_private_key", __func__);
+- goto fail;
+- }
+-
+- ok = 0;
+-fail:
+- if (p != NULL)
+- EVP_PKEY_free(p);
+- if (k != NULL)
+- EVP_PKEY_free(k);
+- if (pctx != NULL)
+- EVP_PKEY_CTX_free(pctx);
+- if (kctx != NULL)
+- EVP_PKEY_CTX_free(kctx);
+-
+- return (ok);
+-}
+-
+-EVP_PKEY *
+-es256_pk_to_EVP_PKEY(const es256_pk_t *k)
+-{
+- BN_CTX *bnctx = NULL;
+- EC_KEY *ec = NULL;
+- EC_POINT *q = NULL;
+- EVP_PKEY *pkey = NULL;
+- BIGNUM *x = NULL;
+- BIGNUM *y = NULL;
+- const EC_GROUP *g = NULL;
+- const int nid = NID_X9_62_prime256v1;
+- int ok = -1;
+-
+- if ((bnctx = BN_CTX_new()) == NULL ||
+- (x = BN_CTX_get(bnctx)) == NULL ||
+- (y = BN_CTX_get(bnctx)) == NULL)
+- goto fail;
+-
+- if (BN_bin2bn(k->x, sizeof(k->x), x) == NULL ||
+- BN_bin2bn(k->y, sizeof(k->y), y) == NULL) {
+- fido_log_debug("%s: BN_bin2bn", __func__);
+- goto fail;
+- }
++ br_prng_seeder seeder;
++ br_hmac_drbg_context rng;
++ br_ec_private_key skey;
++ unsigned char kbuf[BR_EC_KBUF_PRIV_MAX_SIZE];
++ int ok = -1;
+
+- if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL ||
+- (g = EC_KEY_get0_group(ec)) == NULL) {
+- fido_log_debug("%s: EC_KEY init", __func__);
++ if ((seeder = br_prng_seeder_system(NULL)) == NULL) {
++ fido_log_debug("%s: no PRNG seeder", __func__);
+ goto fail;
+ }
+-
+- if ((q = EC_POINT_new(g)) == NULL ||
+- EC_POINT_set_affine_coordinates_GFp(g, q, x, y, bnctx) == 0 ||
+- EC_KEY_set_public_key(ec, q) == 0) {
+- fido_log_debug("%s: EC_KEY_set_public_key", __func__);
++ br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0);
++ if (seeder(&rng.vtable) == 0) {
++ fido_log_debug("%s: seed PRNG", __func__);
+ goto fail;
+ }
+-
+- if ((pkey = EVP_PKEY_new()) == NULL ||
+- EVP_PKEY_assign_EC_KEY(pkey, ec) == 0) {
+- fido_log_debug("%s: EVP_PKEY_assign_EC_KEY", __func__);
++ if (br_ec_keygen(&rng.vtable, br_ec_get_default(), &skey, kbuf,
++ BR_EC_secp256r1) != sizeof(key->d)) {
++ fido_log_debug("%s: EC keygen", __func__);
+ goto fail;
+ }
+-
+- ec = NULL; /* at this point, ec belongs to evp */
++ memcpy(key->d, skey.x, sizeof(key->d));
++ explicit_bzero(&skey, sizeof(skey));
++ explicit_bzero(kbuf, sizeof(kbuf));
+
+ ok = 0;
+ fail:
+- if (bnctx != NULL)
+- BN_CTX_free(bnctx);
+- if (ec != NULL)
+- EC_KEY_free(ec);
+- if (q != NULL)
+- EC_POINT_free(q);
+- if (ok < 0 && pkey != NULL) {
+- EVP_PKEY_free(pkey);
+- pkey = NULL;
+- }
+-
+- return (pkey);
+-}
+-
+-int
+-es256_pk_from_EC_KEY(es256_pk_t *pk, const EC_KEY *ec)
+-{
+- BN_CTX *ctx = NULL;
+- BIGNUM *x = NULL;
+- BIGNUM *y = NULL;
+- const EC_POINT *q = NULL;
+- const EC_GROUP *g = NULL;
+- int ok = FIDO_ERR_INTERNAL;
+- int n;
+-
+- if ((q = EC_KEY_get0_public_key(ec)) == NULL ||
+- (g = EC_KEY_get0_group(ec)) == NULL)
+- goto fail;
+-
+- if ((ctx = BN_CTX_new()) == NULL ||
+- (x = BN_CTX_get(ctx)) == NULL ||
+- (y = BN_CTX_get(ctx)) == NULL)
+- goto fail;
+-
+- if (EC_POINT_get_affine_coordinates_GFp(g, q, x, y, ctx) == 0 ||
+- (n = BN_num_bytes(x)) < 0 || (size_t)n > sizeof(pk->x) ||
+- (n = BN_num_bytes(y)) < 0 || (size_t)n > sizeof(pk->y)) {
+- fido_log_debug("%s: EC_POINT_get_affine_coordinates_GFp",
+- __func__);
+- goto fail;
+- }
+-
+- if ((n = BN_bn2bin(x, pk->x)) < 0 || (size_t)n > sizeof(pk->x) ||
+- (n = BN_bn2bin(y, pk->y)) < 0 || (size_t)n > sizeof(pk->y)) {
+- fido_log_debug("%s: BN_bn2bin", __func__);
+- goto fail;
+- }
+-
+- ok = FIDO_OK;
+-fail:
+- if (ctx != NULL)
+- BN_CTX_free(ctx);
+-
+ return (ok);
+ }
+
+-EVP_PKEY *
+-es256_sk_to_EVP_PKEY(const es256_sk_t *k)
+-{
+- BN_CTX *bnctx = NULL;
+- EC_KEY *ec = NULL;
+- EVP_PKEY *pkey = NULL;
+- BIGNUM *d = NULL;
+- const int nid = NID_X9_62_prime256v1;
+- int ok = -1;
+-
+- if ((bnctx = BN_CTX_new()) == NULL || (d = BN_CTX_get(bnctx)) == NULL ||
+- BN_bin2bn(k->d, sizeof(k->d), d) == NULL) {
+- fido_log_debug("%s: BN_bin2bn", __func__);
+- goto fail;
+- }
+-
+- if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL ||
+- EC_KEY_set_private_key(ec, d) == 0) {
+- fido_log_debug("%s: EC_KEY_set_private_key", __func__);
+- goto fail;
+- }
+-
+- if ((pkey = EVP_PKEY_new()) == NULL ||
+- EVP_PKEY_assign_EC_KEY(pkey, ec) == 0) {
+- fido_log_debug("%s: EVP_PKEY_assign_EC_KEY", __func__);
+- goto fail;
+- }
+-
+- ec = NULL; /* at this point, ec belongs to evp */
+-
+- ok = 0;
+-fail:
+- if (bnctx != NULL)
+- BN_CTX_free(bnctx);
+- if (ec != NULL)
+- EC_KEY_free(ec);
+- if (ok < 0 && pkey != NULL) {
+- EVP_PKEY_free(pkey);
+- pkey = NULL;
+- }
+-
+- return (pkey);
+-}
+-
+ int
+ es256_derive_pk(const es256_sk_t *sk, es256_pk_t *pk)
+ {
+- BIGNUM *d = NULL;
+- EC_KEY *ec = NULL;
+- EC_POINT *q = NULL;
+- const EC_GROUP *g = NULL;
+- const int nid = NID_X9_62_prime256v1;
+- int ok = -1;
+-
+- if ((d = BN_bin2bn(sk->d, (int)sizeof(sk->d), NULL)) == NULL ||
+- (ec = EC_KEY_new_by_curve_name(nid)) == NULL ||
+- (g = EC_KEY_get0_group(ec)) == NULL ||
+- (q = EC_POINT_new(g)) == NULL) {
+- fido_log_debug("%s: get", __func__);
+- goto fail;
+- }
+-
+- if (EC_POINT_mul(g, q, d, NULL, NULL, NULL) == 0 ||
+- EC_KEY_set_public_key(ec, q) == 0 ||
+- es256_pk_from_EC_KEY(pk, ec) != FIDO_OK) {
+- fido_log_debug("%s: set", __func__);
++ br_ec_private_key skey;
++ br_ec_public_key pkey;
++ unsigned char kbuf[BR_EC_KBUF_PUB_MAX_SIZE];
++ int ok = -1;
++
++ skey.curve = BR_EC_secp256r1;
++#ifdef __GNUC__
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wcast-qual"
++#endif
++ skey.x = (unsigned char *)sk->d;
++ skey.xlen = sizeof(sk->d);
++#ifdef __GNUC__
++#pragma GCC diagnostic pop
++#endif
++ if (br_ec_compute_pub(br_ec_get_default(), &pkey, kbuf, &skey) != 65 ||
++ pkey.q[0] != 4 ||
++ es256_pk_set_x(pk, pkey.q + 1) != 0 ||
++ es256_pk_set_y(pk, pkey.q + 1 + 32) != 0) {
++ fido_log_debug("%s: EC compute pub", __func__);
+ goto fail;
+ }
+
+ ok = 0;
+ fail:
+- if (d != NULL)
+- BN_clear_free(d);
+- if (q != NULL)
+- EC_POINT_free(q);
+- if (ec != NULL)
+- EC_KEY_free(ec);
++ explicit_bzero(kbuf, sizeof(kbuf));
+
+ return (ok);
+ }
+diff --git a/src/fido.h b/src/fido.h
+index f85a41a..7d3d71e 100644
+--- a/src/fido.h
++++ b/src/fido.h
+@@ -7,9 +7,6 @@
+ #ifndef _FIDO_H
+ #define _FIDO_H
+
+-#include <openssl/ec.h>
+-#include <openssl/evp.h>
+-
+ #include <stdbool.h>
+ #include <stdint.h>
+ #include <stdlib.h>
+diff --git a/src/fido/eddsa.h b/src/fido/eddsa.h
+index 9de272d..d85d05a 100644
+--- a/src/fido/eddsa.h
++++ b/src/fido/eddsa.h
+@@ -7,34 +7,12 @@
+ #ifndef _FIDO_EDDSA_H
+ #define _FIDO_EDDSA_H
+
+-#include <openssl/ec.h>
+-
+ #include <stdint.h>
+ #include <stdlib.h>
+
+ eddsa_pk_t *eddsa_pk_new(void);
+ void eddsa_pk_free(eddsa_pk_t **);
+-EVP_PKEY *eddsa_pk_to_EVP_PKEY(const eddsa_pk_t *);
+
+-int eddsa_pk_from_EVP_PKEY(eddsa_pk_t *, const EVP_PKEY *);
+ int eddsa_pk_from_ptr(eddsa_pk_t *, const void *, size_t);
+
+-#ifdef _FIDO_INTERNAL
+-
+-#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10101000L
+-#define EVP_PKEY_ED25519 EVP_PKEY_NONE
+-int EVP_PKEY_get_raw_public_key(const EVP_PKEY *, unsigned char *, size_t *);
+-EVP_PKEY *EVP_PKEY_new_raw_public_key(int, ENGINE *, const unsigned char *,
+- size_t);
+-int EVP_DigestVerify(EVP_MD_CTX *, const unsigned char *, size_t,
+- const unsigned char *, size_t);
+-#endif /* LIBRESSL_VERSION_NUMBER || OPENSSL_VERSION_NUMBER < 0x10101000L */
+-
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+-EVP_MD_CTX *EVP_MD_CTX_new(void);
+-void EVP_MD_CTX_free(EVP_MD_CTX *);
+-#endif
+-
+-#endif /* _FIDO_INTERNAL */
+-
+ #endif /* !_FIDO_EDDSA_H */
+diff --git a/src/fido/es256.h b/src/fido/es256.h
+index d3d13dd..5ed7be1 100644
+--- a/src/fido/es256.h
++++ b/src/fido/es256.h
+@@ -7,22 +7,17 @@
+ #ifndef _FIDO_ES256_H
+ #define _FIDO_ES256_H
+
+-#include <openssl/ec.h>
+-
+ #include <stdint.h>
+ #include <stdlib.h>
+
+ es256_pk_t *es256_pk_new(void);
+ void es256_pk_free(es256_pk_t **);
+-EVP_PKEY *es256_pk_to_EVP_PKEY(const es256_pk_t *);
+
+-int es256_pk_from_EC_KEY(es256_pk_t *, const EC_KEY *);
+ int es256_pk_from_ptr(es256_pk_t *, const void *, size_t);
+
+ #ifdef _FIDO_INTERNAL
+ es256_sk_t *es256_sk_new(void);
+ void es256_sk_free(es256_sk_t **);
+-EVP_PKEY *es256_sk_to_EVP_PKEY(const es256_sk_t *);
+
+ int es256_derive_pk(const es256_sk_t *, es256_pk_t *);
+ int es256_sk_create(es256_sk_t *);
+diff --git a/src/fido/rs256.h b/src/fido/rs256.h
+index d2fa162..eb84e89 100644
+--- a/src/fido/rs256.h
++++ b/src/fido/rs256.h
+@@ -7,16 +7,12 @@
+ #ifndef _FIDO_RS256_H
+ #define _FIDO_RS256_H
+
+-#include <openssl/rsa.h>
+-
+ #include <stdint.h>
+ #include <stdlib.h>
+
+ rs256_pk_t *rs256_pk_new(void);
+ void rs256_pk_free(rs256_pk_t **);
+-EVP_PKEY *rs256_pk_to_EVP_PKEY(const rs256_pk_t *);
+
+-int rs256_pk_from_RSA(rs256_pk_t *, const RSA *);
+ int rs256_pk_from_ptr(rs256_pk_t *, const void *, size_t);
+
+ #endif /* !_FIDO_RS256_H */
+diff --git a/src/rs256.c b/src/rs256.c
+index 9f30163..c9da648 100644
+--- a/src/rs256.c
++++ b/src/rs256.c
+@@ -4,41 +4,12 @@
+ * license that can be found in the LICENSE file.
+ */
+
+-#include <openssl/bn.h>
+-#include <openssl/rsa.h>
+-#include <openssl/evp.h>
+-#include <openssl/obj_mac.h>
++#include <bearssl.h>
+
+ #include <string.h>
+ #include "fido.h"
+ #include "fido/rs256.h"
+
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+-static int
+-RSA_bits(const RSA *r)
+-{
+- return (BN_num_bits(r->n));
+-}
+-
+-static int
+-RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
+-{
+- r->n = n;
+- r->e = e;
+- r->d = d;
+-
+- return (1);
+-}
+-
+-static void
+-RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
+-{
+- *n = r->n;
+- *e = r->e;
+- *d = r->d;
+-}
+-#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+-
+ static int
+ decode_bignum(const cbor_item_t *item, void *ptr, size_t len)
+ {
+@@ -116,89 +87,3 @@ rs256_pk_from_ptr(rs256_pk_t *pk, const void *ptr, size_t len)
+
+ return (FIDO_OK);
+ }
+-
+-EVP_PKEY *
+-rs256_pk_to_EVP_PKEY(const rs256_pk_t *k)
+-{
+- RSA *rsa = NULL;
+- EVP_PKEY *pkey = NULL;
+- BIGNUM *n = NULL;
+- BIGNUM *e = NULL;
+- int ok = -1;
+-
+- if ((n = BN_new()) == NULL || (e = BN_new()) == NULL)
+- goto fail;
+-
+- if (BN_bin2bn(k->n, sizeof(k->n), n) == NULL ||
+- BN_bin2bn(k->e, sizeof(k->e), e) == NULL) {
+- fido_log_debug("%s: BN_bin2bn", __func__);
+- goto fail;
+- }
+-
+- if ((rsa = RSA_new()) == NULL || RSA_set0_key(rsa, n, e, NULL) == 0) {
+- fido_log_debug("%s: RSA_set0_key", __func__);
+- goto fail;
+- }
+-
+- /* at this point, n and e belong to rsa */
+- n = NULL;
+- e = NULL;
+-
+- if ((pkey = EVP_PKEY_new()) == NULL ||
+- EVP_PKEY_assign_RSA(pkey, rsa) == 0) {
+- fido_log_debug("%s: EVP_PKEY_assign_RSA", __func__);
+- goto fail;
+- }
+-
+- rsa = NULL; /* at this point, rsa belongs to evp */
+-
+- ok = 0;
+-fail:
+- if (n != NULL)
+- BN_free(n);
+- if (e != NULL)
+- BN_free(e);
+- if (rsa != NULL)
+- RSA_free(rsa);
+- if (ok < 0 && pkey != NULL) {
+- EVP_PKEY_free(pkey);
+- pkey = NULL;
+- }
+-
+- return (pkey);
+-}
+-
+-int
+-rs256_pk_from_RSA(rs256_pk_t *pk, const RSA *rsa)
+-{
+- const BIGNUM *n = NULL;
+- const BIGNUM *e = NULL;
+- const BIGNUM *d = NULL;
+- int k;
+-
+- if (RSA_bits(rsa) != 2048) {
+- fido_log_debug("%s: invalid key length", __func__);
+- return (FIDO_ERR_INVALID_ARGUMENT);
+- }
+-
+- RSA_get0_key(rsa, &n, &e, &d);
+-
+- if (n == NULL || e == NULL) {
+- fido_log_debug("%s: RSA_get0_key", __func__);
+- return (FIDO_ERR_INTERNAL);
+- }
+-
+- if ((k = BN_num_bytes(n)) < 0 || (size_t)k > sizeof(pk->n) ||
+- (k = BN_num_bytes(e)) < 0 || (size_t)k > sizeof(pk->e)) {
+- fido_log_debug("%s: invalid key", __func__);
+- return (FIDO_ERR_INTERNAL);
+- }
+-
+- if ((k = BN_bn2bin(n, pk->n)) < 0 || (size_t)k > sizeof(pk->n) ||
+- (k = BN_bn2bin(e, pk->e)) < 0 || (size_t)k > sizeof(pk->e)) {
+- fido_log_debug("%s: BN_bn2bin", __func__);
+- return (FIDO_ERR_INTERNAL);
+- }
+-
+- return (FIDO_OK);
+-}
+diff --git a/src/u2f.c b/src/u2f.c
+index e02b611..56f93f1 100644
+--- a/src/u2f.c
++++ b/src/u2f.c
+@@ -4,8 +4,7 @@
+ * license that can be found in the LICENSE file.
+ */
+
+-#include <openssl/sha.h>
+-#include <openssl/x509.h>
++#include <bearssl.h>
+
+ #include <string.h>
+ #ifdef HAVE_UNISTD_H
+@@ -78,21 +77,31 @@ sig_get(fido_blob_t *sig, const unsigned char **buf, size_t *len)
+ static int
+ x5c_get(fido_blob_t *x5c, const unsigned char **buf, size_t *len)
+ {
+- X509 *cert = NULL;
+- int ok = -1;
+-
+- if (*len > LONG_MAX) {
+- fido_log_debug("%s: invalid len %zu", __func__, *len);
+- goto fail;
+- }
++ br_x509_decoder_context ctx;
++ const unsigned char *seq;
++ size_t len_len;
++ int ok = -1;
+
+ /* find out the certificate's length */
+- const unsigned char *end = *buf;
+- if ((cert = d2i_X509(NULL, &end, (long)*len)) == NULL || end <= *buf ||
+- (x5c->len = (size_t)(end - *buf)) >= *len) {
+- fido_log_debug("%s: d2i_X509", __func__);
++ seq = *buf;
++ if (*len < 2 || seq[0] != 0x30 || seq[1] == 0x80) {
++ fido_log_debug("%s: X.509 decode", __func__);
+ goto fail;
+ }
++ if ((seq[1] & 0x80) != 0) {
++ len_len = seq[1] & 0x7f;
++ if (len_len > sizeof(size_t) || len_len > *len - 2) {
++ fido_log_debug("%s: X.509 decode", __func__);
++ goto fail;
++ }
++ seq += 2;
++ x5c->len = 0;
++ while (len_len--)
++ x5c->len = x5c->len << 8 | *seq++;
++ x5c->len += seq - *buf;
++ } else {
++ x5c->len = 2 + seq[1];
++ }
+
+ /* read accordingly */
+ if ((x5c->ptr = calloc(1, x5c->len)) == NULL ||
+@@ -103,8 +112,7 @@ x5c_get(fido_blob_t *x5c, const unsigned char **buf, size_t *len)
+
+ ok = 0;
+ fail:
+- if (cert != NULL)
+- X509_free(cert);
++ explicit_bzero(&ctx, sizeof(ctx));
+
+ if (ok < 0) {
+ free(x5c->ptr);
+@@ -119,6 +127,7 @@ static int
+ authdata_fake(const char *rp_id, uint8_t flags, uint32_t sigcount,
+ fido_blob_t *fake_cbor_ad)
+ {
++ br_sha256_context ctx;
+ uint8_t authdata[AUTHDATA_BASE_SIZE] = {0};
+ unsigned char *rp_id_hash;
+ cbor_item_t *item = NULL;
+@@ -126,11 +135,9 @@ authdata_fake(const char *rp_id, uint8_t flags, uint32_t sigcount,
+
+ rp_id_hash = (unsigned char *)&authdata[AUTHDATA_RP_ID_HASH];
+
+- if (SHA256((const void *)rp_id, strlen(rp_id),
+- rp_id_hash) != rp_id_hash) {
+- fido_log_debug("%s: sha256", __func__);
+- return (-1);
+- }
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, rp_id, strlen(rp_id));
++ br_sha256_out(&ctx, rp_id_hash);
+
+ authdata[AUTHDATA_FLAGS] = flags; /* XXX translate? */
+ memcpy(&authdata[AUTHDATA_SIGN_COUNT], &sigcount, 4);
+@@ -159,8 +166,8 @@ send_dummy_register(fido_dev_t *dev, int ms)
+ {
+ const uint8_t cmd = CTAP_FRAME_INIT | CTAP_CMD_MSG;
+ iso7816_apdu_t *apdu = NULL;
+- unsigned char challenge[SHA256_DIGEST_LENGTH];
+- unsigned char application[SHA256_DIGEST_LENGTH];
++ unsigned char challenge[br_sha256_SIZE];
++ unsigned char application[br_sha256_SIZE];
+ unsigned char reply[2048];
+ int r;
+
+@@ -173,7 +180,7 @@ send_dummy_register(fido_dev_t *dev, int ms)
+ memset(&application, 0xff, sizeof(application));
+
+ if ((apdu = iso7816_new(U2F_CMD_REGISTER, 0, 2 *
+- SHA256_DIGEST_LENGTH)) == NULL ||
++ br_sha256_SIZE)) == NULL ||
+ iso7816_add(apdu, &challenge, sizeof(challenge)) < 0 ||
+ iso7816_add(apdu, &application, sizeof(application)) < 0) {
+ fido_log_debug("%s: iso7816", __func__);
+@@ -211,10 +218,11 @@ static int
+ key_lookup(fido_dev_t *dev, const char *rp_id, const fido_blob_t *key_id,
+ int *found, int ms)
+ {
++ br_sha256_context ctx;
+ const uint8_t cmd = CTAP_FRAME_INIT | CTAP_CMD_MSG;
+ iso7816_apdu_t *apdu = NULL;
+- unsigned char challenge[SHA256_DIGEST_LENGTH];
+- unsigned char rp_id_hash[SHA256_DIGEST_LENGTH];
++ unsigned char challenge[br_sha256_SIZE];
++ unsigned char rp_id_hash[br_sha256_SIZE];
+ unsigned char reply[8];
+ uint8_t key_id_len;
+ int r;
+@@ -229,17 +237,14 @@ key_lookup(fido_dev_t *dev, const char *rp_id, const fido_blob_t *key_id,
+ memset(&challenge, 0xff, sizeof(challenge));
+ memset(&rp_id_hash, 0, sizeof(rp_id_hash));
+
+- if (SHA256((const void *)rp_id, strlen(rp_id),
+- rp_id_hash) != rp_id_hash) {
+- fido_log_debug("%s: sha256", __func__);
+- r = FIDO_ERR_INTERNAL;
+- goto fail;
+- }
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, rp_id, strlen(rp_id));
++ br_sha256_out(&ctx, rp_id_hash);
+
+ key_id_len = (uint8_t)key_id->len;
+
+ if ((apdu = iso7816_new(U2F_CMD_AUTH, U2F_AUTH_CHECK, 2 *
+- SHA256_DIGEST_LENGTH + sizeof(key_id_len) + key_id_len)) == NULL ||
++ br_sha256_SIZE + sizeof(key_id_len) + key_id_len)) == NULL ||
+ iso7816_add(apdu, &challenge, sizeof(challenge)) < 0 ||
+ iso7816_add(apdu, &rp_id_hash, sizeof(rp_id_hash)) < 0 ||
+ iso7816_add(apdu, &key_id_len, sizeof(key_id_len)) < 0 ||
+@@ -317,9 +322,10 @@ static int
+ do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id,
+ const fido_blob_t *key_id, fido_blob_t *sig, fido_blob_t *ad, int ms)
+ {
++ br_sha256_context ctx;
+ const uint8_t cmd = CTAP_FRAME_INIT | CTAP_CMD_MSG;
+ iso7816_apdu_t *apdu = NULL;
+- unsigned char rp_id_hash[SHA256_DIGEST_LENGTH];
++ unsigned char rp_id_hash[br_sha256_SIZE];
+ unsigned char reply[128];
+ int reply_len;
+ uint8_t key_id_len;
+@@ -329,7 +335,7 @@ do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id,
+ ms = 0; /* XXX */
+ #endif
+
+- if (cdh->len != SHA256_DIGEST_LENGTH || key_id->len > UINT8_MAX ||
++ if (cdh->len != br_sha256_SIZE || key_id->len > UINT8_MAX ||
+ rp_id == NULL) {
+ r = FIDO_ERR_INVALID_ARGUMENT;
+ goto fail;
+@@ -337,17 +343,14 @@ do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id,
+
+ memset(&rp_id_hash, 0, sizeof(rp_id_hash));
+
+- if (SHA256((const void *)rp_id, strlen(rp_id),
+- rp_id_hash) != rp_id_hash) {
+- fido_log_debug("%s: sha256", __func__);
+- r = FIDO_ERR_INTERNAL;
+- goto fail;
+- }
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, rp_id, strlen(rp_id));
++ br_sha256_out(&ctx, rp_id_hash);
+
+ key_id_len = (uint8_t)key_id->len;
+
+ if ((apdu = iso7816_new(U2F_CMD_AUTH, U2F_AUTH_SIGN, 2 *
+- SHA256_DIGEST_LENGTH + sizeof(key_id_len) + key_id_len)) == NULL ||
++ br_sha256_SIZE + sizeof(key_id_len) + key_id_len)) == NULL ||
+ iso7816_add(apdu, cdh->ptr, cdh->len) < 0 ||
+ iso7816_add(apdu, &rp_id_hash, sizeof(rp_id_hash)) < 0 ||
+ iso7816_add(apdu, &key_id_len, sizeof(key_id_len)) < 0 ||
+@@ -436,6 +439,7 @@ static int
+ encode_cred_authdata(const char *rp_id, const uint8_t *kh, uint8_t kh_len,
+ const uint8_t *pubkey, size_t pubkey_len, fido_blob_t *out)
+ {
++ br_sha256_context ctx;
+ uint8_t authdata[AUTHDATA_BASE_SIZE] = {0};
+ unsigned char *rp_id_hash;
+ uint8_t attcred_raw[ATTCRED_BASE_SIZE] = {0};
+@@ -463,11 +467,9 @@ encode_cred_authdata(const char *rp_id, const uint8_t *kh, uint8_t kh_len,
+
+ rp_id_hash = (unsigned char *)&authdata[AUTHDATA_RP_ID_HASH];
+
+- if (SHA256((const void *)rp_id, strlen(rp_id),
+- rp_id_hash) != rp_id_hash) {
+- fido_log_debug("%s: sha256", __func__);
+- goto fail;
+- }
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, rp_id, strlen(rp_id));
++ br_sha256_out(&ctx, rp_id_hash);
+
+ authdata[AUTHDATA_FLAGS] = (CTAP_AUTHDATA_ATT_CRED |
+ CTAP_AUTHDATA_USER_PRESENT);
+@@ -609,9 +611,10 @@ fail:
+ int
+ u2f_register(fido_dev_t *dev, fido_cred_t *cred, int ms)
+ {
++ br_sha256_context ctx;
+ const uint8_t cmd = CTAP_FRAME_INIT | CTAP_CMD_MSG;
+ iso7816_apdu_t *apdu = NULL;
+- unsigned char rp_id_hash[SHA256_DIGEST_LENGTH];
++ unsigned char rp_id_hash[br_sha256_SIZE];
+ unsigned char reply[2048];
+ int reply_len;
+ int found;
+@@ -628,7 +631,7 @@ u2f_register(fido_dev_t *dev, fido_cred_t *cred, int ms)
+ }
+
+ if (cred->type != COSE_ES256 || cred->cdh.ptr == NULL ||
+- cred->rp.id == NULL || cred->cdh.len != SHA256_DIGEST_LENGTH) {
++ cred->rp.id == NULL || cred->cdh.len != br_sha256_SIZE) {
+ fido_log_debug("%s: type=%d, cdh=(%p,%zu)" , __func__,
+ cred->type, (void *)cred->cdh.ptr, cred->cdh.len);
+ return (FIDO_ERR_INVALID_ARGUMENT);
+@@ -652,14 +655,12 @@ u2f_register(fido_dev_t *dev, fido_cred_t *cred, int ms)
+
+ memset(&rp_id_hash, 0, sizeof(rp_id_hash));
+
+- if (SHA256((const void *)cred->rp.id, strlen(cred->rp.id),
+- rp_id_hash) != rp_id_hash) {
+- fido_log_debug("%s: sha256", __func__);
+- return (FIDO_ERR_INTERNAL);
+- }
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, cred->rp.id, strlen(cred->rp.id));
++ br_sha256_out(&ctx, rp_id_hash);
+
+ if ((apdu = iso7816_new(U2F_CMD_REGISTER, 0, 2 *
+- SHA256_DIGEST_LENGTH)) == NULL ||
++ br_sha256_SIZE)) == NULL ||
+ iso7816_add(apdu, cred->cdh.ptr, cred->cdh.len) < 0 ||
+ iso7816_add(apdu, rp_id_hash, sizeof(rp_id_hash)) < 0) {
+ fido_log_debug("%s: iso7816", __func__);
+--
+2.26.0
+
diff --git a/pkg/libfido2/ver b/pkg/libfido2/ver
@@ -1 +1 @@
-1.3.1 r1
+1.3.1 r2