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