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