opkg

statically linked package installer
git clone anongit@rnpnr.xyz:opkg.git
Log | Files | Refs | Feed | Submodules | README | LICENSE

0036-acme-client-Port-to-BearSSL.patch (40831B)


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