opkg

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

0035-acme-client-Port-to-BearSSL.patch (40769B)


      1 From 1ab0f94943e02c49d88a358351914f9032a5bca3 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   | 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    | 198 ++++++------------
     12  usr.sbin/acme-client/revokeproc.c | 237 ++++++++++-----------
     13  6 files changed, 564 insertions(+), 525 deletions(-)
     14 
     15 diff --git a/usr.sbin/acme-client/acctproc.c b/usr.sbin/acme-client/acctproc.c
     16 index 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  }
    511 diff --git a/usr.sbin/acme-client/certproc.c b/usr.sbin/acme-client/certproc.c
    512 index 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-----"
    527 diff --git a/usr.sbin/acme-client/key.c b/usr.sbin/acme-client/key.c
    528 index 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  }
    921 diff --git a/usr.sbin/acme-client/key.h b/usr.sbin/acme-client/key.h
    922 index 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 */
    953 diff --git a/usr.sbin/acme-client/keyproc.c b/usr.sbin/acme-client/keyproc.c
    954 index f0df9f292d4..fc7de74b616 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 @@ -77,18 +40,20 @@ int
   1017  keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
   1018      enum keytype keytype)
   1019  {
   1020 -	char		*der64 = NULL;
   1021 -	unsigned char	*der = NULL, *dercp;
   1022 -	char		*sans = NULL, *san = NULL;
   1023 -	FILE		*f;
   1024 -	size_t		 i, sansz;
   1025 -	void		*pp;
   1026 -	EVP_PKEY	*pkey = NULL;
   1027 -	X509_REQ	*x = NULL;
   1028 -	X509_NAME	*name = NULL;
   1029 -	int		 len, rc = 0, cc, nid, newkey = 0;
   1030 -	mode_t		 prev;
   1031 -	STACK_OF(X509_EXTENSION) *exts = NULL;
   1032 +	char			*der64 = NULL;
   1033 +	unsigned char		*der = NULL;
   1034 +	FILE			*f;
   1035 +	size_t			 i;
   1036 +	struct key		*pkey = NULL;
   1037 +	struct x509cert_req	 req;
   1038 +	struct x509cert_skey	 skey;
   1039 +	struct x509cert_dn	 dn;
   1040 +	struct x509cert_rdn	 rdn;
   1041 +	struct x509cert_item	 item;
   1042 +	int			 len, rc = 0, newkey = 0;
   1043 +	mode_t			 prev;
   1044 +
   1045 +	req.alts = NULL;
   1046  
   1047  	/*
   1048  	 * First, open our private key file read-only or write-only if
   1049 @@ -110,8 +75,6 @@ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
   1050  
   1051  	/* File-system, user, and sandbox jail. */
   1052  
   1053 -	ERR_load_crypto_strings();
   1054 -
   1055  	if (pledge("stdio", NULL) == -1) {
   1056  		warn("pledge");
   1057  		goto out;
   1058 @@ -145,102 +108,61 @@ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
   1059  	 * Then set it as the X509 requester's key.
   1060  	 */
   1061  
   1062 -	if ((x = X509_REQ_new()) == NULL) {
   1063 -		warnx("X509_REQ_new");
   1064 -		goto out;
   1065 -	} else if (!X509_REQ_set_version(x, 0)) {
   1066 -		warnx("X509_REQ_set_version");
   1067 -		goto out;
   1068 -	} else if (!X509_REQ_set_pubkey(x, pkey)) {
   1069 -		warnx("X509_REQ_set_pubkey");
   1070 -		goto out;
   1071 +	req.pkey.key_type = pkey->type;
   1072 +	skey.type = pkey->type;
   1073 +	switch (pkey->type) {
   1074 +	case BR_KEYTYPE_RSA:
   1075 +		req.pkey.key.rsa = pkey->rsa.pk;
   1076 +		skey.u.rsa = &pkey->rsa.sk;
   1077 +		break;
   1078 +	case BR_KEYTYPE_EC:
   1079 +		req.pkey.key.ec = pkey->ec.pk;
   1080 +		skey.u.ec = &pkey->ec.sk;
   1081 +		break;
   1082  	}
   1083  
   1084  	/* Now specify the common name that we'll request. */
   1085  
   1086 -	if ((name = X509_NAME_new()) == NULL) {
   1087 -		warnx("X509_NAME_new");
   1088 -		goto out;
   1089 -	} else if (!X509_NAME_add_entry_by_txt(name, "CN",
   1090 -		MBSTRING_ASC, (u_char *)alts[0], -1, -1, 0)) {
   1091 -		warnx("X509_NAME_add_entry_by_txt: CN=%s", alts[0]);
   1092 -		goto out;
   1093 -	} else if (!X509_REQ_set_subject_name(x, name)) {
   1094 -		warnx("X509_req_set_issuer_name");
   1095 -		goto out;
   1096 -	}
   1097 +	rdn.oid = x509cert_oid_CN;
   1098 +	rdn.val.tag = X509CERT_ASN1_UTF8STRING;
   1099 +	rdn.val.val = alts[0];
   1100 +	rdn.val.len = strlen(alts[0]);
   1101 +	rdn.val.enc = NULL;
   1102 +	dn.rdn = &rdn;
   1103 +	dn.rdn_len = 1;
   1104 +	req.subject.enc = x509cert_dn_encoder;
   1105 +	req.subject.val = &dn;
   1106  
   1107 -	/*
   1108 -	 * Now add the SAN extensions.
   1109 -	 * This was lifted more or less directly from demos/x509/mkreq.c
   1110 -	 * of the OpenSSL source code.
   1111 -	 * (The zeroth altname is the domain name.)
   1112 -	 * TODO: is this the best way of doing this?
   1113 -	 */
   1114 +	/* Now add the SAN extension. */
   1115  
   1116 -	nid = NID_subject_alt_name;
   1117 -	if ((exts = sk_X509_EXTENSION_new_null()) == NULL) {
   1118 -		warnx("sk_X509_EXTENSION_new_null");
   1119 +	req.alts_len = altsz;
   1120 +	req.alts = calloc(altsz, sizeof(req.alts[0]));
   1121 +	if (req.alts == NULL) {
   1122 +		warn("calloc");
   1123  		goto out;
   1124  	}
   1125 -	/* Initialise to empty string. */
   1126 -	if ((sans = strdup("")) == NULL) {
   1127 -		warn("strdup");
   1128 -		goto out;
   1129 -	}
   1130 -	sansz = strlen(sans) + 1;
   1131  
   1132 -	/*
   1133 -	 * For each SAN entry, append it to the string.
   1134 -	 * We need a single SAN entry for all of the SAN
   1135 -	 * domains: NOT an entry per domain!
   1136 -	 */
   1137 +	/* Add a dNSName SAN entry for each alternate name. */
   1138  
   1139  	for (i = 0; i < altsz; i++) {
   1140 -		cc = asprintf(&san, "%sDNS:%s",
   1141 -		    i ? "," : "", alts[i]);
   1142 -		if (cc == -1) {
   1143 -			warn("asprintf");
   1144 -			goto out;
   1145 -		}
   1146 -		pp = recallocarray(sans, sansz, sansz + strlen(san), 1);
   1147 -		if (pp == NULL) {
   1148 -			warn("recallocarray");
   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 +		req.alts[i].tag = X509CERT_SAN_DNSNAME;
   1173 +		req.alts[i].val = alts[i];
   1174 +		req.alts[i].len = strlen(alts[i]);
   1175  	}
   1176  
   1177 -	/* Now, serialise to DER, then base64. */
   1178 +	/* Sign the X.509 request using SHA256, and serialise to
   1179 +	 * DER then base64. */
   1180  
   1181 -	if ((len = i2d_X509_REQ(x, NULL)) < 0) {
   1182 -		warnx("i2d_X509_REQ");
   1183 +	item.enc = x509cert_req_encoder;
   1184 +	item.val = &req;
   1185 +	if ((len = x509cert_sign(&item, &skey, &br_sha256_vtable, NULL)) == 0) {
   1186 +		warnx("x509cert_sign");
   1187  		goto out;
   1188 -	} else if ((der = dercp = malloc(len)) == NULL) {
   1189 +	} else if ((der = malloc(len)) == NULL) {
   1190  		warn("malloc");
   1191  		goto out;
   1192 -	} else if (len != i2d_X509_REQ(x, &dercp)) {
   1193 -		warnx("i2d_X509_REQ");
   1194 +	} else if ((len = x509cert_sign(&item, &skey, &br_sha256_vtable, der)) == 0) {
   1195 +		warnx("x509cert_sign");
   1196  		goto out;
   1197  	} else if ((der64 = base64buf_url(der, len)) == NULL) {
   1198  		warnx("base64buf_url");
   1199 @@ -265,12 +187,8 @@ out:
   1200  		fclose(f);
   1201  	free(der);
   1202  	free(der64);
   1203 -	free(sans);
   1204 -	free(san);
   1205 -	X509_REQ_free(x);
   1206 -	X509_NAME_free(name);
   1207 -	EVP_PKEY_free(pkey);
   1208 -	ERR_print_errors_fp(stderr);
   1209 -	ERR_free_strings();
   1210 +	free(req.alts);
   1211 +	if (pkey != NULL)
   1212 +		freezero(pkey, pkey->datasz);
   1213  	return rc;
   1214  }
   1215 diff --git a/usr.sbin/acme-client/revokeproc.c b/usr.sbin/acme-client/revokeproc.c
   1216 index 58e81233f1a..378de35f662 100644
   1217 --- a/usr.sbin/acme-client/revokeproc.c
   1218 +++ b/usr.sbin/acme-client/revokeproc.c
   1219 @@ -22,58 +22,54 @@
   1220  #include <stdio.h>
   1221  #include <stdlib.h>
   1222  #include <string.h>
   1223 +#include <time.h>
   1224  #include <unistd.h>
   1225  #include <vis.h>
   1226  
   1227 -#include <openssl/pem.h>
   1228 -#include <openssl/x509.h>
   1229 -#include <openssl/x509v3.h>
   1230 -#include <openssl/err.h>
   1231 +#include <bearssl.h>
   1232  
   1233  #include "extern.h"
   1234  
   1235  #define	RENEW_ALLOW (30 * 24 * 60 * 60)
   1236  
   1237 -/*
   1238 - * Convert the X509's expiration time into a time_t value.
   1239 - */
   1240 -static time_t
   1241 -X509expires(X509 *x)
   1242 +static void
   1243 +append_cert(void *ctx, const void *buf, size_t len)
   1244  {
   1245 -	ASN1_TIME	*atim;
   1246 -	struct tm	 t;
   1247 -
   1248 -	if ((atim = X509_getm_notAfter(x)) == NULL) {
   1249 -		warnx("missing notAfter");
   1250 -		return -1;
   1251 -	}
   1252 -
   1253 -	memset(&t, 0, sizeof(t));
   1254 -
   1255 -	if (!ASN1_TIME_to_tm(atim, &t)) {
   1256 -		warnx("invalid ASN1_TIME");
   1257 -		return -1;
   1258 +	br_x509_certificate *cert = ctx;
   1259 +	size_t newlen;
   1260 +	unsigned char *newdata;
   1261 +
   1262 +	if (cert->data_len == -1)
   1263 +		return;
   1264 +	newlen = cert->data_len + len;
   1265 +	if ((newdata = realloc(cert->data, newlen)) != NULL) {
   1266 +		memcpy(newdata + cert->data_len, buf, len);
   1267 +		cert->data = newdata;
   1268 +		cert->data_len = newlen;
   1269 +	} else {
   1270 +		warn("realloc");
   1271 +		cert->data_len = -1;
   1272  	}
   1273 -
   1274 -	return timegm(&t);
   1275  }
   1276  
   1277  int
   1278  revokeproc(int fd, const char *certfile, int force,
   1279      int revocate, const char *const *alts, size_t altsz)
   1280  {
   1281 -	GENERAL_NAMES			*sans = NULL;
   1282 -	unsigned char			*der = NULL, *dercp;
   1283 -	char				*der64 = NULL;
   1284 -	char				*san = NULL, *str, *tok;
   1285 -	int				 rc = 0, cc, i, len;
   1286 -	size_t				*found = NULL;
   1287 +	static const unsigned char	 dnsname[] = {0, 2};
   1288 +	char				 buf[8192], *pos, *sans = NULL, *der64 = NULL;
   1289 +	int				 rc = 0, cc, state, err;
   1290 +	size_t				 i, j, n, len = 0, altlen, altmax, eltsz;
   1291  	FILE				*f = NULL;
   1292 -	X509				*x = NULL;
   1293 +	br_pem_decoder_context		 pc;
   1294 +	br_x509_decoder_context		 xd;
   1295 +	br_x509_minimal_context		 xc;
   1296 +	br_x509_certificate		 cert = {0};
   1297 +	br_name_element			*elts = NULL;
   1298 +	uint32_t			 days, secs;
   1299  	long				 lval;
   1300  	enum revokeop			 op, rop;
   1301  	time_t				 t;
   1302 -	size_t				 j;
   1303  
   1304  	/*
   1305  	 * First try to open the certificate before we drop privileges
   1306 @@ -88,8 +84,6 @@ revokeproc(int fd, const char *certfile, int force,
   1307  
   1308  	/* File-system and sandbox jailing. */
   1309  
   1310 -	ERR_load_crypto_strings();
   1311 -
   1312  	if (pledge("stdio", NULL) == -1) {
   1313  		warn("pledge");
   1314  		goto out;
   1315 @@ -113,39 +107,86 @@ revokeproc(int fd, const char *certfile, int force,
   1316  		goto out;
   1317  	}
   1318  
   1319 -	if ((x = PEM_read_X509(f, NULL, NULL, NULL)) == NULL) {
   1320 -		warnx("PEM_read_X509");
   1321 -		goto out;
   1322 +	br_pem_decoder_init(&pc);
   1323 +	for (state = 0; state != 2;) {
   1324 +		if (len == 0) {
   1325 +			if (feof(f)) {
   1326 +				warnx("%s: truncated certificate", certfile);
   1327 +				goto out;
   1328 +			}
   1329 +			len = fread(buf, 1, sizeof(buf), f);
   1330 +			if (ferror(f)) {
   1331 +				warn("fread");
   1332 +				goto out;
   1333 +			}
   1334 +			pos = buf;
   1335 +		}
   1336 +		n = br_pem_decoder_push(&pc, pos, len);
   1337 +		pos += n;
   1338 +		len -= n;
   1339 +		switch (br_pem_decoder_event(&pc)) {
   1340 +		case BR_PEM_BEGIN_OBJ:
   1341 +			if (strcmp(br_pem_decoder_name(&pc), "CERTIFICATE") == 0) {
   1342 +				br_pem_decoder_setdest(&pc, append_cert, &cert);
   1343 +				state = 1;
   1344 +			}
   1345 +			break;
   1346 +		case BR_PEM_END_OBJ:
   1347 +			if (state == 1)
   1348 +				state = 2;
   1349 +			break;
   1350 +		case 0:
   1351 +			break;
   1352 +		default:
   1353 +			warnx("%s: PEM decoding error", certfile);
   1354 +			goto out;
   1355 +		}
   1356  	}
   1357 -
   1358 -	/* Cache and sanity check X509v3 extensions. */
   1359 -
   1360 -	if (X509_check_purpose(x, -1, -1) <= 0) {
   1361 -		warnx("%s: invalid X509v3 extensions", certfile);
   1362 +	if (cert.data_len == -1)
   1363  		goto out;
   1364 -	}
   1365  
   1366  	/* Read out the expiration date. */
   1367  
   1368 -	if ((t = X509expires(x)) == -1) {
   1369 -		warnx("X509expires");
   1370 +	br_x509_decoder_init(&xd, NULL, NULL);
   1371 +	br_x509_decoder_push(&xd, cert.data, cert.data_len);
   1372 +	if ((err = br_x509_decoder_last_error(&xd)) != 0) {
   1373 +		warnx("%s: X.509 decoding error %d", certfile, err);
   1374  		goto out;
   1375  	}
   1376 +	br_x509_decoder_get_notafter(&xd, &days, &secs);
   1377 +	t = 86400ll * (days - 719528) + 86400;
   1378  
   1379 -	/* Extract list of SAN entries from the certificate. */
   1380 -
   1381 -	sans = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
   1382 -	if (sans == NULL) {
   1383 -		warnx("%s: does not have a SAN entry", certfile);
   1384 -		if (revocate)
   1385 -			goto out;
   1386 -		force = 2;
   1387 +	for (i = 0, altmax = 0; i < altsz; ++i) {
   1388 +		altlen = strlen(alts[i]) + 1;
   1389 +		if (altlen > altmax)
   1390 +			altmax = altlen;
   1391 +	}
   1392 +	eltsz = altsz + 1;
   1393 +	if ((elts = calloc(eltsz, sizeof(elts[0]))) == NULL ||
   1394 +	    (sans = calloc(eltsz, altmax)) == NULL) {
   1395 +		warn("calloc");
   1396 +		goto out;
   1397 +	}
   1398 +	for (i = 0; i < eltsz; ++i) {
   1399 +		elts[i].oid = dnsname;
   1400 +		elts[i].buf = sans + i * altmax;
   1401 +		elts[i].len = altmax;
   1402  	}
   1403  
   1404 -	/* An array of buckets: the number of entries found. */
   1405 +	/* Extract list of SAN entries from the certificate. */
   1406  
   1407 -	if ((found = calloc(altsz, sizeof(size_t))) == NULL) {
   1408 -		warn("calloc");
   1409 +	br_x509_minimal_init(&xc, &br_sha256_vtable, NULL, 0);
   1410 +	br_x509_minimal_set_hash(&xc, br_sha256_ID, &br_sha256_vtable);
   1411 +	br_x509_minimal_set_hash(&xc, br_sha384_ID, &br_sha384_vtable);
   1412 +	br_x509_minimal_set_hash(&xc, br_sha512_ID, &br_sha512_vtable);
   1413 +	br_x509_minimal_set_name_elements(&xc, elts, eltsz);
   1414 +	xc.vtable->start_chain(&xc.vtable, NULL);
   1415 +	xc.vtable->start_cert(&xc.vtable, cert.data_len);
   1416 +	xc.vtable->append(&xc.vtable, cert.data, cert.data_len);
   1417 +	xc.vtable->end_cert(&xc.vtable);
   1418 +	err = xc.vtable->end_chain(&xc.vtable);
   1419 +	if (err != BR_ERR_X509_NOT_TRUSTED && err != BR_ERR_X509_EXPIRED) {
   1420 +		warnx("%s: X.509 engine error %d", certfile, err);
   1421  		goto out;
   1422  	}
   1423  
   1424 @@ -154,63 +195,37 @@ revokeproc(int fd, const char *certfile, int force,
   1425  	 * configuration file and that all domains are represented only once.
   1426  	 */
   1427  
   1428 -	for (i = 0; i < sk_GENERAL_NAME_num(sans); i++) {
   1429 -		GENERAL_NAME		*gen_name;
   1430 -		const ASN1_IA5STRING	*name;
   1431 -		const unsigned char	*name_buf;
   1432 -		int			 name_len;
   1433 -		int			 name_type;
   1434 -
   1435 -		gen_name = sk_GENERAL_NAME_value(sans, i);
   1436 -		assert(gen_name != NULL);
   1437 -
   1438 -		name = GENERAL_NAME_get0_value(gen_name, &name_type);
   1439 -		if (name_type != GEN_DNS)
   1440 -			continue;
   1441 -
   1442 -		/* name_buf isn't a C string and could contain embedded NULs. */
   1443 -		name_buf = ASN1_STRING_get0_data(name);
   1444 -		name_len = ASN1_STRING_length(name);
   1445 -
   1446 -		for (j = 0; j < altsz; j++) {
   1447 -			if ((size_t)name_len != strlen(alts[j]))
   1448 -				continue;
   1449 -			if (memcmp(name_buf, alts[j], name_len) == 0)
   1450 +	for (i = 0; i < altsz; i++) {
   1451 +		for (j = 0; j < eltsz; j++) {
   1452 +			if (elts[j].status == 1 &&
   1453 +			    strcmp(alts[i], elts[j].buf) == 0) {
   1454 +				elts[j].status = 0;
   1455  				break;
   1456 -		}
   1457 -		if (j == altsz) {
   1458 -			if (revocate) {
   1459 -				char *visbuf;
   1460 -
   1461 -				visbuf = calloc(4, name_len + 1);
   1462 -				if (visbuf == NULL) {
   1463 -					warn("%s: unexpected SAN", certfile);
   1464 -					goto out;
   1465 -				}
   1466 -				strvisx(visbuf, name_buf, name_len, VIS_SAFE);
   1467 -				warnx("%s: unexpected SAN entry: %s",
   1468 -				    certfile, visbuf);
   1469 -				free(visbuf);
   1470 -				goto out;
   1471  			}
   1472 -			force = 2;
   1473 -			continue;
   1474  		}
   1475 -		if (found[j]++) {
   1476 +		if (j == eltsz) {
   1477  			if (revocate) {
   1478 -				warnx("%s: duplicate SAN entry: %.*s",
   1479 -				    certfile, name_len, name_buf);
   1480 +				warnx("%s: domain not listed: %s", certfile, alts[i]);
   1481  				goto out;
   1482  			}
   1483  			force = 2;
   1484  		}
   1485  	}
   1486  
   1487 -	for (j = 0; j < altsz; j++) {
   1488 -		if (found[j])
   1489 +	for (i = 0; i < eltsz; i++) {
   1490 +		if (elts[i].status == 0)
   1491  			continue;
   1492  		if (revocate) {
   1493 -			warnx("%s: domain not listed: %s", certfile, alts[j]);
   1494 +			char *visbuf;
   1495 +
   1496 +			if (elts[i].status != 1 ||
   1497 +			    stravis(&visbuf, elts[i].buf, VIS_SAFE) < 0) {
   1498 +				warnx("%s: unexpected SAN", certfile);
   1499 +				goto out;
   1500 +			}
   1501 +			warnx("%s: unexpected SAN entry: %s",
   1502 +			    certfile, visbuf);
   1503 +			free(visbuf);
   1504  			goto out;
   1505  		}
   1506  		force = 2;
   1507 @@ -236,16 +251,7 @@ revokeproc(int fd, const char *certfile, int force,
   1508  		if (cc <= 0)
   1509  			goto out;
   1510  
   1511 -		if ((len = i2d_X509(x, NULL)) < 0) {
   1512 -			warnx("i2d_X509");
   1513 -			goto out;
   1514 -		} else if ((der = dercp = malloc(len)) == NULL) {
   1515 -			warn("malloc");
   1516 -			goto out;
   1517 -		} else if (len != i2d_X509(x, &dercp)) {
   1518 -			warnx("i2d_X509");
   1519 -			goto out;
   1520 -		} else if ((der64 = base64buf_url(der, len)) == NULL) {
   1521 +		if ((der64 = base64buf_url(cert.data, cert.data_len)) == NULL) {
   1522  			warnx("base64buf_url");
   1523  			goto out;
   1524  		} else if (writestr(fd, COMM_CSR, der64) >= 0)
   1525 @@ -298,12 +304,9 @@ out:
   1526  	close(fd);
   1527  	if (f != NULL)
   1528  		fclose(f);
   1529 -	X509_free(x);
   1530 -	GENERAL_NAMES_free(sans);
   1531 -	free(der);
   1532 -	free(found);
   1533 +	free(cert.data);
   1534 +	free(sans);
   1535 +	free(elts);
   1536  	free(der64);
   1537 -	ERR_print_errors_fp(stderr);
   1538 -	ERR_free_strings();
   1539  	return rc;
   1540  }
   1541 -- 
   1542 2.49.0
   1543