0035-acme-client-Port-to-BearSSL.patch (42655B)
1 From 4ad4ffcb7c731ae48c97b93760d7625724a991bc 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 | 192 ++++++----------- 12 usr.sbin/acme-client/revokeproc.c | 319 +++++++++++------------------ 13 6 files changed, 568 insertions(+), 597 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 4360156b9c0..19b8077a8fb 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 @@ -76,19 +39,20 @@ add_ext(STACK_OF(X509_EXTENSION) *sk, int nid, const char *value) 1017 int 1018 keyproc(int netsock, struct domain_c *domain) 1019 { 1020 - char *der64 = NULL; 1021 - unsigned char *der = NULL, *dercp; 1022 - char *sans = NULL, *san = NULL; 1023 - FILE *f; 1024 - size_t sansz; 1025 - void *pp; 1026 - EVP_PKEY *pkey = NULL; 1027 - X509_REQ *x = NULL; 1028 - int len, rc = 0, cc, nid, newkey = 0, first; 1029 - mode_t prev; 1030 - STACK_OF(X509_EXTENSION) *exts = NULL; 1031 - struct altname_c *ac; 1032 - const char *keyfile = domain->key; 1033 + char *der64 = NULL; 1034 + unsigned char *der = NULL; 1035 + FILE *f; 1036 + struct key *pkey = NULL; 1037 + struct x509cert_req req; 1038 + struct x509cert_skey skey; 1039 + struct x509cert_dn dn; 1040 + struct x509cert_item item; 1041 + int len, rc = 0, newkey = 0, i; 1042 + mode_t prev; 1043 + struct altname_c *ac; 1044 + const char *keyfile = domain->key; 1045 + 1046 + req.alts = NULL; 1047 1048 /* 1049 * First, open our private key file read-only or write-only if 1050 @@ -110,8 +74,6 @@ keyproc(int netsock, struct domain_c *domain) 1051 1052 /* File-system, user, and sandbox jail. */ 1053 1054 - ERR_load_crypto_strings(); 1055 - 1056 if (pledge("stdio", NULL) == -1) { 1057 warn("pledge"); 1058 goto out; 1059 @@ -145,98 +107,65 @@ keyproc(int netsock, struct domain_c *domain) 1060 * Then set it as the X509 requester's key. 1061 */ 1062 1063 - if ((x = X509_REQ_new()) == NULL) { 1064 - warnx("X509_REQ_new"); 1065 - goto out; 1066 - } else if (!X509_REQ_set_version(x, 0)) { 1067 - warnx("X509_REQ_set_version"); 1068 - goto out; 1069 - } else if (!X509_REQ_set_pubkey(x, pkey)) { 1070 - warnx("X509_REQ_set_pubkey"); 1071 - goto out; 1072 + req.pkey.key_type = pkey->type; 1073 + skey.type = pkey->type; 1074 + switch (pkey->type) { 1075 + case BR_KEYTYPE_RSA: 1076 + req.pkey.key.rsa = pkey->rsa.pk; 1077 + skey.u.rsa = &pkey->rsa.sk; 1078 + break; 1079 + case BR_KEYTYPE_EC: 1080 + req.pkey.key.ec = pkey->ec.pk; 1081 + skey.u.ec = &pkey->ec.sk; 1082 + break; 1083 } 1084 1085 - /* 1086 - * Now add the SAN extensions. 1087 - * This was lifted more or less directly from demos/x509/mkreq.c 1088 - * of the OpenSSL source code. 1089 - * (The zeroth altname is the domain name.) 1090 - * TODO: is this the best way of doing this? 1091 - */ 1092 + /* Use an empty subject. */ 1093 1094 - nid = NID_subject_alt_name; 1095 - if ((exts = sk_X509_EXTENSION_new_null()) == NULL) { 1096 - warnx("sk_X509_EXTENSION_new_null"); 1097 - goto out; 1098 - } 1099 - /* Initialise to empty string. */ 1100 - if ((sans = strdup("")) == NULL) { 1101 - warn("strdup"); 1102 + dn.rdn = NULL; 1103 + dn.rdn_len = 0; 1104 + req.subject.enc = x509cert_dn_encoder; 1105 + req.subject.val = &dn; 1106 + 1107 + /* Now add the SAN extension. */ 1108 + 1109 + req.alts_len = domain->altname_count; 1110 + req.alts = calloc(domain->altname_count, sizeof(req.alts[0])); 1111 + if (req.alts == NULL) { 1112 + warn("calloc"); 1113 goto out; 1114 } 1115 - sansz = strlen(sans) + 1; 1116 1117 - /* 1118 - * For each SAN entry, append it to the string. 1119 - * We need a single SAN entry for all of the SAN 1120 - * domains: NOT an entry per domain! 1121 - */ 1122 + /* Add a dNSName SAN entry for each alternate name. */ 1123 1124 - first = 1; 1125 + i = 0; 1126 TAILQ_FOREACH(ac, &domain->altname_list, entry) { 1127 switch (ac->idtype) { 1128 case ID_DNS: 1129 - cc = asprintf(&san, "%sDNS:%s", first ? "" : ",", 1130 - ac->domain); 1131 + req.alts[i].tag = X509CERT_SAN_DNSNAME; 1132 + req.alts[i].val = ac->domain; 1133 + req.alts[i].len = strlen(ac->domain); 1134 break; 1135 case ID_IP: 1136 - cc = asprintf(&san, "%sIP:%s", first ? "" : ",", 1137 - ac->domain); 1138 - break; 1139 - } 1140 - first = 0; 1141 - if (cc == -1) { 1142 - warn("asprintf"); 1143 - goto out; 1144 - } 1145 - pp = recallocarray(sans, sansz, sansz + strlen(san), 1); 1146 - if (pp == NULL) { 1147 - warn("recallocarray"); 1148 + warnx("ID_IP is not supported"); 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 + i++; 1173 } 1174 1175 - /* Now, serialise to DER, then base64. */ 1176 + /* Sign the X.509 request using SHA256, and serialise to 1177 + * DER then base64. */ 1178 1179 - if ((len = i2d_X509_REQ(x, NULL)) < 0) { 1180 - warnx("i2d_X509_REQ"); 1181 + item.enc = x509cert_req_encoder; 1182 + item.val = &req; 1183 + if ((len = x509cert_sign(&item, &skey, &br_sha256_vtable, NULL)) == 0) { 1184 + warnx("x509cert_sign"); 1185 goto out; 1186 - } else if ((der = dercp = malloc(len)) == NULL) { 1187 + } else if ((der = malloc(len)) == NULL) { 1188 warn("malloc"); 1189 goto out; 1190 - } else if (len != i2d_X509_REQ(x, &dercp)) { 1191 - warnx("i2d_X509_REQ"); 1192 + } else if ((len = x509cert_sign(&item, &skey, &br_sha256_vtable, der)) == 0) { 1193 + warnx("x509cert_sign"); 1194 goto out; 1195 } else if ((der64 = base64buf_url(der, len)) == NULL) { 1196 warnx("base64buf_url"); 1197 @@ -261,11 +190,8 @@ out: 1198 fclose(f); 1199 free(der); 1200 free(der64); 1201 - free(sans); 1202 - free(san); 1203 - X509_REQ_free(x); 1204 - EVP_PKEY_free(pkey); 1205 - ERR_print_errors_fp(stderr); 1206 - ERR_free_strings(); 1207 + free(req.alts); 1208 + if (pkey != NULL) 1209 + freezero(pkey, pkey->datasz); 1210 return rc; 1211 } 1212 diff --git a/usr.sbin/acme-client/revokeproc.c b/usr.sbin/acme-client/revokeproc.c 1213 index c0963a278fb..2109d7a8799 100644 1214 --- a/usr.sbin/acme-client/revokeproc.c 1215 +++ b/usr.sbin/acme-client/revokeproc.c 1216 @@ -15,8 +15,6 @@ 1217 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1218 */ 1219 1220 -#include <sys/socket.h> 1221 -#include <arpa/inet.h> 1222 #include <assert.h> 1223 #include <ctype.h> 1224 #include <err.h> 1225 @@ -24,71 +22,54 @@ 1226 #include <stdio.h> 1227 #include <stdlib.h> 1228 #include <string.h> 1229 +#include <time.h> 1230 #include <unistd.h> 1231 #include <vis.h> 1232 1233 -#include <openssl/pem.h> 1234 -#include <openssl/x509.h> 1235 -#include <openssl/x509v3.h> 1236 -#include <openssl/err.h> 1237 +#include <bearssl.h> 1238 1239 #include "extern.h" 1240 1241 -/* 1242 - * Convert the X509's notAfter time into a time_t value. 1243 - */ 1244 -static time_t 1245 -X509notafter(X509 *x) 1246 -{ 1247 - ASN1_TIME *atim; 1248 - struct tm t; 1249 - 1250 - if ((atim = X509_getm_notAfter(x)) == NULL) 1251 - return -1; 1252 - 1253 - memset(&t, 0, sizeof(t)); 1254 - 1255 - if (!ASN1_TIME_to_tm(atim, &t)) 1256 - return -1; 1257 - 1258 - return timegm(&t); 1259 -} 1260 - 1261 -/* 1262 - * Convert the X509's notBefore time into a time_t value. 1263 - */ 1264 -static time_t 1265 -X509notbefore(X509 *x) 1266 +static void 1267 +append_cert(void *ctx, const void *buf, size_t len) 1268 { 1269 - ASN1_TIME *atim; 1270 - struct tm t; 1271 - 1272 - if ((atim = X509_getm_notBefore(x)) == NULL) 1273 - return -1; 1274 - 1275 - memset(&t, 0, sizeof(t)); 1276 - 1277 - if (!ASN1_TIME_to_tm(atim, &t)) 1278 - return -1; 1279 - 1280 - return timegm(&t); 1281 + br_x509_certificate *cert = ctx; 1282 + size_t newlen; 1283 + unsigned char *newdata; 1284 + 1285 + if (cert->data_len == -1) 1286 + return; 1287 + newlen = cert->data_len + len; 1288 + if ((newdata = realloc(cert->data, newlen)) != NULL) { 1289 + memcpy(newdata + cert->data_len, buf, len); 1290 + cert->data = newdata; 1291 + cert->data_len = newlen; 1292 + } else { 1293 + warn("realloc"); 1294 + cert->data_len = -1; 1295 + } 1296 } 1297 1298 int 1299 revokeproc(int fd, const char *certfile, int force, 1300 int revocate, struct domain_c *domain) 1301 { 1302 - GENERAL_NAMES *sans = NULL; 1303 - unsigned char *der = NULL, *dercp; 1304 - char *der64 = NULL; 1305 - int rc = 0, cc, sanidx, len, j, k; 1306 - int *found_altnames = NULL; 1307 + static const unsigned char dnsname[] = {0, 2}; 1308 + char buf[8192], *pos, *sans = NULL, *der64 = NULL; 1309 + int rc = 0, cc, i, eltsz, state, err; 1310 + size_t n, len = 0, altlen, altmax; 1311 FILE *f = NULL; 1312 - X509 *x = NULL; 1313 + br_pem_decoder_context pc; 1314 + br_x509_decoder_context xd; 1315 + br_x509_minimal_context xc; 1316 + br_x509_certificate cert = {0}; 1317 + br_name_element *elts = NULL; 1318 + uint32_t days, secs; 1319 long lval; 1320 enum revokeop op, rop; 1321 time_t notafter, notbefore, cert_validity; 1322 time_t remaining_validity, renew_allow; 1323 + struct altname_c *ac; 1324 1325 /* 1326 * First try to open the certificate before we drop privileges 1327 @@ -103,8 +84,6 @@ revokeproc(int fd, const char *certfile, int force, 1328 1329 /* File-system and sandbox jailing. */ 1330 1331 - ERR_load_crypto_strings(); 1332 - 1333 if (pledge("stdio", NULL) == -1) { 1334 warn("pledge"); 1335 goto out; 1336 @@ -128,45 +107,89 @@ revokeproc(int fd, const char *certfile, int force, 1337 goto out; 1338 } 1339 1340 - if ((x = PEM_read_X509(f, NULL, NULL, NULL)) == NULL) { 1341 - warnx("PEM_read_X509"); 1342 - goto out; 1343 + br_pem_decoder_init(&pc); 1344 + for (state = 0; state != 2;) { 1345 + if (len == 0) { 1346 + if (feof(f)) { 1347 + warnx("%s: truncated certificate", certfile); 1348 + goto out; 1349 + } 1350 + len = fread(buf, 1, sizeof(buf), f); 1351 + if (ferror(f)) { 1352 + warn("fread"); 1353 + goto out; 1354 + } 1355 + pos = buf; 1356 + } 1357 + n = br_pem_decoder_push(&pc, pos, len); 1358 + pos += n; 1359 + len -= n; 1360 + switch (br_pem_decoder_event(&pc)) { 1361 + case BR_PEM_BEGIN_OBJ: 1362 + if (strcmp(br_pem_decoder_name(&pc), "CERTIFICATE") == 0) { 1363 + br_pem_decoder_setdest(&pc, append_cert, &cert); 1364 + state = 1; 1365 + } 1366 + break; 1367 + case BR_PEM_END_OBJ: 1368 + if (state == 1) 1369 + state = 2; 1370 + break; 1371 + case 0: 1372 + break; 1373 + default: 1374 + warnx("%s: PEM decoding error", certfile); 1375 + goto out; 1376 + } 1377 } 1378 - 1379 - /* Cache and sanity check X509v3 extensions. */ 1380 - 1381 - if (X509_check_purpose(x, -1, -1) <= 0) { 1382 - warnx("%s: invalid X509v3 extensions", certfile); 1383 + if (cert.data_len == -1) 1384 goto out; 1385 - } 1386 1387 /* Read out the expiration date. */ 1388 1389 - if ((notafter = X509notafter(x)) == -1) { 1390 - warnx("X509notafter"); 1391 + br_x509_decoder_init(&xd, NULL, NULL); 1392 + br_x509_decoder_push(&xd, cert.data, cert.data_len); 1393 + if ((err = br_x509_decoder_last_error(&xd)) != 0) { 1394 + warnx("%s: X.509 decoding error %d", certfile, err); 1395 goto out; 1396 } 1397 - 1398 - if ((notbefore = X509notbefore(x)) == -1) { 1399 - warnx("X509notbefore"); 1400 + br_x509_decoder_get_notafter(&xd, &days, &secs); 1401 + notafter = 86400ll * (days - 719528) + 86400; 1402 + br_x509_decoder_get_notbefore(&xd, &days, &secs); 1403 + notbefore = 86400ll * (days - 719528) + 86400; 1404 + 1405 + altmax = 0; 1406 + TAILQ_FOREACH(ac, &domain->altname_list, entry) { 1407 + altlen = strlen(ac->domain) + 1; 1408 + if (altlen > altmax) 1409 + altmax = altlen; 1410 + } 1411 + eltsz = domain->altname_count + 1; 1412 + if ((elts = calloc(eltsz, sizeof(elts[0]))) == NULL || 1413 + (sans = calloc(eltsz, altmax)) == NULL) { 1414 + warn("calloc"); 1415 goto out; 1416 } 1417 - 1418 - /* Extract list of SAN entries from the certificate. */ 1419 - 1420 - sans = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 1421 - if (sans == NULL) { 1422 - warnx("%s: does not have a SAN entry", certfile); 1423 - if (revocate) 1424 - goto out; 1425 - force = 2; 1426 + for (i = 0; i < eltsz; ++i) { 1427 + elts[i].oid = dnsname; 1428 + elts[i].buf = sans + i * altmax; 1429 + elts[i].len = altmax; 1430 } 1431 1432 - /* An array of buckets: the number of entries found. */ 1433 + /* Extract list of SAN entries from the certificate. */ 1434 1435 - if ((found_altnames = (int *)calloc(domain->altname_count, 1436 - sizeof(int))) == NULL) { 1437 - warn("calloc"); 1438 + br_x509_minimal_init(&xc, &br_sha256_vtable, NULL, 0); 1439 + br_x509_minimal_set_hash(&xc, br_sha256_ID, &br_sha256_vtable); 1440 + br_x509_minimal_set_hash(&xc, br_sha384_ID, &br_sha384_vtable); 1441 + br_x509_minimal_set_hash(&xc, br_sha512_ID, &br_sha512_vtable); 1442 + br_x509_minimal_set_name_elements(&xc, elts, eltsz); 1443 + xc.vtable->start_chain(&xc.vtable, NULL); 1444 + xc.vtable->start_cert(&xc.vtable, cert.data_len); 1445 + xc.vtable->append(&xc.vtable, cert.data, cert.data_len); 1446 + xc.vtable->end_cert(&xc.vtable); 1447 + err = xc.vtable->end_chain(&xc.vtable); 1448 + if (err != BR_ERR_X509_NOT_TRUSTED && err != BR_ERR_X509_EXPIRED) { 1449 + warnx("%s: X.509 engine error %d", certfile, err); 1450 goto out; 1451 } 1452 1453 @@ -175,121 +198,37 @@ revokeproc(int fd, const char *certfile, int force, 1454 * configuration file and that all domains are represented only once. 1455 */ 1456 1457 - for (sanidx = 0; sanidx < sk_GENERAL_NAME_num(sans); sanidx++) { 1458 - GENERAL_NAME *gen_name; 1459 - char *name_buf = NULL; 1460 - int name_len; 1461 - struct altname_c *ac; 1462 - 1463 - gen_name = sk_GENERAL_NAME_value(sans, sanidx); 1464 - assert(gen_name != NULL); 1465 - 1466 - if (gen_name->type == GEN_IPADD) { 1467 - char ip_buf[INET6_ADDRSTRLEN]; 1468 - const char *ip; 1469 - 1470 - name_len = ASN1_STRING_length(gen_name->d.iPAddress); 1471 - switch (name_len) { 1472 - case 4: 1473 - ip = inet_ntop(AF_INET, 1474 - ASN1_STRING_get0_data(gen_name->d.iPAddress), 1475 - ip_buf, INET6_ADDRSTRLEN); 1476 - break; 1477 - case 16: 1478 - ip = inet_ntop(AF_INET6, 1479 - ASN1_STRING_get0_data(gen_name->d.iPAddress), 1480 - ip_buf, INET6_ADDRSTRLEN); 1481 - break; 1482 - default: 1483 - ip = NULL; 1484 + TAILQ_FOREACH(ac, &domain->altname_list, entry) { 1485 + for (i = 0; i < eltsz; i++) { 1486 + if (elts[i].status == 1 && 1487 + strcmp(ac->domain, elts[i].buf) == 0) { 1488 + elts[i].status = 0; 1489 break; 1490 } 1491 - if (ip == NULL) { 1492 - warnx("invalid IP address"); 1493 - continue; 1494 - } 1495 - name_len = asprintf(&name_buf, "%s", ip); 1496 - } else if (gen_name->type == GEN_DNS) { 1497 - name_len = ASN1_STRING_length(gen_name->d.dNSName); 1498 - name_len = asprintf(&name_buf, "%.*s", 1499 - name_len, 1500 - ASN1_STRING_get0_data(gen_name->d.dNSName)); 1501 - } else 1502 - continue; 1503 - 1504 - if (name_len == -1) { 1505 - warn("asprintf"); 1506 - continue; 1507 } 1508 - 1509 - j = 0; 1510 - TAILQ_FOREACH(ac, &domain->altname_list, entry) { 1511 - if (strcmp(name_buf, ac->domain) == 0) { 1512 - found_altnames[j]++; 1513 - break; 1514 - } 1515 - /* increment if didn't match */ 1516 - j++; 1517 - } 1518 - if (j >= domain->altname_count) { 1519 - /* we haven't matched any */ 1520 - if (revocate) { 1521 - char *visbuf; 1522 - 1523 - visbuf = calloc(4, name_len + 1); 1524 - if (visbuf == NULL) { 1525 - warn("%s: unexpected SAN in " 1526 - "certificate", certfile); 1527 - free(name_buf); 1528 - goto out; 1529 - } 1530 - strvisx(visbuf, name_buf, name_len, VIS_SAFE); 1531 - warnx("%s: unexpected SAN entry in " 1532 - "certificate: %s", certfile, visbuf); 1533 - free(visbuf); 1534 - free(name_buf); 1535 - goto out; 1536 - } 1537 - force = 2; 1538 - continue; 1539 - } 1540 - /* should not reach here if j is out of bounds */ 1541 - if (found_altnames[j] > 1) { 1542 + if (i == eltsz) { 1543 if (revocate) { 1544 - char *visbuf; 1545 - visbuf = calloc(4, name_len + 1); 1546 - if (visbuf == NULL) { 1547 - warn("%s: duplicate SAN in " 1548 - "certificate", certfile); 1549 - free(name_buf); 1550 - goto out; 1551 - } 1552 - warnx("%s: duplicate SAN entry in " 1553 - "certificate: %s", certfile, visbuf); 1554 - free(name_buf); 1555 - free(visbuf); 1556 + warnx("%s: domain not listed: %s", certfile, ac->domain); 1557 goto out; 1558 } 1559 force = 2; 1560 } 1561 - 1562 - free(name_buf); 1563 } 1564 1565 - for (j = 0; j < domain->altname_count; j++) { 1566 - struct altname_c *ac; 1567 - 1568 - if (found_altnames[j]) 1569 + for (i = 0; i < eltsz; i++) { 1570 + if (elts[i].status == 0) 1571 continue; 1572 if (revocate) { 1573 - k = 0; 1574 - TAILQ_FOREACH(ac, &domain->altname_list, entry) { 1575 - if (j == k) 1576 - break; 1577 - k++; 1578 + char *visbuf; 1579 + 1580 + if (elts[i].status != 1 || 1581 + stravis(&visbuf, elts[i].buf, VIS_SAFE) < 0) { 1582 + warnx("%s: unexpected SAN", certfile); 1583 + goto out; 1584 } 1585 - warnx("%s: domain not listed: %s", certfile, 1586 - ac->domain); 1587 + warnx("%s: unexpected SAN entry: %s", 1588 + certfile, visbuf); 1589 + free(visbuf); 1590 goto out; 1591 } 1592 force = 2; 1593 @@ -315,16 +254,7 @@ revokeproc(int fd, const char *certfile, int force, 1594 if (cc <= 0) 1595 goto out; 1596 1597 - if ((len = i2d_X509(x, NULL)) < 0) { 1598 - warnx("i2d_X509"); 1599 - goto out; 1600 - } else if ((der = dercp = malloc(len)) == NULL) { 1601 - warn("malloc"); 1602 - goto out; 1603 - } else if (len != i2d_X509(x, &dercp)) { 1604 - warnx("i2d_X509"); 1605 - goto out; 1606 - } else if ((der64 = base64buf_url(der, len)) == NULL) { 1607 + if ((der64 = base64buf_url(cert.data, cert.data_len)) == NULL) { 1608 warnx("base64buf_url"); 1609 goto out; 1610 } else if (writestr(fd, COMM_CSR, der64) >= 0) 1611 @@ -398,12 +328,9 @@ out: 1612 close(fd); 1613 if (f != NULL) 1614 fclose(f); 1615 - X509_free(x); 1616 - GENERAL_NAMES_free(sans); 1617 - free(der); 1618 - free(found_altnames); 1619 + free(cert.data); 1620 + free(sans); 1621 + free(elts); 1622 free(der64); 1623 - ERR_print_errors_fp(stderr); 1624 - ERR_free_strings(); 1625 return rc; 1626 } 1627 -- 1628 2.54.0 1629