master hovercats/oakiss / pkg / openbsd / patch / 0035-acme-client-Port-to-BearSSL.patch
   1From 1c035ffeee5beaaef9907f7b1a17c64e384085b5 Mon Sep 17 00:00:00 2001
   2From: Michael Forney <mforney@mforney.org>
   3Date: Fri, 23 Apr 2021 23:14:16 -0700
   4Subject: [PATCH] acme-client: Port to BearSSL
   5
   6---
   7 usr.sbin/acme-client/acctproc.c   | 322 ++++++++++-------------------
   8 usr.sbin/acme-client/certproc.c   |   5 -
   9 usr.sbin/acme-client/key.c        | 329 ++++++++++++++++++++++++------
  10 usr.sbin/acme-client/key.h        |  22 +-
  11 usr.sbin/acme-client/keyproc.c    | 192 ++++++-----------
  12 usr.sbin/acme-client/revokeproc.c | 327 +++++++++++------------------
  13 6 files changed, 580 insertions(+), 617 deletions(-)
  14
  15diff --git a/usr.sbin/acme-client/acctproc.c b/usr.sbin/acme-client/acctproc.c
  16index 7a0b9811990..adbe6e8c2ab 100644
  17--- a/usr.sbin/acme-client/acctproc.c
  18+++ b/usr.sbin/acme-client/acctproc.c
  19@@ -19,74 +19,29 @@
  20 
  21 #include <err.h>
  22 #include <errno.h>
  23-#include <limits.h>
  24 #include <stdio.h>
  25 #include <stdlib.h>
  26 #include <string.h>
  27 #include <unistd.h>
  28 
  29-#include <openssl/bn.h>
  30-#include <openssl/ec.h>
  31-#include <openssl/evp.h>
  32-#include <openssl/hmac.h>
  33-#include <openssl/rsa.h>
  34-#include <openssl/err.h>
  35+#include <bearssl.h>
  36 
  37 #include "extern.h"
  38 #include "key.h"
  39 
  40-/*
  41- * Converts a BIGNUM to the form used in JWK.
  42- * This is essentially a base64-encoded big-endian binary string
  43- * representation of the number.
  44- */
  45-static char *
  46-bn2string(const BIGNUM *bn)
  47-{
  48-	int		 len;
  49-	unsigned char	*buf;
  50-	char		*bbuf;
  51-
  52-	/* Extract big-endian representation of BIGNUM. */
  53-
  54-	len = BN_num_bytes(bn);
  55-	if ((buf = malloc(len)) == NULL) {
  56-		warn("malloc");
  57-		return NULL;
  58-	} else if (len != BN_bn2bin(bn, buf)) {
  59-		warnx("BN_bn2bin");
  60-		free(buf);
  61-		return NULL;
  62-	}
  63-
  64-	/* Convert to base64url. */
  65-
  66-	if ((bbuf = base64buf_url(buf, len)) == NULL) {
  67-		warnx("base64buf_url");
  68-		free(buf);
  69-		return NULL;
  70-	}
  71-
  72-	free(buf);
  73-	return bbuf;
  74-}
  75-
  76 /*
  77  * Extract the relevant RSA components from the key and create the JSON
  78  * thumbprint from them.
  79  */
  80 static char *
  81-op_thumb_rsa(EVP_PKEY *pkey)
  82+op_thumb_rsa(struct key *key)
  83 {
  84 	char	*exp = NULL, *mod = NULL, *json = NULL;
  85-	RSA	*r;
  86-
  87-	if ((r = EVP_PKEY_get0_RSA(pkey)) == NULL)
  88-		warnx("EVP_PKEY_get0_RSA");
  89-	else if ((mod = bn2string(RSA_get0_n(r))) == NULL)
  90-		warnx("bn2string");
  91-	else if ((exp = bn2string(RSA_get0_e(r))) == NULL)
  92-		warnx("bn2string");
  93+
  94+	if ((mod = base64buf_url(key->rsa.pk.n, key->rsa.pk.nlen)) == NULL)
  95+		warnx("base64buf_url");
  96+	else if ((exp = base64buf_url(key->rsa.pk.e, key->rsa.pk.elen)) == NULL)
  97+		warnx("base64buf_url");
  98 	else if ((json = json_fmt_thumb_rsa(exp, mod)) == NULL)
  99 		warnx("json_fmt_thumb_rsa");
 100 
 101@@ -100,31 +55,23 @@ op_thumb_rsa(EVP_PKEY *pkey)
 102  * thumbprint from them.
 103  */
 104 static char *
 105-op_thumb_ec(EVP_PKEY *pkey)
 106+op_thumb_ec(struct key *key)
 107 {
 108-	BIGNUM	*X = NULL, *Y = NULL;
 109-	EC_KEY	*ec = NULL;
 110+	size_t	len;
 111 	char	*x = NULL, *y = NULL;
 112 	char	*json = NULL;
 113 
 114-	if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
 115-		warnx("EVP_PKEY_get0_EC_KEY");
 116-	else if ((X = BN_new()) == NULL)
 117-		warnx("BN_new");
 118-	else if ((Y = BN_new()) == NULL)
 119-		warnx("BN_new");
 120-	else if (!EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
 121-	    EC_KEY_get0_public_key(ec), X, Y, NULL))
 122-		warnx("EC_POINT_get_affine_coordinates");
 123-	else if ((x = bn2string(X)) == NULL)
 124-		warnx("bn2string");
 125-	else if ((y = bn2string(Y)) == NULL)
 126-		warnx("bn2string");
 127+	/* Points are stored in uncompressed format. */
 128+	len = key->ec.pk.qlen / 2;
 129+	if (key->ec.pk.qlen % 2 != 1 || key->ec.pk.q[0] != 0x04)
 130+		warnx("invalid EC public key");
 131+	else if ((x = base64buf_url(key->ec.pk.q + 1, len)) == NULL)
 132+		warnx("base64buf_url");
 133+	else if ((y = base64buf_url(key->ec.pk.q + 1 + len, len)) == NULL)
 134+		warnx("base64buf_url");
 135 	else if ((json = json_fmt_thumb_ec(x, y)) == NULL)
 136 		warnx("json_fmt_thumb_ec");
 137 
 138-	BN_free(X);
 139-	BN_free(Y);
 140 	free(x);
 141 	free(y);
 142 	return json;
 143@@ -134,26 +81,26 @@ op_thumb_ec(EVP_PKEY *pkey)
 144  * The thumbprint operation is used for the challenge sequence.
 145  */
 146 static int
 147-op_thumbprint(int fd, EVP_PKEY *pkey)
 148+op_thumbprint(int fd, struct key *pkey)
 149 {
 150-	char		*thumb = NULL, *dig64 = NULL;
 151-	unsigned char	 dig[EVP_MAX_MD_SIZE];
 152-	unsigned int	 digsz;
 153-	int		 rc = 0;
 154+	char			*thumb = NULL, *dig64 = NULL;
 155+	br_sha256_context	 ctx;
 156+	unsigned char		 dig[br_sha256_SIZE];
 157+	int			 rc = 0;
 158 
 159 	/* Construct the thumbprint input itself. */
 160 
 161-	switch (EVP_PKEY_base_id(pkey)) {
 162-	case EVP_PKEY_RSA:
 163+	switch (pkey->type) {
 164+	case BR_KEYTYPE_RSA:
 165 		if ((thumb = op_thumb_rsa(pkey)) != NULL)
 166 			break;
 167 		goto out;
 168-	case EVP_PKEY_EC:
 169+	case BR_KEYTYPE_EC:
 170 		if ((thumb = op_thumb_ec(pkey)) != NULL)
 171 			break;
 172 		goto out;
 173 	default:
 174-		warnx("EVP_PKEY_base_id: unknown key type");
 175+		warnx("unknown key type");
 176 		goto out;
 177 	}
 178 
 179@@ -164,12 +111,10 @@ op_thumbprint(int fd, EVP_PKEY *pkey)
 180 	 * it up in the read loop).
 181 	 */
 182 
 183-	if (!EVP_Digest(thumb, strlen(thumb), dig, &digsz, EVP_sha256(),
 184-	    NULL)) {
 185-		warnx("EVP_Digest");
 186-		goto out;
 187-	}
 188-	if ((dig64 = base64buf_url(dig, digsz)) == NULL) {
 189+	br_sha256_init(&ctx);
 190+	br_sha256_update(&ctx, thumb, strlen(thumb));
 191+	br_sha256_out(&ctx, dig);
 192+	if ((dig64 = base64buf_url(dig, sizeof(dig))) == NULL) {
 193 		warnx("base64buf_url");
 194 		goto out;
 195 	}
 196@@ -184,20 +129,17 @@ out:
 197 }
 198 
 199 static int
 200-op_sign_rsa(char **jwk, EVP_PKEY *pkey)
 201+op_sign_rsa(char **jwk, struct key *key)
 202 {
 203 	char	*exp = NULL, *mod = NULL;
 204 	int	rc = 0;
 205-	RSA	*r;
 206 
 207 	*jwk = NULL;
 208 
 209-	if ((r = EVP_PKEY_get0_RSA(pkey)) == NULL)
 210-		warnx("EVP_PKEY_get0_RSA");
 211-	else if ((mod = bn2string(RSA_get0_n(r))) == NULL)
 212-		warnx("bn2string");
 213-	else if ((exp = bn2string(RSA_get0_e(r))) == NULL)
 214-		warnx("bn2string");
 215+	if ((mod = base64buf_url(key->rsa.pk.n, key->rsa.pk.nlen)) == NULL)
 216+		warnx("base64buf_url");
 217+	else if ((exp = base64buf_url(key->rsa.pk.e, key->rsa.pk.elen)) == NULL)
 218+		warnx("base64buf_url");
 219 	else if ((*jwk = json_fmt_jwk_rsa(exp, mod)) == NULL)
 220 		warnx("json_fmt_jwk_rsa");
 221 	else
 222@@ -209,35 +151,27 @@ op_sign_rsa(char **jwk, EVP_PKEY *pkey)
 223 }
 224 
 225 static int
 226-op_sign_ec(char **jwk, EVP_PKEY *pkey)
 227+op_sign_ec(char **jwk, struct key *key)
 228 {
 229-	BIGNUM	*X = NULL, *Y = NULL;
 230-	EC_KEY	*ec = NULL;
 231+	size_t	len;
 232 	char	*x = NULL, *y = NULL;
 233 	int	rc = 0;
 234 
 235 	*jwk = NULL;
 236 
 237-	if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
 238-		warnx("EVP_PKEY_get0_EC_KEY");
 239-	else if ((X = BN_new()) == NULL)
 240-		warnx("BN_new");
 241-	else if ((Y = BN_new()) == NULL)
 242-		warnx("BN_new");
 243-	else if (!EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
 244-	    EC_KEY_get0_public_key(ec), X, Y, NULL))
 245-		warnx("EC_POINT_get_affine_coordinates");
 246-	else if ((x = bn2string(X)) == NULL)
 247-		warnx("bn2string");
 248-	else if ((y = bn2string(Y)) == NULL)
 249-		warnx("bn2string");
 250+	/* Points are stored in uncompressed format. */
 251+	len = key->ec.pk.qlen / 2;
 252+	if (key->ec.pk.qlen % 2 != 1 || key->ec.pk.q[0] != 0x04)
 253+		warnx("invalid EC public key");
 254+	else if ((x = base64buf_url(key->ec.pk.q + 1, len)) == NULL)
 255+		warnx("base64buf_url");
 256+	else if ((y = base64buf_url(key->ec.pk.q + 1 + len, len)) == NULL)
 257+		warnx("base64buf_url");
 258 	else if ((*jwk = json_fmt_jwk_ec(x, y)) == NULL)
 259 		warnx("json_fmt_jwk_ec");
 260 	else
 261 		rc = 1;
 262 
 263-	BN_free(X);
 264-	BN_free(Y);
 265 	free(x);
 266 	free(y);
 267 	return rc;
 268@@ -248,21 +182,19 @@ op_sign_ec(char **jwk, EVP_PKEY *pkey)
 269  * This requires the sender ("fd") to provide the payload and a nonce.
 270  */
 271 static int
 272-op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
 273+op_sign(int fd, struct key *key, enum acctop op)
 274 {
 275-	EVP_MD_CTX		*ctx = NULL;
 276-	const EVP_MD		*evp_md = NULL;
 277-	ECDSA_SIG		*ec_sig = NULL;
 278-	const BIGNUM		*ec_sig_r = NULL, *ec_sig_s = NULL;
 279-	int			 bn_len, sign_len, rc = 0;
 280+	br_hash_compat_context	 ctx;
 281+	int			 sign_len, rc = 0;
 282+	unsigned int		 digsz, sigsz;
 283 	char			*nonce = NULL, *pay = NULL, *pay64 = NULL;
 284 	char			*prot = NULL, *prot64 = NULL;
 285-	char			*sign = NULL, *dig64 = NULL, *fin = NULL;
 286+	char			*sign = NULL, *sig64 = NULL, *fin = NULL;
 287 	char			*url = NULL, *kid = NULL, *alg = NULL;
 288 	char			*jwk = NULL;
 289-	const unsigned char	*digp;
 290-	unsigned char		*dig = NULL, *buf = NULL;
 291-	size_t			 digsz;
 292+	unsigned char		 dig[64];
 293+	unsigned char		*sig = NULL;
 294+	const unsigned char	*oid = NULL;
 295 
 296 	/* Read our payload and nonce from the requestor. */
 297 
 298@@ -279,19 +211,22 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
 299 
 300 	/* Base64-encode the payload. */
 301 
 302-	if ((pay64 = base64buf_url((unsigned char *)pay, strlen(pay))) == NULL) {
 303+	if ((pay64 = base64buf_url(pay, strlen(pay))) == NULL) {
 304 		warnx("base64buf_url");
 305 		goto out;
 306 	}
 307 
 308-	switch (EVP_PKEY_base_id(pkey)) {
 309-	case EVP_PKEY_RSA:
 310+	switch (key->type) {
 311+	case BR_KEYTYPE_RSA:
 312 		alg = "RS256";
 313-		evp_md = EVP_sha256();
 314+		ctx.vtable = &br_sha256_vtable;
 315+		oid = BR_HASH_OID_SHA256;
 316+		sigsz = (key->rsa.sk.n_bitlen + 7) / 8;
 317 		break;
 318-	case EVP_PKEY_EC:
 319+	case BR_KEYTYPE_EC:
 320 		alg = "ES384";
 321-		evp_md = EVP_sha384();
 322+		ctx.vtable = &br_sha384_vtable;
 323+		sigsz = 96;
 324 		break;
 325 	default:
 326 		warnx("unknown account key type");
 327@@ -305,17 +240,17 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
 328 			goto out;
 329 		}
 330 	} else {
 331-		switch (EVP_PKEY_base_id(pkey)) {
 332-		case EVP_PKEY_RSA:
 333-			if (!op_sign_rsa(&jwk, pkey))
 334+		switch (key->type) {
 335+		case BR_KEYTYPE_RSA:
 336+			if (!op_sign_rsa(&jwk, key))
 337 				goto out;
 338 			break;
 339-		case EVP_PKEY_EC:
 340-			if (!op_sign_ec(&jwk, pkey))
 341+		case BR_KEYTYPE_EC:
 342+			if (!op_sign_ec(&jwk, key))
 343 				goto out;
 344 			break;
 345 		default:
 346-			warnx("EVP_PKEY_base_id");
 347+			warnx("unknown key type");
 348 			goto out;
 349 		}
 350 
 351@@ -342,76 +277,34 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
 352 
 353 	/* Sign the message. */
 354 
 355-	if ((ctx = EVP_MD_CTX_new()) == NULL) {
 356-		warnx("EVP_MD_CTX_new");
 357-		goto out;
 358-	}
 359-	if (!EVP_DigestSignInit(ctx, NULL, evp_md, NULL, pkey)) {
 360-		warnx("EVP_DigestSignInit");
 361-		goto out;
 362-	}
 363-	if (!EVP_DigestSign(ctx, NULL, &digsz, sign, sign_len)) {
 364-		warnx("EVP_DigestSign");
 365-		goto out;
 366-	}
 367-	if ((dig = malloc(digsz)) == NULL) {
 368+	ctx.vtable->init(&ctx.vtable);
 369+	ctx.vtable->update(&ctx.vtable, sign, sign_len);
 370+	ctx.vtable->out(&ctx.vtable, dig);
 371+	digsz = ctx.vtable->desc >> BR_HASHDESC_OUT_OFF & BR_HASHDESC_OUT_MASK;
 372+
 373+	if ((sig = malloc(sigsz)) == NULL) {
 374 		warn("malloc");
 375 		goto out;
 376 	}
 377-	if (!EVP_DigestSign(ctx, dig, &digsz, sign, sign_len)) {
 378-		warnx("EVP_DigestSign");
 379-		goto out;
 380-	}
 381 
 382-	switch (EVP_PKEY_base_id(pkey)) {
 383-	case EVP_PKEY_RSA:
 384-		if ((dig64 = base64buf_url(dig, digsz)) == NULL) {
 385-			warnx("base64buf_url");
 386+	switch (key->type) {
 387+	case BR_KEYTYPE_RSA:
 388+		if (!br_rsa_pkcs1_sign_get_default()(oid, dig, digsz,
 389+		    &key->rsa.sk, sig)) {
 390+			warnx("br_rsa_pkcs1_sign");
 391 			goto out;
 392 		}
 393 		break;
 394-	case EVP_PKEY_EC:
 395-		if (digsz > LONG_MAX) {
 396-			warnx("EC signature too long");
 397-			goto out;
 398-		}
 399-
 400-		digp = dig;
 401-		if ((ec_sig = d2i_ECDSA_SIG(NULL, &digp, digsz)) == NULL) {
 402-			warnx("d2i_ECDSA_SIG");
 403-			goto out;
 404-		}
 405-
 406-		if ((ec_sig_r = ECDSA_SIG_get0_r(ec_sig)) == NULL ||
 407-		    (ec_sig_s = ECDSA_SIG_get0_s(ec_sig)) == NULL) {
 408-			warnx("ECDSA_SIG_get0");
 409-			goto out;
 410-		}
 411-
 412-		if ((bn_len = (EVP_PKEY_bits(pkey) + 7) / 8) <= 0) {
 413-			warnx("EVP_PKEY_bits");
 414-			goto out;
 415-		}
 416-
 417-		if ((buf = calloc(2, bn_len)) == NULL) {
 418-			warnx("calloc");
 419+	case BR_KEYTYPE_EC:
 420+		sigsz = br_ecdsa_sign_raw_get_default()(br_ec_get_default(),
 421+		    ctx.vtable, dig, &key->ec.sk, sig);
 422+		if (sigsz == 0 || sigsz % 2 != 0) {
 423+			warnx("br_ecdsa_sign_raw");
 424 			goto out;
 425 		}
 426-
 427-		if (BN_bn2binpad(ec_sig_r, buf, bn_len) != bn_len ||
 428-		    BN_bn2binpad(ec_sig_s, buf + bn_len, bn_len) != bn_len) {
 429-			warnx("BN_bn2binpad");
 430-			goto out;
 431-		}
 432-
 433-		if ((dig64 = base64buf_url(buf, 2 * bn_len)) == NULL) {
 434-			warnx("base64buf_url");
 435-			goto out;
 436-		}
 437-
 438 		break;
 439 	default:
 440-		warnx("EVP_PKEY_base_id");
 441+		warnx("unknown key type");
 442 		goto out;
 443 	}
 444 
 445@@ -421,7 +314,11 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
 446 	 * when we next enter the read loop).
 447 	 */
 448 
 449-	if ((fin = json_fmt_signed(prot64, pay64, dig64)) == NULL) {
 450+	if ((sig64 = base64buf_url(sig, sigsz)) == NULL) {
 451+		warnx("base64buf_url");
 452+		goto out;
 453+	}
 454+	if ((fin = json_fmt_signed(prot64, pay64, sig64)) == NULL) {
 455 		warnx("json_fmt_signed");
 456 		goto out;
 457 	} else if (writestr(fd, COMM_REQ, fin) < 0)
 458@@ -429,8 +326,6 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
 459 
 460 	rc = 1;
 461 out:
 462-	ECDSA_SIG_free(ec_sig);
 463-	EVP_MD_CTX_free(ctx);
 464 	free(pay);
 465 	free(sign);
 466 	free(pay64);
 467@@ -440,15 +335,14 @@ out:
 468 	free(kid);
 469 	free(prot);
 470 	free(prot64);
 471-	free(dig);
 472-	free(dig64);
 473+	free(sig);
 474+	free(sig64);
 475 	free(fin);
 476-	free(buf);
 477 	return rc;
 478 }
 479 
 480 static int
 481-op_eab(int fd, EVP_PKEY *pkey, const char *eab_kid,
 482+op_eab(int fd, struct key *pkey, const char *eab_kid,
 483     const unsigned char *eab_key, int eab_key_len)
 484 {
 485 	char			*url = NULL;
 486@@ -456,9 +350,11 @@ op_eab(int fd, EVP_PKEY *pkey, const char *eab_kid,
 487 	char			*jwk = NULL, *pay64 = NULL;
 488 	char			*sign = NULL;
 489 	char			*dig64 = NULL, *fin = NULL;
 490-	unsigned char		dig[EVP_MAX_MD_SIZE];
 491+	unsigned char		dig[64];
 492 	unsigned int		digsz;
 493 	int			sign_len, rc = 0;
 494+	br_hmac_key_context	kc;
 495+	br_hmac_context		hc;
 496 
 497 	if ((url = readstr(fd, COMM_URL)) == NULL)
 498 		goto out;
 499@@ -475,17 +371,17 @@ op_eab(int fd, EVP_PKEY *pkey, const char *eab_kid,
 500 	}
 501 
 502 	/* payload component: account public key */
 503-	switch (EVP_PKEY_base_id(pkey)) {
 504-	case EVP_PKEY_RSA:
 505+	switch (pkey->type) {
 506+	case BR_KEYTYPE_RSA:
 507 		if (!op_sign_rsa(&jwk, pkey))
 508 			goto out;
 509 		break;
 510-	case EVP_PKEY_EC:
 511+	case BR_KEYTYPE_EC:
 512 		if (!op_sign_ec(&jwk, pkey))
 513 			goto out;
 514 		break;
 515 	default:
 516-		warnx("EVP_PKEY_base_id");
 517+		warnx("unknown key type");
 518 		goto out;
 519 	}
 520 
 521@@ -502,11 +398,10 @@ op_eab(int fd, EVP_PKEY *pkey, const char *eab_kid,
 522 	}
 523 	
 524 	/* sign with the EAB key */
 525-	if (HMAC(EVP_sha256(), eab_key, eab_key_len, sign, sign_len, dig,
 526-	    &digsz) == NULL) {
 527-		warnx("HMAC");
 528-		goto out;
 529-	}
 530+	br_hmac_key_init(&kc, &br_sha256_vtable, eab_key, eab_key_len);
 531+	br_hmac_init(&hc, &kc, 0);
 532+	br_hmac_update(&hc, sign, sign_len);
 533+	digsz = br_hmac_out(&hc, dig);
 534 
 535 	if ((dig64 = base64buf_url((char *)dig, digsz)) == NULL) {
 536 		warnx("base64buf_url");
 537@@ -539,7 +434,7 @@ acctproc(int netsock, const char *acctkey, enum keytype keytype,
 538     const char *eab_kid, const unsigned char *eab_key, int eab_key_len)
 539 {
 540 	FILE		*f = NULL;
 541-	EVP_PKEY	*pkey = NULL;
 542+	struct key	*pkey = NULL;
 543 	long		 lval;
 544 	enum acctop	 op;
 545 	int		 rc = 0, cc, newacct = 0;
 546@@ -565,8 +460,6 @@ acctproc(int netsock, const char *acctkey, enum keytype keytype,
 547 
 548 	/* File-system, user, and sandbox jailing. */
 549 
 550-	ERR_load_crypto_strings();
 551-
 552 	if (pledge("stdio", NULL) == -1) {
 553 		warn("pledge");
 554 		goto out;
 555@@ -650,8 +543,7 @@ out:
 556 	close(netsock);
 557 	if (f != NULL)
 558 		fclose(f);
 559-	EVP_PKEY_free(pkey);
 560-	ERR_print_errors_fp(stderr);
 561-	ERR_free_strings();
 562+	if (pkey != NULL)
 563+		freezero(pkey, sizeof(*pkey) + pkey->datasz);
 564 	return rc;
 565 }
 566diff --git a/usr.sbin/acme-client/certproc.c b/usr.sbin/acme-client/certproc.c
 567index f443d573675..85c3897a4b8 100644
 568--- a/usr.sbin/acme-client/certproc.c
 569+++ b/usr.sbin/acme-client/certproc.c
 570@@ -21,11 +21,6 @@
 571 #include <string.h>
 572 #include <unistd.h>
 573 
 574-#include <openssl/pem.h>
 575-#include <openssl/x509.h>
 576-#include <openssl/x509v3.h>
 577-#include <openssl/err.h>
 578-
 579 #include "extern.h"
 580 
 581 #define BEGIN_MARKER "-----BEGIN CERTIFICATE-----"
 582diff --git a/usr.sbin/acme-client/key.c b/usr.sbin/acme-client/key.c
 583index 9ece3059d4e..9599a7fdbd5 100644
 584--- a/usr.sbin/acme-client/key.c
 585+++ b/usr.sbin/acme-client/key.c
 586@@ -17,14 +17,11 @@
 587  */
 588 
 589 #include <err.h>
 590+#include <stdio.h>
 591 #include <stdlib.h>
 592 #include <unistd.h>
 593 
 594-#include <openssl/evp.h>
 595-#include <openssl/pem.h>
 596-#include <openssl/rsa.h>
 597-#include <openssl/ec.h>
 598-#include <openssl/obj_mac.h>
 599+#include <bearssl.h>
 600 
 601 #include "key.h"
 602 
 603@@ -33,102 +30,320 @@
 604  */
 605 #define	KBITS 4096
 606 
 607+static void
 608+prng_init(const br_prng_class **ctx, const void *params, const void *seed, size_t len)
 609+{
 610+}
 611+
 612+static void
 613+prng_generate(const br_prng_class **ctx, void *out, size_t len)
 614+{
 615+	arc4random_buf(out, len);
 616+}
 617+
 618+static void
 619+prng_update(const br_prng_class **ctx, const void *seed, size_t len)
 620+{
 621+}
 622+
 623+static const br_prng_class prng_class = {
 624+	0, prng_init, prng_generate, prng_update
 625+}, *prng = &prng_class;
 626+
 627 /*
 628  * Create an RSA key with the default KBITS number of bits.
 629  */
 630-EVP_PKEY *
 631+struct key *
 632 rsa_key_create(FILE *f, const char *fname)
 633 {
 634-	EVP_PKEY_CTX	*ctx = NULL;
 635-	EVP_PKEY	*pkey = NULL;
 636+	struct key	*key = NULL;
 637+	size_t		 slen, plen;
 638+	unsigned char	*sbuf, *pbuf;
 639+	unsigned char	 d[KBITS / 8];
 640+	unsigned char	*der = NULL, *pem = NULL;
 641+	size_t		 derlen, pemlen;
 642 
 643-	if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) {
 644-		warnx("EVP_PKEY_CTX_new_id");
 645-		goto err;
 646-	}
 647-	if (EVP_PKEY_keygen_init(ctx) <= 0) {
 648-		warnx("EVP_PKEY_keygen_init");
 649+	slen = BR_RSA_KBUF_PRIV_SIZE(KBITS);
 650+	plen = BR_RSA_KBUF_PUB_SIZE(KBITS);
 651+	if ((key = malloc(sizeof(*key) + slen + plen)) == NULL) {
 652+		warnx("malloc");
 653 		goto err;
 654 	}
 655-	if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KBITS) <= 0) {
 656-		warnx("EVP_PKEY_set_rsa_keygen_bits");
 657+	key->type = BR_KEYTYPE_RSA;
 658+	key->datasz = slen + plen;
 659+	sbuf = key->data;
 660+	pbuf = key->data + slen;
 661+	if (!br_rsa_keygen_get_default()(&prng, &key->rsa.sk, sbuf,
 662+	    &key->rsa.pk, pbuf, KBITS, 0x10001)) {
 663+		warnx("br_rsa_keygen");
 664 		goto err;
 665 	}
 666-	if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
 667-		warnx("EVP_PKEY_keygen");
 668+
 669+	/* Compute the private exponent. */
 670+
 671+	if (!br_rsa_compute_privexp_get_default()(d, &key->rsa.sk, 0x10001)) {
 672+		warnx("br_rsa_compute_modulus");
 673 		goto err;
 674 	}
 675 
 676-	/* Serialise the key to the disc. */
 677+	/* Serialise the key to the disk. */
 678 
 679-	if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
 680-		warnx("%s: PEM_write_PrivateKey", fname);
 681+	derlen = br_encode_rsa_raw_der(NULL, &key->rsa.sk, &key->rsa.pk,
 682+	    d, sizeof(d));
 683+	if ((der = malloc(derlen)) == NULL) {
 684+		warn("malloc");
 685+		goto err;
 686+	}
 687+	br_encode_rsa_raw_der(der, &key->rsa.sk, &key->rsa.pk, d, sizeof(d));
 688+	pemlen = br_pem_encode(NULL, der, derlen, BR_ENCODE_PEM_RSA_RAW, 0);
 689+	if ((pem = malloc(pemlen + 1)) == NULL) {
 690+		warn("malloc");
 691+		goto err;
 692+	}
 693+	br_pem_encode(pem, der, derlen, BR_ENCODE_PEM_RSA_RAW, 0);
 694+	if (fwrite(pem, 1, pemlen, f) != pemlen) {
 695+		warn("write private key");
 696 		goto err;
 697 	}
 698 
 699-	EVP_PKEY_CTX_free(ctx);
 700-	return pkey;
 701+	free(der);
 702+	free(pem);
 703+	return key;
 704 
 705 err:
 706-	EVP_PKEY_free(pkey);
 707-	EVP_PKEY_CTX_free(ctx);
 708+	free(der);
 709+	free(pem);
 710+	free(key);
 711 	return NULL;
 712 }
 713 
 714-EVP_PKEY *
 715+struct key *
 716 ec_key_create(FILE *f, const char *fname)
 717 {
 718-	EVP_PKEY_CTX	*ctx = NULL;
 719-	EVP_PKEY	*pkey = NULL;
 720+	struct key 		*key = NULL;
 721+	const br_ec_impl	*ec;
 722+	size_t			 slen, plen;
 723+	unsigned char		*sbuf, *pbuf;
 724+	unsigned char		*der = NULL, *pem = NULL;
 725+	size_t			 derlen, pemlen;
 726 
 727-	if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) {
 728-		warnx("EVP_PKEY_CTX_new_id");
 729-		goto err;
 730-	}
 731-	if (EVP_PKEY_keygen_init(ctx) <= 0) {
 732-		warnx("EVP_PKEY_keygen_init");
 733+	slen = BR_EC_KBUF_PRIV_MAX_SIZE;
 734+	plen = BR_EC_KBUF_PUB_MAX_SIZE;
 735+	if ((key = malloc(sizeof(*key) + slen + plen)) == NULL) {
 736+		warn("malloc");
 737 		goto err;
 738 	}
 739-	if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_secp384r1) <= 0) {
 740-		warnx("EVP_PKEY_CTX_set_ec_paramgen_curve_nid");
 741+	key->type = BR_KEYTYPE_EC;
 742+	key->datasz = slen + plen;
 743+	sbuf = key->data;
 744+	pbuf = key->data + slen;
 745+
 746+	ec = br_ec_get_default();
 747+	if (br_ec_keygen(&prng, ec, &key->ec.sk, sbuf, BR_EC_secp384r1) == 0) {
 748+		warnx("br_ec_keygen");
 749 		goto err;
 750 	}
 751-	if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
 752-		warnx("EVP_PKEY_keygen");
 753+	if (br_ec_compute_pub(ec, &key->ec.pk, pbuf, &key->ec.sk) == 0) {
 754+		warnx("br_ec_compute_pub");
 755 		goto err;
 756 	}
 757 
 758-	/* Serialise the key to the disc. */
 759+	/* Serialise the key to the disk in EC format */
 760 
 761-	if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
 762-		warnx("%s: PEM_write_PrivateKey", fname);
 763+	if ((derlen = br_encode_ec_raw_der(NULL, &key->ec.sk,
 764+	    &key->ec.pk)) == 0) {
 765+		warnx("br_encode_ec_raw_der");
 766+		goto err;
 767+	}
 768+	if ((der = malloc(derlen)) == NULL) {
 769+		warn("malloc");
 770+		goto err;
 771+	}
 772+	br_encode_ec_raw_der(der, &key->ec.sk, &key->ec.pk);
 773+	pemlen = br_pem_encode(NULL, der, derlen, BR_ENCODE_PEM_EC_RAW, 0);
 774+	if ((pem = malloc(pemlen + 1)) == NULL) {
 775+		warn("malloc");
 776+		goto err;
 777+	}
 778+	br_pem_encode(pem, der, derlen, BR_ENCODE_PEM_EC_RAW, 0);
 779+	if (fwrite(pem, 1, pemlen, f) != pemlen) {
 780+		warn("write private key");
 781 		goto err;
 782 	}
 783 
 784-	EVP_PKEY_CTX_free(ctx);
 785-	return pkey;
 786+	free(der);
 787+	free(pem);
 788+	return key;
 789 
 790 err:
 791-	EVP_PKEY_free(pkey);
 792-	EVP_PKEY_CTX_free(ctx);
 793+	free(der);
 794+	free(pem);
 795+	free(key);
 796 	return NULL;
 797 }
 798 
 799-EVP_PKEY *
 800+static void
 801+append_skey(void *ctx, const void *src, size_t len)
 802+{
 803+	br_skey_decoder_push(ctx, src, len);
 804+}
 805+
 806+struct key *
 807 key_load(FILE *f, const char *fname)
 808 {
 809-	EVP_PKEY	*pkey;
 810+	struct key			*key = NULL;
 811+	size_t				 datasz, len = 0, n;
 812+	int				 type = 0, err;
 813+	unsigned char			 buf[8192], *pos;
 814+	br_pem_decoder_context		 pemctx;
 815+	br_skey_decoder_context		 keyctx;
 816+	br_rsa_compute_modulus		 compute_modulus;
 817+	br_rsa_compute_pubexp		 compute_pubexp;
 818+	const br_ec_impl		*ecimpl;
 819+	const br_rsa_private_key	*rsa;
 820+	const br_ec_private_key		*ec;
 821+	const char			*name = NULL;
 822+	uint32_t			 pubexp;
 823 
 824-	pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL);
 825-	if (pkey == NULL) {
 826-		warnx("%s: PEM_read_PrivateKey", fname);
 827-		return NULL;
 828+	br_pem_decoder_init(&pemctx);
 829+	br_skey_decoder_init(&keyctx);
 830+	while (type == 0) {
 831+		if (len == 0) {
 832+			if (feof(f)) {
 833+				warnx("%s: missing private key", fname);
 834+				break;
 835+			}
 836+			len = fread(buf, 1, sizeof(buf), f);
 837+			if (ferror(f)) {
 838+				warn("%s: read", fname);
 839+				goto err;
 840+			}
 841+			pos = buf;
 842+		}
 843+		n = br_pem_decoder_push(&pemctx, pos, len);
 844+		pos += n;
 845+		len -= n;
 846+		switch (br_pem_decoder_event(&pemctx)) {
 847+		case BR_PEM_BEGIN_OBJ:
 848+			name = br_pem_decoder_name(&pemctx);
 849+			if (strcmp(name, BR_ENCODE_PEM_PKCS8) != 0 &&
 850+			    strcmp(name, BR_ENCODE_PEM_RSA_RAW) != 0 &&
 851+			    strcmp(name, BR_ENCODE_PEM_EC_RAW) != 0) {
 852+				name = NULL;
 853+				break;
 854+			}
 855+			br_pem_decoder_setdest(&pemctx, append_skey, &keyctx);
 856+			break;
 857+		case BR_PEM_END_OBJ:
 858+			if (name == NULL)
 859+				break;
 860+			if ((err = br_skey_decoder_last_error(&keyctx)) != 0) {
 861+				warnx("%s: br_skey_decoder: %d", fname, err);
 862+				goto err;
 863+			}
 864+			type = br_skey_decoder_key_type(&keyctx);
 865+			break;
 866+		case 0:
 867+			break;
 868+		default:
 869+			warnx("%s: PEM decoding failed", fname);
 870+			goto err;
 871+		}
 872 	}
 873-	if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA ||
 874-	    EVP_PKEY_base_id(pkey) == EVP_PKEY_EC)
 875-		return pkey;
 876 
 877-	warnx("%s: unsupported key type", fname);
 878-	EVP_PKEY_free(pkey);
 879-	return NULL;
 880+	switch (type) {
 881+	case BR_KEYTYPE_RSA:
 882+		rsa = br_skey_decoder_get_rsa(&keyctx);
 883+		compute_modulus = br_rsa_compute_modulus_get_default();
 884+		compute_pubexp = br_rsa_compute_pubexp_get_default();
 885+
 886+		/* Compute public modulus size. This will fail if
 887+		 * p or q is not 3 mod 4. */
 888+		if ((datasz = compute_modulus(NULL, rsa)) == 0) {
 889+			warnx("%s: br_rsa_compute_modulus", fname);
 890+			goto err;
 891+		}
 892+		datasz += 4 + rsa->plen + rsa->qlen + rsa->dplen + rsa->dqlen +
 893+		    rsa->iqlen;
 894+
 895+		if ((key = malloc(sizeof(*key) + datasz)) == NULL) {
 896+			warn("malloc");
 897+			goto err;
 898+		}
 899+		key->type = BR_KEYTYPE_RSA;
 900+		key->datasz = datasz;
 901+
 902+		if ((pubexp = compute_pubexp(rsa)) == 0) {
 903+			warnx("%s: br_rsa_compute_pubexp", fname);
 904+			goto err;
 905+		}
 906+
 907+		/* Copy private key. */
 908+		key->rsa.sk.n_bitlen = rsa->n_bitlen;
 909+		key->rsa.sk.p = key->data;
 910+		key->rsa.sk.plen = rsa->plen;
 911+		key->rsa.sk.q = key->rsa.sk.p + rsa->plen;
 912+		key->rsa.sk.qlen = rsa->qlen;
 913+		key->rsa.sk.dp = key->rsa.sk.q + rsa->qlen;
 914+		key->rsa.sk.dplen = rsa->dplen;
 915+		key->rsa.sk.dq = key->rsa.sk.dp + rsa->dplen;
 916+		key->rsa.sk.dqlen = rsa->dqlen;
 917+		key->rsa.sk.iq = key->rsa.sk.dq + rsa->dqlen;
 918+		key->rsa.sk.iqlen = rsa->iqlen;
 919+		memcpy(key->rsa.sk.p, rsa->p, rsa->plen);
 920+		memcpy(key->rsa.sk.q, rsa->q, rsa->qlen);
 921+		memcpy(key->rsa.sk.dp, rsa->dp, rsa->dplen);
 922+		memcpy(key->rsa.sk.dq, rsa->dq, rsa->dqlen);
 923+		memcpy(key->rsa.sk.iq, rsa->iq, rsa->iqlen);
 924+
 925+		/* Compute public modulus and encode public exponent. */
 926+		key->rsa.pk.n = key->rsa.sk.iq + rsa->iqlen;
 927+		key->rsa.pk.nlen = compute_modulus(key->rsa.pk.n, rsa);
 928+		key->rsa.pk.elen = 4;
 929+		key->rsa.pk.e = key->rsa.pk.n + key->rsa.pk.nlen;
 930+		key->rsa.pk.e[0] = pubexp >> 24;
 931+		key->rsa.pk.e[1] = pubexp >> 16;
 932+		key->rsa.pk.e[2] = pubexp >> 8;
 933+		key->rsa.pk.e[3] = pubexp;
 934+
 935+		/* Trim leading zeros. */
 936+		while (key->rsa.pk.elen > 0 && key->rsa.pk.e[0] == 0) {
 937+			--key->rsa.pk.elen;
 938+			++key->rsa.pk.e;
 939+		}
 940+		goto out;
 941+	case BR_KEYTYPE_EC:
 942+		ec = br_skey_decoder_get_ec(&keyctx);
 943+		ecimpl = br_ec_get_default();
 944+		if ((datasz = br_ec_compute_pub(ecimpl, NULL, NULL, ec)) == 0) {
 945+			warnx("%s: br_ec_compute_pub", fname);
 946+			goto err;
 947+		}
 948+		datasz += ec->xlen;
 949+
 950+		if ((key = malloc(sizeof(*key) + datasz)) == NULL) {
 951+			warn("malloc");
 952+			goto err;
 953+		}
 954+		key->type = BR_KEYTYPE_EC;
 955+		key->datasz = datasz;
 956+
 957+		key->ec.sk.curve = ec->curve;
 958+		key->ec.sk.x = key->data;
 959+		key->ec.sk.xlen = ec->xlen;
 960+		memcpy(key->ec.sk.x, ec->x, ec->xlen);
 961+		br_ec_compute_pub(ecimpl, &key->ec.pk,
 962+		    key->ec.sk.x + key->ec.sk.xlen, &key->ec.sk);
 963+		goto out;
 964+	}
 965+
 966+	warnx("%s: missing private key", fname);
 967+
 968+err:
 969+	free(key);
 970+	key = NULL;
 971+out:
 972+	explicit_bzero(&pemctx, sizeof(pemctx));
 973+	explicit_bzero(&keyctx, sizeof(keyctx));
 974+	return key;
 975 }
 976diff --git a/usr.sbin/acme-client/key.h b/usr.sbin/acme-client/key.h
 977index 272d36eb09a..12abdec813c 100644
 978--- a/usr.sbin/acme-client/key.h
 979+++ b/usr.sbin/acme-client/key.h
 980@@ -18,8 +18,24 @@
 981 #ifndef KEY_H
 982 #define KEY_H
 983 
 984-EVP_PKEY	*rsa_key_create(FILE *, const char *);
 985-EVP_PKEY	*ec_key_create(FILE *, const char *);
 986-EVP_PKEY	*key_load(FILE *, const char *);
 987+struct key {
 988+	int type;
 989+	union {
 990+		struct {
 991+			br_rsa_public_key pk;
 992+			br_rsa_private_key sk;
 993+		} rsa;
 994+		struct {
 995+			br_ec_public_key pk;
 996+			br_ec_private_key sk;
 997+		} ec;
 998+	};
 999+	size_t datasz;
1000+	unsigned char data[];
1001+};
1002+
1003+struct key	*rsa_key_create(FILE *, const char *);
1004+struct key	*ec_key_create(FILE *, const char *);
1005+struct key	*key_load(FILE *, const char *);
1006 
1007 #endif /* ! KEY_H */
1008diff --git a/usr.sbin/acme-client/keyproc.c b/usr.sbin/acme-client/keyproc.c
1009index 4360156b9c0..19b8077a8fb 100644
1010--- a/usr.sbin/acme-client/keyproc.c
1011+++ b/usr.sbin/acme-client/keyproc.c
1012@@ -18,55 +18,18 @@
1013 #include <sys/stat.h>
1014 
1015 #include <err.h>
1016+#include <errno.h>
1017 #include <stdio.h>
1018 #include <stdlib.h>
1019 #include <string.h>
1020 #include <unistd.h>
1021 
1022-#include <openssl/pem.h>
1023-#include <openssl/err.h>
1024-#include <openssl/rand.h>
1025-#include <openssl/x509.h>
1026-#include <openssl/x509v3.h>
1027+#include <bearssl.h>
1028+#include <x509cert.h>
1029 
1030 #include "extern.h"
1031 #include "key.h"
1032 
1033-/*
1034- * This was lifted more or less directly from demos/x509/mkreq.c of the
1035- * OpenSSL source code.
1036- */
1037-static int
1038-add_ext(STACK_OF(X509_EXTENSION) *sk, int nid, const char *value)
1039-{
1040-	X509_EXTENSION	*ex;
1041-	char		*cp;
1042-
1043-	/*
1044-	 * XXX: I don't like this at all.
1045-	 * There's no documentation for X509V3_EXT_conf_nid, so I'm not
1046-	 * sure if the "value" parameter is ever written to, touched,
1047-	 * etc.
1048-	 * The 'official' examples suggest not (they use a string
1049-	 * literal as the input), but to be safe, I'm doing an
1050-	 * allocation here and just letting it go.
1051-	 * This leaks memory, but bounded to the number of SANs.
1052-	 */
1053-
1054-	if ((cp = strdup(value)) == NULL) {
1055-		warn("strdup");
1056-		return (0);
1057-	}
1058-	ex = X509V3_EXT_conf_nid(NULL, NULL, nid, cp);
1059-	if (ex == NULL) {
1060-		warnx("X509V3_EXT_conf_nid");
1061-		free(cp);
1062-		return (0);
1063-	}
1064-	sk_X509_EXTENSION_push(sk, ex);
1065-	return (1);
1066-}
1067-
1068 /*
1069  * Create an X509 certificate from the private key we have on file.
1070  * To do this, we first open the key file, then jail ourselves.
1071@@ -76,19 +39,20 @@ add_ext(STACK_OF(X509_EXTENSION) *sk, int nid, const char *value)
1072 int
1073 keyproc(int netsock, struct domain_c *domain)
1074 {
1075-	char		*der64 = NULL;
1076-	unsigned char	*der = NULL, *dercp;
1077-	char		*sans = NULL, *san = NULL;
1078-	FILE		*f;
1079-	size_t		 sansz;
1080-	void		*pp;
1081-	EVP_PKEY	*pkey = NULL;
1082-	X509_REQ	*x = NULL;
1083-	int		 len, rc = 0, cc, nid, newkey = 0, first;
1084-	mode_t		 prev;
1085-	STACK_OF(X509_EXTENSION) *exts = NULL;
1086-	struct altname_c	 *ac;
1087-	const char	*keyfile = domain->key;
1088+	char			*der64 = NULL;
1089+	unsigned char		*der = NULL;
1090+	FILE			*f;
1091+	struct key		*pkey = NULL;
1092+	struct x509cert_req	 req;
1093+	struct x509cert_skey	 skey;
1094+	struct x509cert_dn	 dn;
1095+	struct x509cert_item	 item;
1096+	int			 len, rc = 0, newkey = 0, i;
1097+	mode_t			 prev;
1098+	struct altname_c	*ac;
1099+	const char		*keyfile = domain->key;
1100+
1101+	req.alts = NULL;
1102 
1103 	/*
1104 	 * First, open our private key file read-only or write-only if
1105@@ -110,8 +74,6 @@ keyproc(int netsock, struct domain_c *domain)
1106 
1107 	/* File-system, user, and sandbox jail. */
1108 
1109-	ERR_load_crypto_strings();
1110-
1111 	if (pledge("stdio", NULL) == -1) {
1112 		warn("pledge");
1113 		goto out;
1114@@ -145,98 +107,65 @@ keyproc(int netsock, struct domain_c *domain)
1115 	 * Then set it as the X509 requester's key.
1116 	 */
1117 
1118-	if ((x = X509_REQ_new()) == NULL) {
1119-		warnx("X509_REQ_new");
1120-		goto out;
1121-	} else if (!X509_REQ_set_version(x, 0)) {
1122-		warnx("X509_REQ_set_version");
1123-		goto out;
1124-	} else if (!X509_REQ_set_pubkey(x, pkey)) {
1125-		warnx("X509_REQ_set_pubkey");
1126-		goto out;
1127+	req.pkey.key_type = pkey->type;
1128+	skey.type = pkey->type;
1129+	switch (pkey->type) {
1130+	case BR_KEYTYPE_RSA:
1131+		req.pkey.key.rsa = pkey->rsa.pk;
1132+		skey.u.rsa = &pkey->rsa.sk;
1133+		break;
1134+	case BR_KEYTYPE_EC:
1135+		req.pkey.key.ec = pkey->ec.pk;
1136+		skey.u.ec = &pkey->ec.sk;
1137+		break;
1138 	}
1139 
1140-	/*
1141-	 * Now add the SAN extensions.
1142-	 * This was lifted more or less directly from demos/x509/mkreq.c
1143-	 * of the OpenSSL source code.
1144-	 * (The zeroth altname is the domain name.)
1145-	 * TODO: is this the best way of doing this?
1146-	 */
1147+	/* Use an empty subject. */
1148 
1149-	nid = NID_subject_alt_name;
1150-	if ((exts = sk_X509_EXTENSION_new_null()) == NULL) {
1151-		warnx("sk_X509_EXTENSION_new_null");
1152-		goto out;
1153-	}
1154-	/* Initialise to empty string. */
1155-	if ((sans = strdup("")) == NULL) {
1156-		warn("strdup");
1157+	dn.rdn = NULL;
1158+	dn.rdn_len = 0;
1159+	req.subject.enc = x509cert_dn_encoder;
1160+	req.subject.val = &dn;
1161+
1162+	/* Now add the SAN extension. */
1163+
1164+	req.alts_len = domain->altname_count;
1165+	req.alts = calloc(domain->altname_count, sizeof(req.alts[0]));
1166+	if (req.alts == NULL) {
1167+		warn("calloc");
1168 		goto out;
1169 	}
1170-	sansz = strlen(sans) + 1;
1171 
1172-	/*
1173-	 * For each SAN entry, append it to the string.
1174-	 * We need a single SAN entry for all of the SAN
1175-	 * domains: NOT an entry per domain!
1176-	 */
1177+	/* Add a dNSName SAN entry for each alternate name. */
1178 
1179-	first = 1;
1180+	i = 0;
1181 	TAILQ_FOREACH(ac, &domain->altname_list, entry) {
1182 		switch (ac->idtype) {
1183 		case ID_DNS:
1184-			cc = asprintf(&san, "%sDNS:%s", first ? "" : ",",
1185-			    ac->domain);
1186+			req.alts[i].tag = X509CERT_SAN_DNSNAME;
1187+			req.alts[i].val = ac->domain;
1188+			req.alts[i].len = strlen(ac->domain);
1189 			break;
1190 		case ID_IP:
1191-			cc = asprintf(&san, "%sIP:%s", first ? "" : ",",
1192-			    ac->domain);
1193-			break;
1194-		}
1195-		first = 0;
1196-		if (cc == -1) {
1197-			warn("asprintf");
1198-			goto out;
1199-		}
1200-		pp = recallocarray(sans, sansz, sansz + strlen(san), 1);
1201-		if (pp == NULL) {
1202-			warn("recallocarray");
1203+			warnx("ID_IP is not supported");
1204 			goto out;
1205 		}
1206-		sans = pp;
1207-		sansz += strlen(san);
1208-		strlcat(sans, san, sansz);
1209-		free(san);
1210-		san = NULL;
1211-	}
1212-
1213-	if (!add_ext(exts, nid, sans)) {
1214-		warnx("add_ext");
1215-		goto out;
1216-	} else if (!X509_REQ_add_extensions(x, exts)) {
1217-		warnx("X509_REQ_add_extensions");
1218-		goto out;
1219-	}
1220-	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1221-
1222-	/* Sign the X509 request using SHA256. */
1223-
1224-	if (!X509_REQ_sign(x, pkey, EVP_sha256())) {
1225-		warnx("X509_sign");
1226-		goto out;
1227+		i++;
1228 	}
1229 
1230-	/* Now, serialise to DER, then base64. */
1231+	/* Sign the X.509 request using SHA256, and serialise to
1232+	 * DER then base64. */
1233 
1234-	if ((len = i2d_X509_REQ(x, NULL)) < 0) {
1235-		warnx("i2d_X509_REQ");
1236+	item.enc = x509cert_req_encoder;
1237+	item.val = &req;
1238+	if ((len = x509cert_sign(&item, &skey, &br_sha256_vtable, NULL)) == 0) {
1239+		warnx("x509cert_sign");
1240 		goto out;
1241-	} else if ((der = dercp = malloc(len)) == NULL) {
1242+	} else if ((der = malloc(len)) == NULL) {
1243 		warn("malloc");
1244 		goto out;
1245-	} else if (len != i2d_X509_REQ(x, &dercp)) {
1246-		warnx("i2d_X509_REQ");
1247+	} else if ((len = x509cert_sign(&item, &skey, &br_sha256_vtable, der)) == 0) {
1248+		warnx("x509cert_sign");
1249 		goto out;
1250 	} else if ((der64 = base64buf_url(der, len)) == NULL) {
1251 		warnx("base64buf_url");
1252@@ -261,11 +190,8 @@ out:
1253 		fclose(f);
1254 	free(der);
1255 	free(der64);
1256-	free(sans);
1257-	free(san);
1258-	X509_REQ_free(x);
1259-	EVP_PKEY_free(pkey);
1260-	ERR_print_errors_fp(stderr);
1261-	ERR_free_strings();
1262+	free(req.alts);
1263+	if (pkey != NULL)
1264+		freezero(pkey, pkey->datasz);
1265 	return rc;
1266 }
1267diff --git a/usr.sbin/acme-client/revokeproc.c b/usr.sbin/acme-client/revokeproc.c
1268index 081a68786f2..785d8aea346 100644
1269--- a/usr.sbin/acme-client/revokeproc.c
1270+++ b/usr.sbin/acme-client/revokeproc.c
1271@@ -15,8 +15,6 @@
1272  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1273  */
1274 
1275-#include <sys/socket.h>
1276-#include <arpa/inet.h>
1277 #include <assert.h>
1278 #include <ctype.h>
1279 #include <err.h>
1280@@ -24,79 +22,54 @@
1281 #include <stdio.h>
1282 #include <stdlib.h>
1283 #include <string.h>
1284+#include <time.h>
1285 #include <unistd.h>
1286 #include <vis.h>
1287 
1288-#include <openssl/pem.h>
1289-#include <openssl/x509.h>
1290-#include <openssl/x509v3.h>
1291-#include <openssl/err.h>
1292+#include <bearssl.h>
1293 
1294 #include "extern.h"
1295 
1296-/*
1297- * Convert the X509's notAfter time into a time_t value.
1298- */
1299-static int
1300-X509notafter(const X509 *x, time_t *notafter)
1301-{
1302-	const ASN1_TIME	*atim;
1303-	struct tm	 t;
1304-
1305-	if ((atim = X509_get0_notAfter(x)) == NULL)
1306-		return -1;
1307-
1308-	memset(&t, 0, sizeof(t));
1309-
1310-	if (!ASN1_TIME_to_tm(atim, &t))
1311-		return -1;
1312-
1313-	t.tm_wday = -1;		/* sentinel for error */
1314-	if ((*notafter = timegm(&t)) == -1 && t.tm_wday == -1)
1315-		return -1;
1316-
1317-	return 0;
1318-}
1319-
1320-/*
1321- * Convert the X509's notBefore time into a time_t value.
1322- */
1323-static int
1324-X509notbefore(const X509 *x, time_t *notbefore)
1325+static void
1326+append_cert(void *ctx, const void *buf, size_t len)
1327 {
1328-	const ASN1_TIME	*atim;
1329-	struct tm	 t;
1330-
1331-	if ((atim = X509_get0_notBefore(x)) == NULL)
1332-		return -1;
1333-
1334-	memset(&t, 0, sizeof(t));
1335-
1336-	if (!ASN1_TIME_to_tm(atim, &t))
1337-		return -1;
1338-
1339-	t.tm_wday = -1;		/* sentinel for error */
1340-	if ((*notbefore = timegm(&t)) == -1 && t.tm_wday == -1)
1341-		return -1;
1342-
1343-	return 0;
1344+	br_x509_certificate *cert = ctx;
1345+	size_t newlen;
1346+	unsigned char *newdata;
1347+
1348+	if (cert->data_len == -1)
1349+		return;
1350+	newlen = cert->data_len + len;
1351+	if ((newdata = realloc(cert->data, newlen)) != NULL) {
1352+		memcpy(newdata + cert->data_len, buf, len);
1353+		cert->data = newdata;
1354+		cert->data_len = newlen;
1355+	} else {
1356+		warn("realloc");
1357+		cert->data_len = -1;
1358+	}
1359 }
1360 
1361 int
1362 revokeproc(int fd, const char *certfile, int force,
1363     int revocate, struct domain_c *domain)
1364 {
1365-	GENERAL_NAMES			*sans = NULL;
1366-	unsigned char			*der = NULL, *dercp;
1367-	char				*der64 = NULL;
1368-	int				 rc = 0, cc, sanidx, len, j, k;
1369-	int				*found_altnames = NULL;
1370+	static const unsigned char	 dnsname[] = {0, 2};
1371+	char				 buf[8192], *pos, *sans = NULL, *der64 = NULL;
1372+	int				 rc = 0, cc, i, eltsz, state, err;
1373+	size_t				 n, len = 0, altlen, altmax;
1374 	FILE				*f = NULL;
1375-	X509				*x = NULL;
1376+	br_pem_decoder_context		 pc;
1377+	br_x509_decoder_context		 xd;
1378+	br_x509_minimal_context		 xc;
1379+	br_x509_certificate		 cert = {0};
1380+	br_name_element			*elts = NULL;
1381+	uint32_t			 days, secs;
1382 	long				 lval;
1383 	enum revokeop			 op, rop;
1384 	time_t				 notafter, notbefore, cert_validity;
1385 	time_t				 remaining_validity, renew_allow;
1386+	struct altname_c		*ac;
1387 
1388 	/*
1389 	 * First try to open the certificate before we drop privileges
1390@@ -111,8 +84,6 @@ revokeproc(int fd, const char *certfile, int force,
1391 
1392 	/* File-system and sandbox jailing. */
1393 
1394-	ERR_load_crypto_strings();
1395-
1396 	if (pledge("stdio", NULL) == -1) {
1397 		warn("pledge");
1398 		goto out;
1399@@ -136,45 +107,89 @@ revokeproc(int fd, const char *certfile, int force,
1400 		goto out;
1401 	}
1402 
1403-	if ((x = PEM_read_X509(f, NULL, NULL, NULL)) == NULL) {
1404-		warnx("PEM_read_X509");
1405-		goto out;
1406+	br_pem_decoder_init(&pc);
1407+	for (state = 0; state != 2;) {
1408+		if (len == 0) {
1409+			if (feof(f)) {
1410+				warnx("%s: truncated certificate", certfile);
1411+				goto out;
1412+			}
1413+			len = fread(buf, 1, sizeof(buf), f);
1414+			if (ferror(f)) {
1415+				warn("fread");
1416+				goto out;
1417+			}
1418+			pos = buf;
1419+		}
1420+		n = br_pem_decoder_push(&pc, pos, len);
1421+		pos += n;
1422+		len -= n;
1423+		switch (br_pem_decoder_event(&pc)) {
1424+		case BR_PEM_BEGIN_OBJ:
1425+			if (strcmp(br_pem_decoder_name(&pc), "CERTIFICATE") == 0) {
1426+				br_pem_decoder_setdest(&pc, append_cert, &cert);
1427+				state = 1;
1428+			}
1429+			break;
1430+		case BR_PEM_END_OBJ:
1431+			if (state == 1)
1432+				state = 2;
1433+			break;
1434+		case 0:
1435+			break;
1436+		default:
1437+			warnx("%s: PEM decoding error", certfile);
1438+			goto out;
1439+		}
1440 	}
1441-
1442-	/* Cache and sanity check X509v3 extensions. */
1443-
1444-	if (X509_check_purpose(x, -1, -1) <= 0) {
1445-		warnx("%s: invalid X509v3 extensions", certfile);
1446+	if (cert.data_len == -1)
1447 		goto out;
1448-	}
1449 
1450 	/* Read out the expiration date. */
1451 
1452-	if (X509notafter(x, &notafter) == -1) {
1453-		warnx("X509notafter");
1454+	br_x509_decoder_init(&xd, NULL, NULL);
1455+	br_x509_decoder_push(&xd, cert.data, cert.data_len);
1456+	if ((err = br_x509_decoder_last_error(&xd)) != 0) {
1457+		warnx("%s: X.509 decoding error %d", certfile, err);
1458 		goto out;
1459 	}
1460-
1461-	if (X509notbefore(x, &notbefore) == -1) {
1462-		warnx("X509notbefore");
1463+	br_x509_decoder_get_notafter(&xd, &days, &secs);
1464+	notafter = 86400ll * (days - 719528) + 86400;
1465+	br_x509_decoder_get_notbefore(&xd, &days, &secs);
1466+	notbefore = 86400ll * (days - 719528) + 86400;
1467+
1468+	altmax = 0;
1469+	TAILQ_FOREACH(ac, &domain->altname_list, entry) {
1470+		altlen = strlen(ac->domain) + 1;
1471+		if (altlen > altmax)
1472+			altmax = altlen;
1473+	}
1474+	eltsz = domain->altname_count + 1;
1475+	if ((elts = calloc(eltsz, sizeof(elts[0]))) == NULL ||
1476+	    (sans = calloc(eltsz, altmax)) == NULL) {
1477+		warn("calloc");
1478 		goto out;
1479 	}
1480-
1481-	/* Extract list of SAN entries from the certificate. */
1482-
1483-	sans = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
1484-	if (sans == NULL) {
1485-		warnx("%s: does not have a SAN entry", certfile);
1486-		if (revocate)
1487-			goto out;
1488-		force = 2;
1489+	for (i = 0; i < eltsz; ++i) {
1490+		elts[i].oid = dnsname;
1491+		elts[i].buf = sans + i * altmax;
1492+		elts[i].len = altmax;
1493 	}
1494 
1495-	/* An array of buckets: the number of entries found. */
1496+	/* Extract list of SAN entries from the certificate. */
1497 
1498-	if ((found_altnames = (int *)calloc(domain->altname_count,
1499-	    sizeof(int))) == NULL) {
1500-		warn("calloc");
1501+	br_x509_minimal_init(&xc, &br_sha256_vtable, NULL, 0);
1502+	br_x509_minimal_set_hash(&xc, br_sha256_ID, &br_sha256_vtable);
1503+	br_x509_minimal_set_hash(&xc, br_sha384_ID, &br_sha384_vtable);
1504+	br_x509_minimal_set_hash(&xc, br_sha512_ID, &br_sha512_vtable);
1505+	br_x509_minimal_set_name_elements(&xc, elts, eltsz);
1506+	xc.vtable->start_chain(&xc.vtable, NULL);
1507+	xc.vtable->start_cert(&xc.vtable, cert.data_len);
1508+	xc.vtable->append(&xc.vtable, cert.data, cert.data_len);
1509+	xc.vtable->end_cert(&xc.vtable);
1510+	err = xc.vtable->end_chain(&xc.vtable);
1511+	if (err != BR_ERR_X509_NOT_TRUSTED && err != BR_ERR_X509_EXPIRED) {
1512+		warnx("%s: X.509 engine error %d", certfile, err);
1513 		goto out;
1514 	}
1515 
1516@@ -183,121 +198,37 @@ revokeproc(int fd, const char *certfile, int force,
1517 	 * configuration file and that all domains are represented only once.
1518 	 */
1519 
1520-	for (sanidx = 0; sanidx < sk_GENERAL_NAME_num(sans); sanidx++) {
1521-		GENERAL_NAME		*gen_name;
1522-		char			*name_buf = NULL;
1523-		int			 name_len;
1524-		struct altname_c	*ac;
1525-
1526-		gen_name = sk_GENERAL_NAME_value(sans, sanidx);
1527-		assert(gen_name != NULL);
1528-
1529-		if (gen_name->type == GEN_IPADD) {
1530-			char		 ip_buf[INET6_ADDRSTRLEN];
1531-			const char	*ip;
1532-
1533-			name_len = ASN1_STRING_length(gen_name->d.iPAddress);
1534-			switch (name_len) {
1535-			case 4:
1536-				ip = inet_ntop(AF_INET,
1537-				    ASN1_STRING_get0_data(gen_name->d.iPAddress),
1538-				    ip_buf, INET6_ADDRSTRLEN);
1539-				break;
1540-			case 16:
1541-				ip = inet_ntop(AF_INET6,
1542-				    ASN1_STRING_get0_data(gen_name->d.iPAddress),
1543-				    ip_buf, INET6_ADDRSTRLEN);
1544-				break;
1545-			default:
1546-				ip = NULL;
1547-				break;
1548-			}
1549-			if (ip == NULL) {
1550-				warnx("invalid IP address");
1551-				continue;
1552-			}
1553-			name_len = asprintf(&name_buf, "%s", ip);
1554-		} else if (gen_name->type == GEN_DNS) {
1555-			name_len = ASN1_STRING_length(gen_name->d.dNSName);
1556-			name_len = asprintf(&name_buf, "%.*s",
1557-			    name_len,
1558-			    ASN1_STRING_get0_data(gen_name->d.dNSName));
1559-		} else
1560-			continue;
1561-
1562-		if (name_len == -1) {
1563-			warn("asprintf");
1564-			continue;
1565-		}
1566-
1567-		j = 0;
1568-		TAILQ_FOREACH(ac, &domain->altname_list, entry) {
1569-			if (strcmp(name_buf, ac->domain) == 0) {
1570-				found_altnames[j]++;
1571+	TAILQ_FOREACH(ac, &domain->altname_list, entry) {
1572+		for (i = 0; i < eltsz; i++) {
1573+			if (elts[i].status == 1 &&
1574+			    strcmp(ac->domain, elts[i].buf) == 0) {
1575+				elts[i].status = 0;
1576 				break;
1577 			}
1578-			/* increment if didn't match */
1579-			j++;
1580-		}
1581-		if (j >= domain->altname_count) {
1582-			/* we haven't matched any */
1583-			if (revocate) {
1584-				char *visbuf;
1585-
1586-				visbuf = calloc(4, name_len + 1);
1587-				if (visbuf == NULL) {
1588-					warn("%s: unexpected SAN in "
1589-					    "certificate", certfile);
1590-					free(name_buf);
1591-					goto out;
1592-				}
1593-				strvisx(visbuf, name_buf, name_len, VIS_SAFE);
1594-				warnx("%s: unexpected SAN entry in "
1595-				    "certificate: %s", certfile, visbuf);
1596-				free(visbuf);
1597-				free(name_buf);
1598-				goto out;
1599-			}
1600-			force = 2;
1601-			continue;
1602 		}
1603-		/* should not reach here if j is out of bounds */
1604-		if (found_altnames[j] > 1) {
1605+		if (i == eltsz) {
1606 			if (revocate) {
1607-				char *visbuf;
1608-				visbuf = calloc(4, name_len + 1);
1609-				if (visbuf == NULL) {
1610-					warn("%s: duplicate SAN in "
1611-					    "certificate", certfile);
1612-					free(name_buf);
1613-					goto out;
1614-				}
1615-				warnx("%s: duplicate SAN entry in "
1616-				    "certificate: %s", certfile, visbuf);
1617-				free(name_buf);
1618-				free(visbuf);
1619+				warnx("%s: domain not listed: %s", certfile, ac->domain);
1620 				goto out;
1621 			}
1622 			force = 2;
1623 		}
1624-
1625-		free(name_buf);
1626 	}
1627 
1628-	for (j = 0; j < domain->altname_count; j++) {
1629-		struct altname_c	*ac;
1630-
1631-		if (found_altnames[j])
1632+	for (i = 0; i < eltsz; i++) {
1633+		if (elts[i].status == 0)
1634 			continue;
1635 		if (revocate) {
1636-			k = 0;
1637-			TAILQ_FOREACH(ac, &domain->altname_list, entry) {
1638-				if (j == k)
1639-					break;
1640-				k++;
1641+			char *visbuf;
1642+
1643+			if (elts[i].status != 1 ||
1644+			    stravis(&visbuf, elts[i].buf, VIS_SAFE) < 0) {
1645+				warnx("%s: unexpected SAN", certfile);
1646+				goto out;
1647 			}
1648-			warnx("%s: domain not listed: %s", certfile,
1649-			    ac->domain);
1650+			warnx("%s: unexpected SAN entry: %s",
1651+			    certfile, visbuf);
1652+			free(visbuf);
1653 			goto out;
1654 		}
1655 		force = 2;
1656@@ -323,16 +254,7 @@ revokeproc(int fd, const char *certfile, int force,
1657 		if (cc <= 0)
1658 			goto out;
1659 
1660-		if ((len = i2d_X509(x, NULL)) < 0) {
1661-			warnx("i2d_X509");
1662-			goto out;
1663-		} else if ((der = dercp = malloc(len)) == NULL) {
1664-			warn("malloc");
1665-			goto out;
1666-		} else if (len != i2d_X509(x, &dercp)) {
1667-			warnx("i2d_X509");
1668-			goto out;
1669-		} else if ((der64 = base64buf_url(der, len)) == NULL) {
1670+		if ((der64 = base64buf_url(cert.data, cert.data_len)) == NULL) {
1671 			warnx("base64buf_url");
1672 			goto out;
1673 		} else if (writestr(fd, COMM_CSR, der64) >= 0)
1674@@ -406,12 +328,9 @@ out:
1675 	close(fd);
1676 	if (f != NULL)
1677 		fclose(f);
1678-	X509_free(x);
1679-	GENERAL_NAMES_free(sans);
1680-	free(der);
1681-	free(found_altnames);
1682+	free(cert.data);
1683+	free(sans);
1684+	free(elts);
1685 	free(der64);
1686-	ERR_print_errors_fp(stderr);
1687-	ERR_free_strings();
1688 	return rc;
1689 }
1690-- 
16912.54.0
1692