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