logo

oasis

Own branch of Oasis Linux (upstream: <https://git.sr.ht/~mcf/oasis/>) git clone https://anongit.hacktivis.me/git/oasis.git

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


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