linux-qubasis
linux oasis port as a qubes template
git clone https://9o.is/git/linux-qubasis.git
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