1 /*
2 * Copyright (C) 2019-2021 Nicola Di Lieto <nicola.dilieto@gmail.com>
3 *
4 * This file is part of uacme.
5 *
6 * uacme is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * uacme is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <arpa/inet.h>
24 #include <err.h>
25 #include <errno.h>
26 #include <netdb.h>
27 #include <netinet/in.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/stat.h>
33 #include <sys/socket.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36
37 #include "base64.h"
38 #include "crypto.h"
39 #include "curlwrap.h"
40 #include "msg.h"
41 #if !defined(USE_OPENSSL)
42 #include "read-file.h"
43 #endif
44
45 #if defined(USE_GNUTLS)
46 #include <gnutls/crypto.h>
47 #include <gnutls/ocsp.h>
48 #if HAVE_GNUTLS_X509_CRQ_SET_TLSFEATURES
49 #include <gnutls/x509-ext.h>
50 #endif
51 #if !HAVE_GNUTLS_DECODE_RS_VALUE
52 #include <libtasn1.h>
53 #endif
54 #elif defined(USE_OPENSSL)
55 #include <openssl/asn1.h>
56 #include <openssl/bio.h>
57 #include <openssl/bn.h>
58 #include <openssl/crypto.h>
59 #include <openssl/engine.h>
60 #include <openssl/err.h>
61 #include <openssl/evp.h>
62 #include <openssl/hmac.h>
63 #include <openssl/ocsp.h>
64 #include <openssl/opensslv.h>
65 #include <openssl/pem.h>
66 #include <openssl/rsa.h>
67 #include <openssl/ssl.h>
68 #include <openssl/x509.h>
69 #include <openssl/x509v3.h>
70 #elif defined(USE_MBEDTLS)
71 #include <mbedtls/asn1write.h>
72 #include <mbedtls/base64.h>
73 #include <mbedtls/ctr_drbg.h>
74 #include <mbedtls/entropy.h>
75 #include <mbedtls/error.h>
76 #include <mbedtls/md.h>
77 #include <mbedtls/oid.h>
78 #include <mbedtls/pem.h>
79 #include <mbedtls/pk.h>
80 #include <mbedtls/platform.h>
81 #include <mbedtls/sha1.h>
82 #include <mbedtls/version.h>
83 #include <mbedtls/x509_crt.h>
84 #include <mbedtls/x509_csr.h>
85 #endif
86
87 #if defined(USE_GNUTLS)
88 #if GNUTLS_VERSION_NUMBER < 0x03031e
89 #error GnuTLS version 3.3.30 or later is required
90 #endif
91
crypto_init(void)92 bool crypto_init(void)
93 {
94 #if HAVE_GNUTLS_DECODE_RS_VALUE
95 if (!gnutls_check_version("3.6.0")) {
96 warnx("crypto_init: GnuTLS version 3.6.0 or later is required");
97 #elif HAVE_GNUTLS_X509_CRQ_SET_TLSFEATURES
98 if (!gnutls_check_version("3.5.1")) {
99 warnx("crypto_init: GnuTLS version 3.5.1 or later is required");
100 #else
101 if (!gnutls_check_version("3.3.30")) {
102 warnx("crypto_init: GnuTLS version 3.3.30 or later is required");
103 #endif
104 return false;
105 }
106 gnutls_global_init();
107 return true;
108 }
109
110 void crypto_deinit(void)
111 {
112 gnutls_global_deinit();
113 }
114 #elif defined(USE_OPENSSL)
115 #if OPENSSL_VERSION_NUMBER < 0x1010100fL
116 #error OpenSSL version 1.1.1 or later is required
117 #endif
118
119 bool crypto_init(void)
120 {
121 if (OpenSSL_version_num() < 0x1010100fL) {
122 warnx("crypto_init: openssl version 1.1.1 or later is required");
123 return false;
124 }
125 return true;
126 }
127
128 void crypto_deinit(void)
129 {
130 }
131
132 static void openssl_error(const char *prefix)
133 {
134 unsigned long e;
135 while ((e = ERR_get_error()) != 0) {
136 warnx("%s: openssl %s", prefix, ERR_error_string(e, NULL));
137 return;
138 }
139 }
140
141 static bool openssl_hash_fast(const EVP_MD *type,
142 const void *input, size_t len, unsigned char *output)
143 {
144 bool success = false;
145 EVP_MD_CTX *emc = EVP_MD_CTX_create();
146 if (!emc) {
147 openssl_error("openssl_hash_fast");
148 goto out;
149 }
150 if (!EVP_DigestInit_ex(emc, type, NULL)) {
151 openssl_error("openssl_hash_fast");
152 goto out;
153 }
154 if (!EVP_DigestUpdate(emc, input, len)) {
155 openssl_error("openssl_hash_fast");
156 goto out;
157 }
158 if (!EVP_DigestFinal_ex(emc, output, NULL)) {
159 openssl_error("openssl_hash_fast");
160 goto out;
161 }
162 success = true;
163 out:
164 if (emc)
165 EVP_MD_CTX_destroy(emc);
166 return success;
167 }
168
169 static bool openssl_hmac_fast(const EVP_MD *type, const void *key,
170 size_t keylen, const void *input, size_t len, unsigned char *output)
171 {
172 bool success = false;
173 HMAC_CTX *hmac = HMAC_CTX_new();
174 if (!hmac) {
175 openssl_error("openssl_hmac_fast");
176 goto out;
177 }
178 if (!HMAC_Init_ex(hmac, key, keylen, type, NULL)) {
179 openssl_error("openssl_hmac_fast");
180 goto out;
181 }
182 if (!HMAC_Update(hmac, input, len)) {
183 openssl_error("openssl_hmac_fast");
184 goto out;
185 }
186 if (!HMAC_Final(hmac, output, NULL)) {
187 openssl_error("openssl_hmac_fast");
188 goto out;
189 }
190 success = true;
191 out:
192 if (hmac)
193 HMAC_CTX_free(hmac);
194 return success;
195 }
196 #elif defined(USE_MBEDTLS)
197 #if MBEDTLS_VERSION_NUMBER < 0x02100000
198 #error mbedTLS version 2.16 or later is required
199 #endif
200
201 static mbedtls_entropy_context entropy;
202 static mbedtls_ctr_drbg_context ctr_drbg;
203
204 static const char *_mbedtls_strerror(int code)
205 {
206 static char buf[0x100];
207 mbedtls_strerror(code, buf, sizeof(buf));
208 return buf;
209 }
210
211 bool crypto_init(void)
212 {
213 #if defined(MBEDTLS_VERSION_C)
214 if (mbedtls_version_get_number() < 0x02100000) {
215 warnx("crypto_init: mbedTLS version 2.16 or later is required");
216 return false;
217 }
218 #endif
219 mbedtls_entropy_init(&entropy);
220 mbedtls_ctr_drbg_init(&ctr_drbg);
221 int r = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
222 &entropy, NULL, 0);
223 if (r) {
224 warnx("crypto_init: mbedtls_ctr_dbg_seed failed: %s",
225 _mbedtls_strerror(r));
226 return false;
227 }
228 return true;
229 }
230
231 void crypto_deinit(void)
232 {
233 mbedtls_ctr_drbg_free(&ctr_drbg);
234 mbedtls_entropy_free(&entropy);
235 }
236
237 static int mbedtls_hash_fast(mbedtls_md_type_t md_type,
238 const void *input, size_t len, unsigned char *output)
239 {
240 const mbedtls_md_info_t *mdi = mbedtls_md_info_from_type(md_type);
241 if (!mdi) {
242 warnx("mbedtls_hash_fast: md_info not found");
243 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
244 }
245 return mbedtls_md(mdi, input, len, output);
246 }
247
248 static int mbedtls_hmac_fast(mbedtls_md_type_t md_type, const void *key,
249 size_t keylen, const void *input, size_t len, unsigned char *output)
250 {
251 const mbedtls_md_info_t *mdi = mbedtls_md_info_from_type(md_type);
252 if (!mdi) {
253 warnx("mbedtls_hmac_fast: md_info not found");
254 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
255 }
256 return mbedtls_md_hmac(mdi, key, keylen, input, len, output);
257 }
258 #endif
259
260 char *sha2_base64url(size_t bits, const char *format, ...)
261 {
262 char *input = NULL;
263 size_t encoded_hash_len;
264 char *encoded_hash = NULL;
265 const unsigned int hash_len = (bits+7)/8;
266 unsigned char *hash = NULL;
267 va_list ap;
268 va_start(ap, format);
269 if (vasprintf(&input, format, ap) < 0) {
270 warnx("sha2_base64url: vasprintf failed");
271 input = NULL;
272 goto out;
273 }
274
275 hash = calloc(1, hash_len);
276 if (!hash) {
277 warn("sha2_base64url: calloc failed");
278 goto out;
279 }
280
281 #if defined(USE_GNUTLS)
282 gnutls_digest_algorithm_t type;
283 #elif defined(USE_OPENSSL)
284 const EVP_MD *type;
285 #elif defined(USE_MBEDTLS)
286 mbedtls_md_type_t type;
287 #endif
288 switch (bits) {
289 case 256:
290 #if defined(USE_GNUTLS)
291 type = GNUTLS_DIG_SHA256;
292 #elif defined(USE_OPENSSL)
293 type = EVP_sha256();
294 #elif defined(USE_MBEDTLS)
295 type = MBEDTLS_MD_SHA256;
296 #endif
297 break;
298
299 case 384:
300 #if defined(USE_GNUTLS)
301 type = GNUTLS_DIG_SHA384;
302 #elif defined(USE_OPENSSL)
303 type = EVP_sha384();
304 #elif defined(USE_MBEDTLS)
305 type = MBEDTLS_MD_SHA384;
306 #endif
307 break;
308
309 default:
310 warnx("sha2_base64url: invalid hash bit length");
311 goto out;
312 }
313
314 #if defined(USE_GNUTLS)
315 int r = gnutls_hash_fast(type, input, strlen(input), hash);
316 if (r != GNUTLS_E_SUCCESS) {
317 warnx("sha2_base64url: gnutls_hash_fast failed: %s",
318 gnutls_strerror(r));
319 goto out;
320 }
321 #elif defined(USE_OPENSSL)
322 if (!openssl_hash_fast(type, input, strlen(input), hash)) {
323 warnx("sha2_base64url: openssl_hash_fast failed");
324 goto out;
325 }
326 #elif defined(USE_MBEDTLS)
327 int r = mbedtls_hash_fast(type, input, strlen(input), hash);
328 if (r != 0) {
329 warnx("sha2_base64url: mbedtls_hash_fast failed: %s",
330 _mbedtls_strerror(r));
331 goto out;
332 }
333 #endif
334 encoded_hash_len = base64_ENCODED_LEN(hash_len,
335 base64_VARIANT_URLSAFE_NO_PADDING);
336 encoded_hash = calloc(1, encoded_hash_len);
337 if (!encoded_hash) {
338 warn("sha2_base64url: calloc failed");
339 goto out;
340 }
341 if (!bin2base64(encoded_hash, encoded_hash_len,
342 hash, hash_len, base64_VARIANT_URLSAFE_NO_PADDING)) {
343 warnx("sha2_base64url: bin2base64 failed");
344 free(encoded_hash);
345 encoded_hash = NULL;
346 goto out;
347 }
348 out:
349 va_end(ap);
350 free(input);
351 free(hash);
352 return encoded_hash;
353 }
354
355 char *hmac_base64url(size_t bits, const char *key, const char *format, ...)
356 {
357 char *input = NULL;
358 size_t encoded_hash_len;
359 char *encoded_hash = NULL;
360 const unsigned int hash_len = (bits+7)/8;
361 unsigned char *hash = NULL;
362 size_t keylen = strlen(key);
363 void *keybin = NULL;
364 va_list ap;
365 va_start(ap, format);
366 if (vasprintf(&input, format, ap) < 0) {
367 warnx("hmac_base64url: vasprintf failed");
368 input = NULL;
369 goto out;
370 }
371
372 hash = calloc(1, hash_len);
373 if (!hash) {
374 warn("hmac_base64url: calloc failed");
375 goto out;
376 }
377
378 keybin = calloc(1, keylen);
379 if (!keybin) {
380 warn("hmac_base64url: calloc failed");
381 goto out;
382 }
383
384 if (base642bin(keybin, keylen, key, keylen, NULL, &keylen, NULL,
385 base64_VARIANT_URLSAFE_NO_PADDING)) {
386 warnx("hmac_base64url: failed to decode key");
387 goto out;
388 }
389
390 #if defined(USE_GNUTLS)
391 gnutls_mac_algorithm_t type;
392 #elif defined(USE_OPENSSL)
393 const EVP_MD *type;
394 #elif defined(USE_MBEDTLS)
395 mbedtls_md_type_t type;
396 #endif
397 switch (bits) {
398 case 256:
399 #if defined(USE_GNUTLS)
400 type = GNUTLS_MAC_SHA256;
401 #elif defined(USE_OPENSSL)
402 type = EVP_sha256();
403 #elif defined(USE_MBEDTLS)
404 type = MBEDTLS_MD_SHA256;
405 #endif
406 break;
407
408 case 384:
409 #if defined(USE_GNUTLS)
410 type = GNUTLS_MAC_SHA384;
411 #elif defined(USE_OPENSSL)
412 type = EVP_sha384();
413 #elif defined(USE_MBEDTLS)
414 type = MBEDTLS_MD_SHA384;
415 #endif
416 break;
417
418 case 512:
419 #if defined(USE_GNUTLS)
420 type = GNUTLS_MAC_SHA512;
421 #elif defined(USE_OPENSSL)
422 type = EVP_sha512();
423 #elif defined(USE_MBEDTLS)
424 type = MBEDTLS_MD_SHA512;
425 #endif
426 break;
427
428 default:
429 warnx("hmac_base64url: invalid hmac bit length");
430 goto out;
431 }
432
433 #if defined(USE_GNUTLS)
434 int r = gnutls_hmac_fast(type, keybin, keylen, input, strlen(input), hash);
435 if (r != GNUTLS_E_SUCCESS) {
436 warnx("hmac_base64url: gnutls_hmac_fast failed: %s",
437 gnutls_strerror(r));
438 goto out;
439 }
440 #elif defined(USE_OPENSSL)
441 if (!openssl_hmac_fast(type, keybin, keylen, input, strlen(input), hash)) {
442 warnx("hmac_base64url: openssl_hmac_fast failed");
443 goto out;
444 }
445 #elif defined(USE_MBEDTLS)
446 int r = mbedtls_hmac_fast(type, keybin, keylen, input, strlen(input), hash);
447 if (r != 0) {
448 warnx("hmac_base64url: mbedtls_hmac_fast failed: %s",
449 _mbedtls_strerror(r));
450 goto out;
451 }
452 #endif
453 encoded_hash_len = base64_ENCODED_LEN(hash_len,
454 base64_VARIANT_URLSAFE_NO_PADDING);
455 encoded_hash = calloc(1, encoded_hash_len);
456 if (!encoded_hash) {
457 warn("hmac_base64url: calloc failed");
458 goto out;
459 }
460 if (!bin2base64(encoded_hash, encoded_hash_len,
461 hash, hash_len, base64_VARIANT_URLSAFE_NO_PADDING)) {
462 warnx("hmac_base64url: bin2base64 failed");
463 free(encoded_hash);
464 encoded_hash = NULL;
465 goto out;
466 }
467 out:
468 va_end(ap);
469 free(input);
470 free(hash);
471 free(keybin);
472 return encoded_hash;
473 }
474
475 static char *bn2str(const unsigned char *data, size_t data_len, size_t pad_len)
476 {
477 char *ret = NULL;
478 unsigned char *buf = NULL;
479
480 while (data_len && !*data) {
481 data++;
482 data_len--;
483 }
484
485 if (pad_len == 0)
486 pad_len = data_len;
487 else if (pad_len < data_len) {
488 warnx("bn2str: insufficient pad_len");
489 goto out;
490 }
491
492 buf = calloc(1, pad_len);
493 if (!buf) {
494 warn("bn2str: calloc failed");
495 goto out;
496 }
497 memcpy(buf + pad_len - data_len, data, data_len);
498
499 size_t encoded_len = base64_ENCODED_LEN(pad_len,
500 base64_VARIANT_URLSAFE_NO_PADDING);
501 ret = calloc(1, encoded_len);
502 if (!ret) {
503 warn("bn2str: calloc failed");
504 goto out;
505 }
506 if (!bin2base64(ret, encoded_len, buf, pad_len,
507 base64_VARIANT_URLSAFE_NO_PADDING)) {
508 free(ret);
509 ret = NULL;
510 }
511 out:
512 free(buf);
513 return ret;
514 }
515
516 static bool rsa_params(privkey_t key, char **m, char **e)
517 {
518 int r;
519 char *_m = NULL;
520 char *_e = NULL;
521 #if defined(USE_GNUTLS)
522 gnutls_datum_t mod = {NULL, 0};
523 gnutls_datum_t exp = {NULL, 0};
524 if (gnutls_privkey_get_pk_algorithm(key, NULL) != GNUTLS_PK_RSA) {
525 warnx("rsa_params: not a RSA key");
526 goto out;
527 }
528 r = gnutls_privkey_export_rsa_raw(key, &mod, &exp,
529 NULL, NULL, NULL, NULL, NULL, NULL);
530 if (r < 0) {
531 warnx("rsa_params: gnutls_privkey_export_rsa_raw: %s",
532 gnutls_strerror(r));
533 goto out;
534 }
535 _m = bn2str(mod.data, mod.size, 0);
536 if (!_m) {
537 warnx("rsa_params: bn2str failed");
538 goto out;
539 }
540 _e = bn2str(exp.data, exp.size, 0);
541 if (!_e) {
542 warnx("rsa_params: bn2str failed");
543 goto out;
544 }
545 #elif defined(USE_OPENSSL)
546 unsigned char *data = NULL;
547 RSA *rsa = EVP_PKEY_get0_RSA(key);
548 if (!rsa) {
549 openssl_error("rsa_params");
550 goto out;
551 }
552 r = BN_num_bytes(RSA_get0_n(rsa));
553 data = calloc(1, r);
554 if (!data) {
555 warn("rsa_params: calloc failed");
556 goto out;
557 }
558 if (BN_bn2bin(RSA_get0_n(rsa), data) != r) {
559 openssl_error("rsa_params");
560 goto out;
561 }
562 _m = bn2str(data, r, 0);
563 if (!_m) {
564 warnx("rsa_params: bn2str failed");
565 goto out;
566 }
567 free(data);
568 r = BN_num_bytes(RSA_get0_e(rsa));
569 data = calloc(1, r);
570 if (!data) {
571 warn("rsa_params: calloc failed");
572 goto out;
573 }
574 if (BN_bn2bin(RSA_get0_e(rsa), data) != r) {
575 openssl_error("rsa_params");
576 goto out;
577 }
578 _e = bn2str(data, r, 0);
579 if (!_e) {
580 warnx("rsa_params: bn2str failed");
581 goto out;
582 }
583 #elif defined(USE_MBEDTLS)
584 unsigned char *data = NULL;
585 size_t len;
586 if (!mbedtls_pk_can_do(key, MBEDTLS_PK_RSA)) {
587 warnx("rsa_params: not a RSA key");
588 goto out;
589 }
590 const mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key);
591 len = mbedtls_mpi_size(&rsa->N);
592 data = calloc(1, len);
593 if (!data) {
594 warnx("rsa_params: calloc failed");
595 goto out;
596 }
597 r = mbedtls_mpi_write_binary(&rsa->N, data, len);
598 if (r) {
599 warnx("rsa_params: mbedtls_mpi_write_binary failed: %s",
600 _mbedtls_strerror(r));
601 goto out;
602 }
603 _m = bn2str(data, len, 0);
604 if (!_m) {
605 warnx("rsa_params: bn2str failed");
606 goto out;
607 }
608 free(data);
609 len = mbedtls_mpi_size(&rsa->E);
610 data = calloc(1, len);
611 if (!data) {
612 warnx("rsa_params: calloc failed");
613 goto out;
614 }
615 r = mbedtls_mpi_write_binary(&rsa->E, data, len);
616 if (r) {
617 warnx("rsa_params: mbedtls_mpi_write_binary failed: %s",
618 _mbedtls_strerror(r));
619 goto out;
620 }
621 _e = bn2str(data, len, 0);
622 if (!_e) {
623 warnx("rsa_params: bn2str failed");
624 goto out;
625 }
626 #endif
627 out:
628 #if defined(USE_GNUTLS)
629 free(mod.data);
630 free(exp.data);
631 #elif defined(USE_OPENSSL)
632 free(data);
633 #elif defined(USE_MBEDTLS)
634 free(data);
635 #endif
636 if (_e && _m) {
637 if (e)
638 *e = _e;
639 else
640 free(_e);
641 if (m)
642 *m = _m;
643 else
644 free(_m);
645 return true;
646 } else {
647 free(_e);
648 free(_m);
649 return false;
650 }
651 }
652
653 static size_t ec_params(privkey_t key, char **x, char **y)
654 {
655 int r;
656 size_t bits = 0;
657 char *_x = NULL;
658 char *_y = NULL;
659 #if defined(USE_GNUTLS)
660 gnutls_ecc_curve_t curve;
661 gnutls_datum_t dx = {NULL, 0};
662 gnutls_datum_t dy = {NULL, 0};
663 if (gnutls_privkey_get_pk_algorithm(key, NULL) != GNUTLS_PK_EC) {
664 warnx("ec_params: not a EC key");
665 goto out;
666 }
667 r = gnutls_privkey_export_ecc_raw(key, &curve, &dx, &dy, NULL);
668 if (r < 0) {
669 warnx("ec_params: gnutls_privkey_export_ecc_raw: %s",
670 gnutls_strerror(r));
671 goto out;
672 }
673 switch (curve) {
674 case GNUTLS_ECC_CURVE_SECP256R1:
675 bits = 256;
676 break;
677
678 case GNUTLS_ECC_CURVE_SECP384R1:
679 bits = 384;
680 break;
681
682 default:
683 warnx("ec_params: only \"prime256v1\" and \"secp384r1\" "
684 "Elliptic Curves supported");
685 goto out;
686 }
687 _x = bn2str(dx.data, dx.size, (bits+7)/8);
688 if (!_x) {
689 warnx("ec_params: bn2str failed");
690 goto out;
691 }
692 _y = bn2str(dy.data, dy.size, (bits+7)/8);
693 if (!_y) {
694 warnx("ec_params: bn2str failed");
695 goto out;
696 }
697 #elif defined(USE_OPENSSL)
698 unsigned char *data = NULL;
699 BIGNUM *bx = BN_new();
700 BIGNUM *by = BN_new();
701 if (!bx || !by) {
702 openssl_error("ec_params");
703 goto out;
704 }
705 EC_KEY *ec = EVP_PKEY_get0_EC_KEY(key);
706 if (!ec) {
707 openssl_error("ec_params");
708 goto out;
709 }
710 const EC_GROUP *g = EC_KEY_get0_group(ec);
711 if (!g) {
712 openssl_error("ec_params");
713 }
714 switch (EC_GROUP_get_curve_name(g)) {
715 case NID_X9_62_prime256v1:
716 bits = 256;
717 break;
718
719 case NID_secp384r1:
720 bits = 384;
721 break;
722
723 default:
724 warnx("ec_params: only \"prime256v1\" and \"secp384r1\" "
725 "Elliptic Curves supported");
726 goto out;
727 }
728 const EC_POINT *pubkey = EC_KEY_get0_public_key(ec);
729 if (!pubkey) {
730 openssl_error("ec_params");
731 goto out;
732 }
733 if (!EC_POINT_get_affine_coordinates(g, pubkey, bx, by, NULL)) {
734 openssl_error("ec_params");
735 goto out;
736 }
737 r = BN_num_bytes(bx);
738 data = calloc(1, r);
739 if (!data) {
740 warn("ec_params: calloc failed");
741 goto out;
742 }
743 if (BN_bn2bin(bx, data) != r) {
744 openssl_error("ec_params");
745 goto out;
746 }
747 _x = bn2str(data, r, (bits+7)/8);
748 if (!_x) {
749 warnx("ec_params: bn2str failed");
750 goto out;
751 }
752 free(data);
753 r = BN_num_bytes(by);
754 data = calloc(1, r);
755 if (!data) {
756 warn("ec_params: calloc failed");
757 goto out;
758 }
759 if (BN_bn2bin(by, data) != r) {
760 openssl_error("ec_params");
761 goto out;
762 }
763 _y = bn2str(data, r, (bits+7)/8);
764 if (!_y) {
765 warnx("ec_params: bn2str failed");
766 goto out;
767 }
768 #elif defined(USE_MBEDTLS)
769 unsigned char *data = NULL;
770 size_t len;
771 if (!mbedtls_pk_can_do(key, MBEDTLS_PK_ECKEY)) {
772 warnx("ec_params: not a EC key");
773 goto out;
774 }
775 const mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key);
776 switch (ec->grp.id) {
777 case MBEDTLS_ECP_DP_SECP256R1:
778 bits = 256;
779 break;
780
781 case MBEDTLS_ECP_DP_SECP384R1:
782 bits = 384;
783 break;
784
785 default:
786 warnx("ec_params: only \"prime256v1\" and \"secp384r1\" "
787 "Elliptic Curves supported");
788 goto out;
789 }
790 len = mbedtls_mpi_size(&ec->Q.X);
791 data = calloc(1, len);
792 if (!data) {
793 warnx("ec_params: calloc failed");
794 goto out;
795 }
796 r = mbedtls_mpi_write_binary(&ec->Q.X, data, len);
797 if (r) {
798 warnx("ec_params: mbedtls_mpi_write_binary failed: %s",
799 _mbedtls_strerror(r));
800 goto out;
801 }
802 _x = bn2str(data, len, (bits+7)/8);
803 if (!_x) {
804 warnx("ec_params: bn2str failed");
805 goto out;
806 }
807 free(data);
808 len = mbedtls_mpi_size(&ec->Q.Y);
809 data = calloc(1, len);
810 if (!data) {
811 warnx("ec_params: calloc failed");
812 goto out;
813 }
814 r = mbedtls_mpi_write_binary(&ec->Q.Y, data, len);
815 if (r) {
816 warnx("ec_params: mbedtls_mpi_write_binary failed: %s",
817 _mbedtls_strerror(r));
818 goto out;
819 }
820 _y = bn2str(data, len, (bits+7)/8);
821 if (!_y) {
822 warnx("ec_params: bn2str failed");
823 goto out;
824 }
825 #endif
826 out:
827 #if defined(USE_GNUTLS)
828 free(dx.data);
829 free(dy.data);
830 #elif defined(USE_OPENSSL)
831 if (bx)
832 BN_free(bx);
833 if (by)
834 BN_free(by);
835 free(data);
836 #elif defined(USE_MBEDTLS)
837 free(data);
838 #endif
839 if (_x && _y) {
840 if (x)
841 *x = _x;
842 else
843 free(_x);
844 if (y)
845 *y = _y;
846 else
847 free(_y);
848 return bits;
849 } else {
850 free(_x);
851 free(_y);
852 return 0;
853 }
854 }
855
856 keytype_t key_type(privkey_t key)
857 {
858 #if defined(USE_GNUTLS)
859 switch (gnutls_privkey_get_pk_algorithm(key, NULL)) {
860 case GNUTLS_PK_RSA:
861 return PK_RSA;
862 case GNUTLS_PK_EC:
863 return PK_EC;
864 #elif defined(USE_OPENSSL)
865 switch (EVP_PKEY_base_id(key)) {
866 case EVP_PKEY_RSA:
867 return PK_RSA;
868 case EVP_PKEY_EC:
869 return PK_EC;
870 #elif defined(USE_MBEDTLS)
871 switch (mbedtls_pk_get_type(key)) {
872 case MBEDTLS_PK_RSA:
873 return PK_RSA;
874 case MBEDTLS_PK_ECKEY:
875 return PK_EC;
876 #endif
877 default:
878 return PK_NONE;
879 }
880 }
881
882 char *jws_jwk(privkey_t key, const char **crv, const char **alg)
883 {
884 char *ret = NULL;
885 char *p1 = NULL;
886 char *p2 = NULL;
887 const char *_crv = NULL;
888 switch (key_type(key)) {
889 case PK_RSA:
890 if (!rsa_params(key, &p1, &p2)) {
891 warnx("jws_jwk: rsa_params failed");
892 goto out;
893 }
894 if (asprintf(&ret, "{\"kty\":\"RSA\",\"n\":\"%s\",\"e\":\"%s\"}",
895 p1, p2) < 0) {
896 warnx("jws_jwk: asprintf failed");
897 ret = NULL;
898 goto out;
899 }
900 if (alg) *alg = "RS256";
901 break;
902
903 case PK_EC:
904 switch (ec_params(key, &p1, &p2)) {
905 case 0:
906 warnx("jws_jwk: ec_params failed");
907 goto out;
908
909 case 256:
910 _crv = "P-256";
911 if (crv) *crv = _crv;
912 if (alg) *alg = "ES256";
913 break;
914
915 case 384:
916 _crv = "P-384";
917 if (crv) *crv = _crv;
918 if (alg) *alg = "ES384";
919 break;
920
921 default:
922 warnx("jws_jwk: unsupported EC curve");
923 goto out;
924 }
925 if (asprintf(&ret, "{\"kty\":\"EC\",\"crv\":\"%s\","
926 "\"x\":\"%s\",\"y\":\"%s\"}", _crv, p1, p2) < 0) {
927 warnx("jws_jwk: asprintf failed");
928 ret = NULL;
929 goto out;
930 }
931 break;
932
933 default:
934 warnx("jws_jwk: only RSA/EC keys are supported");
935 goto out;
936 }
937 out:
938 free(p1);
939 free(p2);
940 return ret;
941 }
942
943 char *jws_protected_jwk(const char *nonce, const char *url,
944 privkey_t key)
945 {
946 char *ret = NULL;
947 const char *crv = NULL;
948 const char *alg = NULL;
949 char *jwk = jws_jwk(key, &crv, &alg);
950 if (!jwk) {
951 warnx("jws_protected_jwk: jws_jwk failed");
952 goto out;
953 }
954
955 if (nonce) {
956 if (asprintf(&ret, "{\"alg\":\"%s\",\"nonce\":\"%s\","
957 "\"url\":\"%s\",\"jwk\":%s}", alg, nonce, url, jwk) < 0) {
958 warnx("jws_protected_jwk: asprintf failed");
959 ret = NULL;
960 }
961 } else {
962 if (asprintf(&ret, "{\"alg\":\"%s\",\"url\":\"%s\",\"jwk\":%s}",
963 alg, url, jwk) < 0) {
964 warnx("jws_protected_jwk: asprintf failed");
965 ret = NULL;
966 }
967 }
968 out:
969 free(jwk);
970 return ret;
971 }
972
973 char *jws_protected_kid(const char *nonce, const char *url,
974 const char *kid, privkey_t key)
975 {
976 char *ret = NULL;
977 const char *alg = NULL;
978 switch (key_type(key)) {
979 case PK_RSA:
980 alg = "RS256";
981 break;
982
983 case PK_EC:
984 switch (ec_params(key, NULL, NULL)) {
985 case 0:
986 warnx("jws_protected_kid: ec_params failed");
987 goto out;
988
989 case 256:
990 alg = "ES256";
991 break;
992
993 case 384:
994 alg = "ES384";
995 break;
996
997 default:
998 warnx("jws_protected_kid: unsupported EC curve");
999 goto out;
1000 }
1001 break;
1002
1003 default:
1004 warnx("jws_protected_kid: only RSA/EC keys are supported");
1005 goto out;
1006 }
1007 if (asprintf(&ret, "{\"alg\":\"%s\",\"nonce\":\"%s\","
1008 "\"url\":\"%s\",\"kid\":\"%s\"}", alg, nonce, url, kid) < 0) {
1009 warnx("jws_protected_kid: asprintf failed");
1010 ret = NULL;
1011 }
1012 out:
1013 return ret;
1014 }
1015
1016 char *jws_protected_eab(size_t bits, const char *keyid, const char *url)
1017 {
1018 char *ret = NULL;
1019 if (asprintf(&ret, "{\"alg\":\"HS%zu\",\"kid\":\"%s\",\"url\":\"%s\"}",
1020 bits, keyid, url) < 0) {
1021 warnx("jws_protected_eab: asprintf failed");
1022 ret = NULL;
1023 }
1024 return ret;
1025 }
1026
1027 char *jws_thumbprint(privkey_t key)
1028 {
1029 char *ret = NULL;
1030 char *p1 = NULL;
1031 char *p2 = NULL;
1032 const char *crv = NULL;
1033 switch (key_type(key)) {
1034 case PK_RSA:
1035 if (!rsa_params(key, &p1, &p2)) {
1036 warnx("jws_thumbprint: rsa_params failed");
1037 goto out;
1038 }
1039 ret = sha2_base64url(256, "{\"e\":\"%s\",\"kty\":\"RSA\","
1040 "\"n\":\"%s\"}", p2, p1);
1041 if (!ret)
1042 warnx("jws_thumbprint: sha2_base64url failed");
1043 break;
1044
1045 case PK_EC:
1046 switch (ec_params(key, &p1, &p2)) {
1047 case 0:
1048 warnx("jws_thumbprint: ec_params failed");
1049 goto out;
1050
1051 case 256:
1052 crv = "P-256";
1053 break;
1054
1055 case 384:
1056 crv = "P-384";
1057 break;
1058
1059 default:
1060 warnx("jws_thumbprint: unsupported EC curve");
1061 goto out;
1062 }
1063 ret = sha2_base64url(256, "{\"crv\":\"%s\",\"kty\":\"EC\","
1064 "\"x\":\"%s\",\"y\":\"%s\"}", crv, p1, p2);
1065 if (!ret)
1066 warnx("jws_thumbprint: sha2_base64url failed");
1067 break;
1068
1069 default:
1070 warnx("jws_thumbprint: only RSA/EC keys are supported");
1071 goto out;
1072 }
1073 out:
1074 free(p1);
1075 free(p2);
1076 return ret;
1077 }
1078
1079 #if defined(USE_GNUTLS)
1080 static unsigned char *gnutls_datum_data(gnutls_datum_t *d, bool free)
1081 {
1082 unsigned char *ret = malloc(d->size);
1083 if (!ret) {
1084 warn("gnutls_datum2mem: malloc failed");
1085 goto out;
1086 }
1087 memcpy(ret, d->data, d->size);
1088 if (free) {
1089 gnutls_free(d->data);
1090 d->data = NULL;
1091 }
1092 out:
1093 return ret;
1094 }
1095 #endif
1096
1097 bool ec_decode(size_t hash_size, unsigned char **sig, size_t *sig_size)
1098 {
1099 int r;
1100 #if defined(USE_GNUTLS)
1101 #if HAVE_GNUTLS_DECODE_RS_VALUE
1102 gnutls_datum_t dr = {NULL, 0};
1103 gnutls_datum_t ds = {NULL, 0};
1104 gnutls_datum_t dsig = {*sig, *sig_size};
1105 r = gnutls_decode_rs_value(&dsig, &dr, &ds);
1106 if (r < 0) {
1107 warnx("ec_decode: gnutls_decode_rs_value: %s", gnutls_strerror(r));
1108 return false;
1109 }
1110 unsigned char *tmp = calloc(1, 2*hash_size);
1111 if (!tmp) {
1112 warn("ec_decode: calloc failed");
1113 gnutls_free(dr.data);
1114 gnutls_free(ds.data);
1115 return false;
1116 }
1117 if (dr.size >= hash_size)
1118 memcpy(tmp, dr.data + dr.size - hash_size, hash_size);
1119 else
1120 memcpy(tmp + hash_size - dr.size, dr.data, dr.size);
1121 if (ds.size >= hash_size)
1122 memcpy(tmp + hash_size, ds.data + ds.size - hash_size, hash_size);
1123 else
1124 memcpy(tmp + 2*hash_size - ds.size, ds.data, ds.size);
1125 gnutls_free(dr.data);
1126 gnutls_free(ds.data);
1127 #else
1128 int len;
1129 const unsigned char *p = *sig;
1130 int ps = *sig_size;
1131 unsigned long tag;
1132 unsigned char cls;
1133
1134 r = asn1_get_tag_der(p, ps, &cls, &len, &tag);
1135 if (r != ASN1_SUCCESS) {
1136 warnx("ec_decode: asn1_get_tag_der: %s", asn1_strerror(r));
1137 return false;
1138 }
1139 if (cls != ASN1_CLASS_STRUCTURED || tag != ASN1_TAG_SEQUENCE) {
1140 warnx("ec_decode: unexpected ASN1 tag");
1141 return false;
1142 }
1143 p += len;
1144 ps -= len;
1145
1146 r = asn1_get_length_der(p, ps, &len);
1147 if (r < 0) {
1148 warnx("ec_decode: asn1_get_length_der: %d", r);
1149 return false;
1150 }
1151 p += len;
1152 ps -= len;
1153
1154 if (p + r != *sig + *sig_size) {
1155 warnx("ec_decode: signature lenght mismatch");
1156 return false;
1157 }
1158
1159 unsigned char *tmp = calloc(1, 2*hash_size);
1160 if (!tmp) {
1161 warn("ec_decode: calloc failed");
1162 return false;
1163 }
1164
1165 r = asn1_get_tag_der(p, ps, &cls, &len, &tag);
1166 if (r != ASN1_SUCCESS) {
1167 warnx("ec_decode: asn1_get_tag_der: %s", asn1_strerror(r));
1168 free(tmp);
1169 return false;
1170 }
1171 if (cls != ASN1_CLASS_UNIVERSAL || tag != ASN1_TAG_INTEGER) {
1172 warnx("ec_decode: unexpected ASN1 tag");
1173 free(tmp);
1174 return false;
1175 }
1176 p += len;
1177 ps -= len;
1178
1179 r = asn1_get_length_der(p, ps, &len);
1180 if (r < 0) {
1181 warnx("ec_decode: asn1_get_length_der: %d", r);
1182 free(tmp);
1183 return false;
1184 }
1185 p += len;
1186 ps -= len;
1187
1188 if (r >= (int)hash_size)
1189 memcpy(tmp, p + r - hash_size, hash_size);
1190 else
1191 memcpy(tmp + hash_size - r, p, r);
1192 p += r;
1193 ps -= r;
1194
1195 r = asn1_get_tag_der(p, ps, &cls, &len, &tag);
1196 if (r != ASN1_SUCCESS) {
1197 warnx("ec_decode: asn1_get_tag_der: %s", asn1_strerror(r));
1198 free(tmp);
1199 return false;
1200 }
1201 if (cls != ASN1_CLASS_UNIVERSAL || tag != ASN1_TAG_INTEGER) {
1202 warnx("ec_decode: unexpected ASN1 tag");
1203 free(tmp);
1204 return false;
1205 }
1206 p += len;
1207 ps -= len;
1208
1209 r = asn1_get_length_der(p, ps, &len);
1210 if (r < 0) {
1211 warnx("ec_decode: asn1_get_length_der: %d", r);
1212 free(tmp);
1213 return false;
1214 }
1215 p += len;
1216 ps -= len;
1217
1218 if (r >= (int)hash_size)
1219 memcpy(tmp + hash_size, p + r - hash_size, hash_size);
1220 else
1221 memcpy(tmp + 2*hash_size - r, p, r);
1222 p += r;
1223 ps -= r;
1224
1225 if (ps != 0) {
1226 warnx("ec_decode: signature lenght mismatch");
1227 free(tmp);
1228 return false;
1229 }
1230 #endif
1231 #elif defined(USE_OPENSSL)
1232 const unsigned char *p = *sig;
1233 ECDSA_SIG *s = d2i_ECDSA_SIG(NULL, &p, *sig_size);
1234 if (!s) {
1235 openssl_error("ec_decode");
1236 return false;
1237 }
1238 unsigned char *tmp = calloc(1, 2*hash_size);
1239 if (!tmp) {
1240 warn("ec_decode: calloc failed");
1241 ECDSA_SIG_free(s);
1242 return false;
1243 }
1244 r = BN_num_bytes(ECDSA_SIG_get0_r(s));
1245 unsigned char *data = calloc(1, r);
1246 if (!data) {
1247 warn("ec_decode: calloc failed");
1248 ECDSA_SIG_free(s);
1249 free(tmp);
1250 return false;
1251 }
1252 if (BN_bn2bin(ECDSA_SIG_get0_r(s), data) != r) {
1253 openssl_error("ec_decode");
1254 ECDSA_SIG_free(s);
1255 free(data);
1256 free(tmp);
1257 return false;
1258 }
1259 if (r >= (int)hash_size)
1260 memcpy(tmp, data + r - hash_size, hash_size);
1261 else
1262 memcpy(tmp + hash_size - r, data, r);
1263 free(data);
1264
1265 r = BN_num_bytes(ECDSA_SIG_get0_s(s));
1266 data = calloc(1, r);
1267 if (!data) {
1268 warn("ec_decode: calloc failed");
1269 ECDSA_SIG_free(s);
1270 free(tmp);
1271 return false;
1272 }
1273 if (BN_bn2bin(ECDSA_SIG_get0_s(s), data) != r) {
1274 openssl_error("ec_decode");
1275 ECDSA_SIG_free(s);
1276 free(data);
1277 free(tmp);
1278 return false;
1279 }
1280 if (r >= (int)hash_size)
1281 memcpy(tmp + hash_size, data + r - hash_size, hash_size);
1282 else
1283 memcpy(tmp + 2*hash_size - r, data, r);
1284
1285 ECDSA_SIG_free(s);
1286 free(data);
1287 #elif defined(USE_MBEDTLS)
1288 unsigned char *p = *sig;
1289 const unsigned char *end = p + *sig_size;
1290 size_t len;
1291 r = mbedtls_asn1_get_tag(&p, end, &len,
1292 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
1293 if (r != 0) {
1294 warnx("ec_decode: mbedtls_asn1_get_tag failed: %s",
1295 _mbedtls_strerror(r));
1296 return false;
1297 }
1298 if (p + len != end) {
1299 warnx("ec_decode: signature lenght mismatch");
1300 return false;
1301 }
1302 unsigned char *tmp = calloc(1, 2*hash_size);
1303 if (!tmp) {
1304 warn("ec_decode: calloc failed");
1305 return false;
1306 }
1307 r = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
1308 if (r != 0) {
1309 warnx("ec_decode: mbedtls_asn1_get_tag failed: %s",
1310 _mbedtls_strerror(r));
1311 free(tmp);
1312 return false;
1313 }
1314 if (len >= hash_size)
1315 memcpy(tmp, p + len - hash_size, hash_size);
1316 else
1317 memcpy(tmp + hash_size - len, p, len);
1318 p += len;
1319
1320 r = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
1321 if (r != 0) {
1322 warnx("ec_decode: mbedtls_asn1_get_tag failed: %s",
1323 _mbedtls_strerror(r));
1324 free(tmp);
1325 return false;
1326 }
1327 if (len >= hash_size)
1328 memcpy(tmp + hash_size, p + len - hash_size, hash_size);
1329 else
1330 memcpy(tmp + 2*hash_size - len, p, len);
1331 #endif
1332 free(*sig);
1333 *sig = tmp;
1334 *sig_size = 2*hash_size;
1335 return true;
1336 }
1337
1338 char *jws_encode(const char *protected, const char *payload,
1339 privkey_t key)
1340 {
1341 char *jws = NULL;
1342 char *encoded_payload = encode_base64url(payload);
1343 char *encoded_protected = encode_base64url(protected);
1344 char *encoded_combined = NULL;
1345 unsigned char *signature = NULL;
1346 size_t signature_size = 0;
1347 char *encoded_signature = NULL;
1348 size_t hash_size = 0;
1349 #if defined(USE_GNUTLS)
1350 gnutls_digest_algorithm_t hash_type;
1351 #elif defined(USE_OPENSSL)
1352 EVP_MD_CTX *emc = NULL;
1353 const EVP_MD *hash_type;
1354 unsigned int len;
1355 #elif defined(USE_MBEDTLS)
1356 mbedtls_md_type_t hash_type;
1357 unsigned char *hash = NULL;
1358 #endif
1359
1360 if (!encoded_payload || !encoded_protected) {
1361 warnx("jws_encode: encode_base64url failed");
1362 goto out;
1363 }
1364 if (asprintf(&encoded_combined, "%s.%s", encoded_protected,
1365 encoded_payload) < 0) {
1366 warnx("jws_encode: asprintf failed");
1367 encoded_combined = NULL;
1368 goto out;
1369 }
1370
1371 switch (key_type(key)) {
1372 case PK_RSA:
1373 hash_size = 32;
1374 #if defined(USE_GNUTLS)
1375 hash_type = GNUTLS_DIG_SHA256;
1376 #elif defined(USE_OPENSSL)
1377 hash_type = EVP_sha256();
1378 #elif defined(USE_MBEDTLS)
1379 hash_type = MBEDTLS_MD_SHA256;
1380 #endif
1381 break;
1382
1383 case PK_EC:
1384 switch (ec_params(key, NULL, NULL)) {
1385 case 0:
1386 warnx("jws_encode: ec_params failed");
1387 goto out;
1388
1389 case 256:
1390 hash_size = 32;
1391 #if defined(USE_GNUTLS)
1392 hash_type = GNUTLS_DIG_SHA256;
1393 #elif defined(USE_OPENSSL)
1394 hash_type = EVP_sha256();
1395 #elif defined(USE_MBEDTLS)
1396 hash_type = MBEDTLS_MD_SHA256;
1397 #endif
1398 break;
1399
1400 case 384:
1401 hash_size = 48;
1402 #if defined(USE_GNUTLS)
1403 hash_type = GNUTLS_DIG_SHA384;
1404 #elif defined(USE_OPENSSL)
1405 hash_type = EVP_sha384();
1406 #elif defined(USE_MBEDTLS)
1407 hash_type = MBEDTLS_MD_SHA384;
1408 #endif
1409 break;
1410
1411 default:
1412 warnx("jws_encode: unsupported EC curve");
1413 goto out;
1414 }
1415 break;
1416
1417 default:
1418 warnx("jws_encode: only RSA/EC keys are supported");
1419 goto out;
1420 }
1421
1422 #if defined(USE_GNUTLS)
1423 gnutls_datum_t data = {
1424 (unsigned char *)encoded_combined, strlen(encoded_combined)};
1425 gnutls_datum_t sign = {NULL, 0};
1426 int r = gnutls_privkey_sign_data(key, hash_type, 0, &data, &sign);
1427 if (r != GNUTLS_E_SUCCESS) {
1428 warnx("jws_encode: gnutls_privkey_sign_data: %s", gnutls_strerror(r));
1429 goto out;
1430 }
1431 signature_size = sign.size;
1432 signature = gnutls_datum_data(&sign, true);
1433 if (!signature) {
1434 warnx("jws_encode: gnutls_datum_data failed");
1435 goto out;
1436 }
1437 #elif defined(USE_OPENSSL)
1438 emc = EVP_MD_CTX_create();
1439 if (!emc) {
1440 openssl_error("jws_encode");
1441 goto out;
1442 }
1443 signature = calloc(1, EVP_PKEY_size(key));
1444 if (!signature) {
1445 warn("jws_encode: calloc failed");
1446 goto out;
1447 }
1448 if (!EVP_SignInit_ex(emc, hash_type, NULL)) {
1449 openssl_error("jws_encode");
1450 goto out;
1451 }
1452 if (!EVP_SignUpdate(emc, encoded_combined, strlen(encoded_combined))) {
1453 openssl_error("jws_encode");
1454 goto out;
1455 }
1456 if (!EVP_SignFinal(emc, signature, &len, key)) {
1457 openssl_error("jws_encode");
1458 goto out;
1459 }
1460 signature_size = len;
1461 #elif defined(USE_MBEDTLS)
1462 hash = calloc(1, hash_size);
1463 if (!hash) {
1464 warn("jws_encode: calloc failed");
1465 goto out;
1466 }
1467 int r = mbedtls_hash_fast(hash_type, encoded_combined,
1468 strlen(encoded_combined), hash);
1469 if (r != 0) {
1470 warnx("jws_encode: mbedtls_hash_fast failed: %s",
1471 _mbedtls_strerror(r));
1472 goto out;
1473 }
1474 switch (mbedtls_pk_get_type(key)) {
1475 case MBEDTLS_PK_RSA:
1476 signature = calloc(1, mbedtls_pk_get_len(key));
1477 break;
1478
1479 case MBEDTLS_PK_ECKEY:
1480 signature = calloc(1, 9+2*mbedtls_pk_get_len(key));
1481 break;
1482
1483 default:
1484 warnx("jws_encode: only RSA/EC keys are supported");
1485 goto out;
1486 }
1487 if (!signature) {
1488 warn("jws_encode: calloc failed");
1489 goto out;
1490 }
1491 r = mbedtls_pk_sign(key, hash_type, hash, hash_size, signature,
1492 &signature_size, mbedtls_ctr_drbg_random, &ctr_drbg);
1493 if (r != 0) {
1494 warnx("jws_encode: mbedtls_pk_sign failed: %s",
1495 _mbedtls_strerror(r));
1496 goto out;
1497 }
1498 #endif
1499 if (key_type(key) == PK_EC && !ec_decode(hash_size, &signature,
1500 &signature_size)) {
1501 warnx("jws_encode: ec_decode failed");
1502 goto out;
1503 }
1504 size_t encoded_signature_len = base64_ENCODED_LEN(signature_size,
1505 base64_VARIANT_URLSAFE_NO_PADDING);
1506 encoded_signature = calloc(1, encoded_signature_len);
1507 if (!encoded_signature) {
1508 warn("jws_encode: calloc failed");
1509 goto out;
1510 }
1511 if (!bin2base64(encoded_signature, encoded_signature_len, signature,
1512 signature_size, base64_VARIANT_URLSAFE_NO_PADDING)) {
1513 warnx("jws_encode: bin2base64 failed");
1514 goto out;
1515 }
1516 if (asprintf(&jws,
1517 "{\"protected\":\"%s\","
1518 "\"payload\":\"%s\","
1519 "\"signature\":\"%s\"}",
1520 encoded_protected,
1521 encoded_payload,
1522 encoded_signature) < 0) {
1523 warnx("jws_encode: asprintf failed");
1524 jws = NULL;
1525 }
1526 out:
1527 #if defined(USE_OPENSSL)
1528 if (emc)
1529 EVP_MD_CTX_destroy(emc);
1530 #elif defined(USE_MBEDTLS)
1531 free(hash);
1532 #endif
1533 free(encoded_payload);
1534 free(encoded_protected);
1535 free(encoded_combined);
1536 free(encoded_signature);
1537 free(signature);
1538 return jws;
1539 }
1540
1541 char *jws_encode_hmac(const char *protected, const char *payload,
1542 size_t bits, const char *key)
1543 {
1544 char *jws = NULL;
1545 char *encoded_payload = encode_base64url(payload);
1546 char *encoded_protected = encode_base64url(protected);
1547 char *encoded_signature = NULL;
1548
1549 if (!encoded_payload || !encoded_protected) {
1550 warnx("jws_encode_hmac: encode_base64url failed");
1551 goto out;
1552 }
1553
1554 encoded_signature = hmac_base64url(bits, key, "%s.%s",
1555 encoded_protected, encoded_payload);
1556 if (!encoded_signature) {
1557 warnx("jws_encode_hmac: hmac_base64url failed");
1558 goto out;
1559 }
1560 if (asprintf(&jws,
1561 "{\"protected\":\"%s\","
1562 "\"payload\":\"%s\","
1563 "\"signature\":\"%s\"}",
1564 encoded_protected,
1565 encoded_payload,
1566 encoded_signature) < 0) {
1567 warnx("jws_encode_hmac: asprintf failed");
1568 jws = NULL;
1569 }
1570 out:
1571 free(encoded_payload);
1572 free(encoded_protected);
1573 free(encoded_signature);
1574 return jws;
1575 }
1576
1577 static bool key_gen(keytype_t type, int bits, const char *keyfile)
1578 {
1579 bool success = false;
1580 int r;
1581 #if !defined(USE_OPENSSL)
1582 void *pem_data = NULL;
1583 size_t pem_size = 0;
1584 #endif
1585 #if defined(USE_GNUTLS)
1586 gnutls_x509_privkey_t key = NULL;
1587 r = gnutls_x509_privkey_init(&key);
1588 if (r != GNUTLS_E_SUCCESS) {
1589 warnx("key_gen: gnutls_x509_privkey_init: %s",
1590 gnutls_strerror(r));
1591 goto out;
1592 }
1593 switch (type) {
1594 case PK_RSA:
1595 msg(1, "generating new %d-bit RSA key", bits);
1596 r = gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, bits, 0);
1597 break;
1598
1599 case PK_EC:
1600 switch (bits) {
1601 case 256:
1602 msg(1, "generating new %d-bit EC key", bits);
1603 r = gnutls_x509_privkey_generate(key, GNUTLS_PK_EC,
1604 GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_SECP256R1), 0);
1605 break;
1606
1607 case 384:
1608 msg(1, "generating new %d-bit EC key", bits);
1609 r = gnutls_x509_privkey_generate(key, GNUTLS_PK_EC,
1610 GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_SECP384R1), 0);
1611 break;
1612
1613 default:
1614 warnx("key_gen: EC key size must be either 256 or 384");
1615 goto out;
1616 }
1617 break;
1618
1619 default:
1620 warnx("key_gen: only RSA/EC keys are supported");
1621 goto out;
1622 }
1623 if (r != GNUTLS_E_SUCCESS) {
1624 warnx("key_gen: gnutls_x509_privkey_generate: %s",
1625 gnutls_strerror(r));
1626 goto out;
1627 }
1628 gnutls_datum_t data = {NULL, 0};
1629 r = gnutls_x509_privkey_export2(key, GNUTLS_X509_FMT_PEM, &data);
1630 if (r != GNUTLS_E_SUCCESS) {
1631 warnx("key_gen: gnutls_x509_privkey_export2: %s",
1632 gnutls_strerror(r));
1633 goto out;
1634 }
1635 pem_size = data.size;
1636 pem_data = gnutls_datum_data(&data, true);
1637 if (!pem_data) {
1638 warnx("key_gen: gnutls_datum_data failed");
1639 goto out;
1640 }
1641 #elif defined(USE_OPENSSL)
1642 EVP_PKEY *key = NULL;
1643 EVP_PKEY_CTX *epc = NULL;
1644 switch (type) {
1645 case PK_RSA:
1646 epc = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
1647 break;
1648
1649 case PK_EC:
1650 epc = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
1651 break;
1652
1653 default:
1654 warnx("key_gen: only RSA/EC keys are supported");
1655 goto out;
1656 }
1657 if (!epc) {
1658 openssl_error("key_gen");
1659 goto out;
1660 }
1661 if (!EVP_PKEY_keygen_init(epc)) {
1662 openssl_error("key_gen");
1663 goto out;
1664 }
1665 switch (type) {
1666 case PK_RSA:
1667 msg(1, "generating new %d-bit RSA key", bits);
1668 if (!EVP_PKEY_CTX_set_rsa_keygen_bits(epc, bits)) {
1669 openssl_error("key_gen");
1670 goto out;
1671 }
1672 break;
1673
1674 case PK_EC:
1675 switch (bits) {
1676 case 256:
1677 msg(1, "generating new %d-bit EC key", bits);
1678 if (!EVP_PKEY_CTX_set_ec_paramgen_curve_nid(epc,
1679 NID_X9_62_prime256v1)) {
1680 openssl_error("key_gen");
1681 goto out;
1682 }
1683 break;
1684
1685 case 384:
1686 msg(1, "generating new %d-bit EC key", bits);
1687 if (!EVP_PKEY_CTX_set_ec_paramgen_curve_nid(epc,
1688 NID_secp384r1)) {
1689 openssl_error("key_gen");
1690 goto out;
1691 }
1692 break;
1693
1694 default:
1695 warnx("key_gen: EC key size must be either 256 or 384");
1696 goto out;
1697 }
1698 break;
1699
1700 default:
1701 warnx("key_gen: only RSA/EC keys are supported");
1702 goto out;
1703 }
1704 if (!EVP_PKEY_keygen(epc, &key)) {
1705 openssl_error("key_gen");
1706 goto out;
1707 }
1708 #elif defined(USE_MBEDTLS)
1709 mbedtls_pk_context key;
1710 mbedtls_pk_init(&key);
1711 const mbedtls_pk_info_t *pki;
1712 switch (type) {
1713 case PK_RSA:
1714 pki = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1715 break;
1716
1717 case PK_EC:
1718 pki = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
1719 break;
1720
1721 default:
1722 warnx("key_gen: only RSA/EC keys are supported");
1723 goto out;
1724 }
1725 if (!pki) {
1726 warnx("key_gen: mbedtls_pk_info_from_type failed");
1727 goto out;
1728 }
1729 r = mbedtls_pk_setup(&key, pki);
1730 if (r) {
1731 warnx("key_gen: mbedtls_pk_setup failed: %s",
1732 _mbedtls_strerror(r));
1733 goto out;
1734 }
1735 switch (type) {
1736 case PK_RSA:
1737 msg(1, "generating new %d-bit RSA key", bits);
1738 r = mbedtls_rsa_gen_key(mbedtls_pk_rsa(key),
1739 mbedtls_ctr_drbg_random, &ctr_drbg, bits, 65537);
1740 if (r) {
1741 warnx("key_gen: mbedtls_rsa_gen_key failed: %s",
1742 _mbedtls_strerror(r));
1743 goto out;
1744 }
1745 break;
1746
1747 case PK_EC:
1748 switch (bits) {
1749 case 256:
1750 msg(1, "generating new %d-bit EC key", bits);
1751 r = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1,
1752 mbedtls_pk_ec(key), mbedtls_ctr_drbg_random,
1753 &ctr_drbg);
1754 break;
1755
1756 case 384:
1757 msg(1, "generating new %d-bit EC key", bits);
1758 r = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP384R1,
1759 mbedtls_pk_ec(key), mbedtls_ctr_drbg_random,
1760 &ctr_drbg);
1761 break;
1762
1763 default:
1764 warnx("key_gen: EC key size must be either 256 or 384");
1765 goto out;
1766 }
1767 if (r) {
1768 warnx("key_gen: mbedtls_ecp_gen_key failed: %s",
1769 _mbedtls_strerror(r));
1770 goto out;
1771 }
1772 break;
1773
1774 default:
1775 warnx("key_gen: only RSA/EC keys are supported");
1776 goto out;
1777 }
1778 pem_size = 4096;
1779 while (1) {
1780 pem_data = calloc(1, pem_size);
1781 if (!pem_data) {
1782 warn("key_gen: calloc failed");
1783 goto out;
1784 }
1785 r = mbedtls_pk_write_key_pem(&key, pem_data, pem_size);
1786 if (r == 0)
1787 break;
1788 else if (r == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
1789 free(pem_data);
1790 pem_size *= 2;
1791 } else {
1792 warnx("key_gen: mbedtls_pk_write_key_pem failed: %s",
1793 _mbedtls_strerror(r));
1794 goto out;
1795 }
1796 }
1797 pem_size = strlen(pem_data);
1798 #endif
1799 mode_t prev = umask((S_IWUSR | S_IXUSR) | S_IRWXG | S_IRWXO);
1800 FILE *f = fopen(keyfile, "w");
1801 umask(prev);
1802 if (!f) {
1803 warn("key_gen: failed to create %s", keyfile);
1804 goto out;
1805 }
1806 #if defined(USE_OPENSSL)
1807 r = PEM_write_PrivateKey(f, key, NULL, NULL, 0, NULL, NULL);
1808 fclose(f);
1809 if (!r) {
1810 openssl_error("key_gen");
1811 warnx("key_gen: failed to write %s", keyfile);
1812 unlink(keyfile);
1813 goto out;
1814 }
1815 #else
1816 r = fwrite(pem_data, 1, pem_size, f);
1817 fclose(f);
1818 if (r != (int)pem_size) {
1819 warn("key_gen: failed to write to %s", keyfile);
1820 unlink(keyfile);
1821 goto out;
1822 }
1823 #endif
1824 msg(1, "key saved to %s", keyfile);
1825 success = true;
1826 out:
1827 #if defined(USE_GNUTLS)
1828 gnutls_x509_privkey_deinit(key);
1829 free(pem_data);
1830 #elif defined(USE_OPENSSL)
1831 if (key)
1832 EVP_PKEY_free(key);
1833 if (epc)
1834 EVP_PKEY_CTX_free(epc);
1835 #elif defined(USE_MBEDTLS)
1836 mbedtls_pk_free(&key);
1837 free(pem_data);
1838 #endif
1839 return success;
1840 }
1841
1842 privkey_t key_load(keytype_t type, int bits, const char *format, ...)
1843 {
1844 privkey_t key = NULL;
1845 char *keyfile = NULL;
1846 #if !defined(USE_OPENSSL)
1847 int r;
1848 void *keydata = NULL;
1849 size_t keysize = 0;
1850 #endif
1851 va_list ap;
1852 va_start(ap, format);
1853 if (vasprintf(&keyfile, format, ap) < 0)
1854 keyfile = NULL;
1855 va_end(ap);
1856 if (!keyfile) {
1857 warnx("key_load: vasprintf failed");
1858 goto out;
1859 }
1860
1861 msg(1, "loading key from %s", keyfile);
1862 #if defined(USE_OPENSSL)
1863 while (!key) {
1864 FILE *f = fopen(keyfile, "r");
1865 if (!f) {
1866 if (errno != ENOENT) {
1867 warn("key_load: failed to open %s", keyfile);
1868 goto out;
1869 } else {
1870 msg(1, "%s not found", keyfile);
1871 if (type == PK_NONE) {
1872 warnx("key_load: %s does not exist", keyfile);
1873 goto out;
1874 }
1875 if (!key_gen(type, bits, keyfile)) {
1876 warnx("key_load: key_gen failed");
1877 goto out;
1878 }
1879 }
1880 } else {
1881 key = PEM_read_PrivateKey(f, NULL, NULL, NULL);
1882 fclose(f);
1883 if (!key) {
1884 openssl_error("key_load");
1885 warnx("key_load: failed to read %s", keyfile);
1886 goto out;
1887 }
1888 }
1889 }
1890 #else
1891 while (!(keydata = read_file(keyfile, &keysize))) {
1892 if (errno != ENOENT) {
1893 warn("key_load: failed to read %s", keyfile);
1894 goto out;
1895 } else {
1896 msg(1, "%s not found", keyfile);
1897 if (type == PK_NONE) {
1898 warnx("key_load: %s does not exist", keyfile);
1899 goto out;
1900 }
1901 if (!key_gen(type, bits, keyfile)) {
1902 warnx("key_load: key_gen failed");
1903 goto out;
1904 }
1905 }
1906 }
1907 #endif
1908
1909 #if defined(USE_GNUTLS)
1910 r = gnutls_privkey_init(&key);
1911 if (r != GNUTLS_E_SUCCESS) {
1912 warnx("key_load: gnutls_privkey_import_x509_raw: %s",
1913 gnutls_strerror(r));
1914 goto out;
1915 }
1916 gnutls_datum_t data = {keydata, keysize};
1917 r = gnutls_privkey_import_x509_raw(key, &data,
1918 GNUTLS_X509_FMT_PEM, NULL, 0);
1919 if (r != GNUTLS_E_SUCCESS) {
1920 warnx("key_load: gnutls_privkey_import_x509_raw: %s",
1921 gnutls_strerror(r));
1922 gnutls_privkey_deinit(key);
1923 key = NULL;
1924 goto out;
1925 }
1926
1927 r = gnutls_privkey_verify_params(key);
1928 if (r != GNUTLS_E_SUCCESS) {
1929 warnx("key_load: gnutls_privkey_verify_params: %s",
1930 gnutls_strerror(r));
1931 gnutls_privkey_deinit(key);
1932 key = NULL;
1933 goto out;
1934 }
1935
1936 #elif defined(USE_MBEDTLS)
1937 key = calloc(1, sizeof(*key));
1938 if (!key) {
1939 warn("key_load: calloc failed");
1940 goto out;
1941 }
1942 mbedtls_pk_init(key);
1943 r = mbedtls_pk_parse_key(key, keydata, keysize+1, NULL, 0);
1944 if (r) {
1945 warnx("key_load: mbedtls_pk_parse failed: %s",
1946 _mbedtls_strerror(r));
1947 free(key);
1948 key = NULL;
1949 goto out;
1950 }
1951 #endif
1952 switch (key_type(key)) {
1953 case PK_RSA:
1954 if (!rsa_params(key, NULL, NULL)) {
1955 warnx("key_load: invalid key");
1956 privkey_deinit(key);
1957 key = NULL;
1958 }
1959 break;
1960
1961 case PK_EC:
1962 if (!ec_params(key, NULL, NULL)) {
1963 warnx("key_load: invalid key");
1964 privkey_deinit(key);
1965 key = NULL;
1966 }
1967 break;
1968
1969 default:
1970 warnx("key_load: only RSA/EC keys are supported");
1971 privkey_deinit(key);
1972 key = NULL;
1973 }
1974 out:
1975 free(keyfile);
1976 #if !defined(USE_OPENSSL)
1977 free(keydata);
1978 #endif
1979 return key;
1980 }
1981
1982 bool is_ip(const char *s, unsigned char *ip, size_t *ip_len)
1983 {
1984 bool ret = false;
1985 struct addrinfo hints, *ai;
1986 memset(&hints, 0, sizeof(hints));
1987 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
1988 hints.ai_family = AF_UNSPEC;
1989
1990 if (getaddrinfo(s, NULL, &hints, &ai) == 0) {
1991 if (ai->ai_family == AF_INET) {
1992 if (ip_len && *ip_len >= sizeof(struct in_addr)) {
1993 struct sockaddr_in *s = (struct sockaddr_in *)ai->ai_addr;
1994 *ip_len = sizeof(struct in_addr);
1995 if (ip)
1996 memcpy(ip, &s->sin_addr, sizeof(struct in_addr));
1997 }
1998 ret = true;
1999 } else if (ai->ai_family == AF_INET6) {
2000 if (ip_len && *ip_len >= sizeof(struct in6_addr)) {
2001 struct sockaddr_in6 *s = (struct sockaddr_in6 *)ai->ai_addr;
2002 *ip_len = sizeof(struct in6_addr);
2003 if (ip)
2004 memcpy(ip, &s->sin6_addr, sizeof(struct in6_addr));
2005 }
2006 ret = true;
2007 } else if (ip_len)
2008 *ip_len = 0;
2009 freeaddrinfo(ai);
2010 } else if (ip_len)
2011 *ip_len = 0;
2012
2013 return ret;
2014 }
2015
2016 char *csr_gen(char * const *names, bool status_req, privkey_t key)
2017 {
2018 char *req = NULL;
2019 unsigned char *csrdata = NULL;
2020 size_t csrsize = 0;
2021 int r;
2022 #if !defined(USE_OPENSSL)
2023 unsigned char ip[16];
2024 size_t ip_len;
2025 #endif
2026 #if defined(USE_GNUTLS)
2027 unsigned int key_usage = 0;
2028 gnutls_digest_algorithm_t hash_type;
2029 gnutls_pubkey_t pubkey = NULL;
2030 gnutls_x509_crq_t crq = NULL;
2031 #if HAVE_GNUTLS_X509_CRQ_SET_TLSFEATURES
2032 gnutls_x509_tlsfeatures_t tls_features = NULL;
2033 #endif
2034 #elif defined(USE_OPENSSL)
2035 const char *key_usage = NULL;
2036 const EVP_MD *hash_type;
2037 X509_REQ *crq = NULL;
2038 X509_NAME *name = NULL;
2039 STACK_OF(X509_EXTENSION) *exts = NULL;
2040 char *san = NULL;
2041 #elif defined(USE_MBEDTLS)
2042 unsigned int key_usage = 0;
2043 mbedtls_md_type_t hash_type;
2044 size_t buflen = 1024;
2045 unsigned char *buf = NULL;
2046 char *cn = NULL;
2047 mbedtls_x509write_csr csr;
2048 mbedtls_x509write_csr_init(&csr);
2049 #endif
2050
2051 switch (key_type(key)) {
2052 case PK_RSA:
2053 #if defined(USE_GNUTLS)
2054 key_usage = GNUTLS_KEY_DIGITAL_SIGNATURE |
2055 GNUTLS_KEY_KEY_ENCIPHERMENT;
2056 hash_type = GNUTLS_DIG_SHA256;
2057 #elif defined(USE_OPENSSL)
2058 key_usage = "critical, digitalSignature, keyEncipherment";
2059 hash_type = EVP_sha256();
2060 #elif defined(USE_MBEDTLS)
2061 key_usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
2062 MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
2063 hash_type = MBEDTLS_MD_SHA256;
2064 #endif
2065 break;
2066
2067 case PK_EC:
2068 #if defined(USE_GNUTLS)
2069 key_usage = GNUTLS_KEY_DIGITAL_SIGNATURE;
2070 #elif defined(USE_OPENSSL)
2071 key_usage = "critical, digitalSignature";
2072 #elif defined(USE_MBEDTLS)
2073 key_usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
2074 #endif
2075 switch (ec_params(key, NULL, NULL)) {
2076 case 0:
2077 warnx("csr_gen: ec_params failed");
2078 goto out;
2079
2080 case 256:
2081 #if defined(USE_GNUTLS)
2082 hash_type = GNUTLS_DIG_SHA256;
2083 #elif defined(USE_OPENSSL)
2084 hash_type = EVP_sha256();
2085 #elif defined(USE_MBEDTLS)
2086 hash_type = MBEDTLS_MD_SHA256;
2087 #endif
2088 break;
2089
2090 case 384:
2091 #if defined(USE_GNUTLS)
2092 hash_type = GNUTLS_DIG_SHA384;
2093 #elif defined(USE_OPENSSL)
2094 hash_type = EVP_sha384();
2095 #elif defined(USE_MBEDTLS)
2096 hash_type = MBEDTLS_MD_SHA384;
2097 #endif
2098 break;
2099
2100 default:
2101 warnx("csr_gen: unsupported EC curve");
2102 goto out;
2103 }
2104 break;
2105
2106 default:
2107 warnx("csr_gen: only RSA/EC keys are supported");
2108 goto out;
2109 }
2110
2111 #if defined(USE_GNUTLS)
2112 r = gnutls_x509_crq_init(&crq);
2113 if (r != GNUTLS_E_SUCCESS) {
2114 warnx("csr_gen: gnutls_x509_crq_init: %s", gnutls_strerror(r));
2115 goto out;
2116 }
2117
2118 r = gnutls_x509_crq_set_dn_by_oid(crq, GNUTLS_OID_X520_COMMON_NAME, 0,
2119 *names, strlen(*names));
2120 if (r != GNUTLS_E_SUCCESS) {
2121 warnx("csr_gen: gnutls_x509_crq_set_dn_by_oid: %s", gnutls_strerror(r));
2122 goto out;
2123 }
2124
2125 while (*names) {
2126 ip_len = sizeof(ip);
2127 if (is_ip(*names, ip, &ip_len))
2128 r = gnutls_x509_crq_set_subject_alt_name(crq, GNUTLS_SAN_IPADDRESS,
2129 ip, ip_len, GNUTLS_FSAN_APPEND);
2130 else
2131 r = gnutls_x509_crq_set_subject_alt_name(crq, GNUTLS_SAN_DNSNAME,
2132 *names, strlen(*names), GNUTLS_FSAN_APPEND);
2133 if (r != GNUTLS_E_SUCCESS) {
2134 warnx("csr_gen: gnutls_x509_set_subject_alt_name: %s",
2135 gnutls_strerror(r));
2136 goto out;
2137 }
2138 names++;
2139 }
2140
2141 r = gnutls_x509_crq_set_key_usage(crq, key_usage);
2142 if (r != GNUTLS_E_SUCCESS) {
2143 warnx("csr_gen: gnutls_x509_crq_set_key_usage: %s",
2144 gnutls_strerror(r));
2145 goto out;
2146 }
2147
2148 if (status_req) {
2149 #if HAVE_GNUTLS_X509_CRQ_SET_TLSFEATURES
2150 r = gnutls_x509_tlsfeatures_init(&tls_features);
2151 if (r != GNUTLS_E_SUCCESS) {
2152 warnx("csr_gen: gnutls_x509_tlsfeatures_init: %s",
2153 gnutls_strerror(r));
2154 goto out;
2155 }
2156
2157 // status_request TLS feature (OCSP Must-Staple)
2158 r = gnutls_x509_tlsfeatures_add(tls_features, 5);
2159 if (r != GNUTLS_E_SUCCESS) {
2160 warnx("csr_gen: gnutls_x509_tlsfeatures_add: %s",
2161 gnutls_strerror(r));
2162 goto out;
2163 }
2164
2165 r = gnutls_x509_crq_set_tlsfeatures(crq, tls_features);
2166 if (r != GNUTLS_E_SUCCESS) {
2167 warnx("csr_gen: gnutls_x509_set_tlsfeatures: %s",
2168 gnutls_strerror(r));
2169 goto out;
2170 }
2171 #else
2172 warnx("csr_gen: -m, --must-staple disabled at compile time "
2173 "- consider recompiling with GnuTLS 3.5.1 or later");
2174 goto out;
2175 #endif
2176 }
2177
2178 r = gnutls_pubkey_init(&pubkey);
2179 if (r != GNUTLS_E_SUCCESS) {
2180 warnx("csr_gen: gnutls_pubkey_init: %s", gnutls_strerror(r));
2181 goto out;
2182 }
2183
2184 r = gnutls_pubkey_import_privkey(pubkey, key, 0, 0);
2185 if (r != GNUTLS_E_SUCCESS) {
2186 warnx("csr_gen: gnutls_pubkey_import_privkey: %s", gnutls_strerror(r));
2187 goto out;
2188 }
2189
2190 r = gnutls_x509_crq_set_pubkey(crq, pubkey);
2191 if (r != GNUTLS_E_SUCCESS) {
2192 warnx("csr_gen: gnutls_x509_crq_set_pubkey: %s", gnutls_strerror(r));
2193 goto out;
2194 }
2195
2196 gnutls_digest_algorithm_t dig;
2197 unsigned int mand;
2198 r = gnutls_pubkey_get_preferred_hash_algorithm(pubkey, &dig, &mand);
2199 if (r != GNUTLS_E_SUCCESS) {
2200 warnx("csr_gen: gnutls_pubkey_get_preferred_hash_algorithm: %s",
2201 gnutls_strerror(r));
2202 goto out;
2203 }
2204 if (mand == 0)
2205 dig = hash_type;
2206 else if (dig != hash_type) {
2207 warnx("csr_gen: unsupported message digest");
2208 goto out;
2209 }
2210
2211 r = gnutls_x509_crq_privkey_sign(crq, key, dig, 0);
2212 if (r != GNUTLS_E_SUCCESS) {
2213 warnx("csr_gen: gnutls_crq_privkey_sign: %s", gnutls_strerror(r));
2214 goto out;
2215 }
2216
2217 gnutls_datum_t data = {NULL, 0};
2218 r = gnutls_x509_crq_export2(crq, GNUTLS_X509_FMT_DER, &data);
2219 if (r != GNUTLS_E_SUCCESS) {
2220 warnx("csr_gen: gnutls_x509_crq_export2: %s", gnutls_strerror(r));
2221 goto out;
2222 }
2223 csrsize = data.size;
2224 csrdata = gnutls_datum_data(&data, true);
2225 if (!csrdata) {
2226 warnx("csr_gen: gnutls_datum_data failed");
2227 goto out;
2228 }
2229 #elif defined(USE_OPENSSL)
2230 if (!(crq = X509_REQ_new())) {
2231 openssl_error("csr_gen");
2232 goto out;
2233 }
2234 if (!(name = X509_NAME_new())) {
2235 openssl_error("csr_gen");
2236 goto out;
2237 }
2238 if (!X509_REQ_set_pubkey(crq, key)) {
2239 openssl_error("csr_gen");
2240 goto out;
2241 }
2242 if (!X509_NAME_add_entry_by_txt(name, "CN",
2243 MBSTRING_ASC, (unsigned char *)*names, -1, -1, 0)) {
2244 openssl_error("csr_gen");
2245 goto out;
2246 }
2247 if (!X509_REQ_set_subject_name(crq, name)) {
2248 openssl_error("csr_gen");
2249 goto out;
2250 }
2251 if (asprintf(&san, "%s:%s", is_ip(*names, NULL, NULL) ? "IP" : "DNS",
2252 *names) < 0) {
2253 warnx("csr_gen: asprintf failed");
2254 san = NULL;
2255 goto out;
2256 }
2257 while (*++names) {
2258 char *tmp = NULL;
2259 if (asprintf(&tmp, "%s,%s:%s", san,
2260 is_ip(*names, NULL, NULL) ? "IP" : "DNS", *names) < 0) {
2261 warnx("csr_gen: asprintf failed");
2262 goto out;
2263 }
2264 free(san);
2265 san = tmp;
2266 }
2267 exts = sk_X509_EXTENSION_new_null();
2268 if (!exts) {
2269 openssl_error("csr_gen");
2270 goto out;
2271 }
2272 X509_EXTENSION *ext = X509V3_EXT_conf_nid(NULL, NULL,
2273 NID_subject_alt_name, san);
2274 if (!ext) {
2275 openssl_error("csr_gen");
2276 goto out;
2277 }
2278 sk_X509_EXTENSION_push(exts, ext);
2279 ext = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, key_usage);
2280 if (!ext) {
2281 openssl_error("csr_gen");
2282 goto out;
2283 }
2284 sk_X509_EXTENSION_push(exts, ext);
2285 if (status_req) {
2286 ext = X509V3_EXT_conf_nid(NULL, NULL, NID_tlsfeature,
2287 "status_request");
2288 if (!ext) {
2289 openssl_error("csr_gen");
2290 goto out;
2291 }
2292 sk_X509_EXTENSION_push(exts, ext);
2293 }
2294 if (!X509_REQ_add_extensions(crq, exts)) {
2295 openssl_error("csr_gen");
2296 goto out;
2297 }
2298 if (!X509_REQ_sign(crq, key, hash_type)) {
2299 openssl_error("csr_gen");
2300 goto out;
2301 }
2302 r = i2d_X509_REQ(crq, NULL);
2303 if (r < 0) {
2304 openssl_error("csr_gen");
2305 goto out;
2306 }
2307 csrsize = r;
2308 csrdata = calloc(1, csrsize);
2309 if (!csrdata) {
2310 warn("csr_gen: calloc failed");
2311 goto out;
2312 }
2313 unsigned char *tmp = csrdata;
2314 if (i2d_X509_REQ(crq, &tmp) != (int)csrsize) {
2315 openssl_error("csr_gen");
2316 goto out;
2317 }
2318 #elif defined(USE_MBEDTLS)
2319 mbedtls_x509write_csr_set_key(&csr, key);
2320 mbedtls_x509write_csr_set_md_alg(&csr, hash_type);
2321
2322 if (asprintf(&cn, "CN=%s", *names) < 0) {
2323 warnx("csr_gen: asprintf failed");
2324 cn = NULL;
2325 goto out;
2326 }
2327
2328 r = mbedtls_x509write_csr_set_key_usage(&csr, key_usage);
2329 if (r) {
2330 warnx("csr_gen: mbedtls_x509write_csr_set_key_usage failed: %s",
2331 _mbedtls_strerror(r));
2332 goto out;
2333 }
2334
2335 r = mbedtls_x509write_csr_set_subject_name(&csr, cn);
2336 if (r) {
2337 warnx("csr_gen: mbedtls_x509write_csr_set_subject_name failed: %s",
2338 _mbedtls_strerror(r));
2339 goto out;
2340 }
2341
2342 while (1) {
2343 buflen *= 2;
2344 free(buf);
2345 buf = calloc(1, buflen);
2346 if (!buf) {
2347 warn("csr_gen: calloc failed");
2348 goto out;
2349 }
2350 unsigned char *p = buf + buflen;
2351 size_t len = 0;
2352 size_t count = 0;
2353 while (names[count]) count++;
2354 while (count--) {
2355 const unsigned char *data;
2356 size_t data_len;
2357 unsigned char tag;
2358
2359 ip_len = sizeof(ip);
2360 if (is_ip(names[count], ip, &ip_len)) {
2361 tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | 7;
2362 data = ip;
2363 data_len = ip_len;
2364 } else {
2365 tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2;
2366 data = (const unsigned char *)names[count];
2367 data_len = strlen(names[count]);
2368 }
2369
2370 r = mbedtls_asn1_write_raw_buffer(&p, buf, data, data_len);
2371 if (r >= 0)
2372 len += r;
2373 else if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)
2374 break;
2375 else {
2376 warnx("csr_gen: mbedtls_asn1_write_raw_buffer failed: %s",
2377 _mbedtls_strerror(r));
2378 goto out;
2379 }
2380 r = mbedtls_asn1_write_len(&p, buf, data_len);
2381 if (r >= 0)
2382 len += r;
2383 else if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)
2384 break;
2385 else {
2386 warnx("csr_gen: mbedtls_asn1_write_len failed: %s",
2387 _mbedtls_strerror(r));
2388 goto out;
2389 }
2390 r = mbedtls_asn1_write_tag(&p, buf, tag);
2391 if (r >= 0)
2392 len += r;
2393 else if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)
2394 break;
2395 else {
2396 warnx("csr_gen: mbedtls_asn1_write_tag failed: %s",
2397 _mbedtls_strerror(r));
2398 goto out;
2399 }
2400 }
2401 if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)
2402 continue;
2403 r = mbedtls_asn1_write_len(&p, buf, len);
2404 if (r >= 0)
2405 len += r;
2406 else if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)
2407 continue;
2408 else {
2409 warnx("csr_gen: mbedtls_asn1_write_len failed: %s",
2410 _mbedtls_strerror(r));
2411 goto out;
2412 }
2413 r = mbedtls_asn1_write_tag(&p, buf,
2414 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
2415 if (r >= 0)
2416 len += r;
2417 else if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)
2418 continue;
2419 else {
2420 warnx("csr_gen: mbedtls_asn1_write_tag failed: %s",
2421 _mbedtls_strerror(r));
2422 goto out;
2423 }
2424 r = mbedtls_x509write_csr_set_extension(&csr,
2425 MBEDTLS_OID_SUBJECT_ALT_NAME,
2426 MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME),
2427 buf + buflen - len, len);
2428 if (r) {
2429 warnx("csr_gen: mbedtls_x509write_csr_set_extension failed: %s",
2430 _mbedtls_strerror(r));
2431 goto out;
2432 }
2433 if (!status_req)
2434 break;
2435 p = buf + buflen;
2436 len = 0;
2437 // status_request TLS feature (OCSP Must-Staple)
2438 r = mbedtls_asn1_write_int(&p, buf, 5);
2439 if (r >= 0)
2440 len += r;
2441 else if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)
2442 continue;
2443 else {
2444 warnx("csr_gen: mbedtls_asn1_write_int failed: %s",
2445 _mbedtls_strerror(r));
2446 goto out;
2447 }
2448 r = mbedtls_asn1_write_len(&p, buf, len);
2449 if (r >= 0)
2450 len += r;
2451 else if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)
2452 continue;
2453 else {
2454 warnx("csr_gen: mbedtls_asn1_write_len failed: %s",
2455 _mbedtls_strerror(r));
2456 goto out;
2457 }
2458 r = mbedtls_asn1_write_tag(&p, buf,
2459 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
2460 if (r >= 0)
2461 len += r;
2462 else if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)
2463 continue;
2464 else {
2465 warnx("csr_gen: mbedtls_asn1_write_tag failed: %s",
2466 _mbedtls_strerror(r));
2467 goto out;
2468 }
2469 r = mbedtls_x509write_csr_set_extension(&csr,
2470 // http://oid-info.com/get/1.3.6.1.5.5.7.1.24
2471 // pe(1) id-pe-tlsfeature(24)
2472 MBEDTLS_OID_PKIX "\x01\x18",
2473 MBEDTLS_OID_SIZE(MBEDTLS_OID_PKIX "\x01\x18"),
2474 buf + buflen - len, len);
2475 if (r) {
2476 warnx("csr_gen: mbedtls_x509write_csr_set_extension failed: %s",
2477 _mbedtls_strerror(r));
2478 goto out;
2479 }
2480 break;
2481 }
2482
2483 while (1) {
2484 r = mbedtls_x509write_csr_der(&csr, buf, buflen,
2485 mbedtls_ctr_drbg_random, &ctr_drbg);
2486 if (r > 0)
2487 break;
2488 else if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {
2489 free(buf);
2490 buflen *= 2;
2491 buf = calloc(1, buflen);
2492 if (!buf) {
2493 warn("csr_gen: calloc failed");
2494 goto out;
2495 }
2496 } else {
2497 warnx("csr_gen: mbedtls_x509write_csr_der failed: %s",
2498 _mbedtls_strerror(r));
2499 goto out;
2500 }
2501 }
2502 csrsize = r;
2503 csrdata = calloc(1, csrsize);
2504 if (!csrdata) {
2505 warn("csr_gen: calloc failed");
2506 goto out;
2507 }
2508 memcpy(csrdata, buf + buflen - csrsize, csrsize);
2509 #endif
2510 r = base64_ENCODED_LEN(csrsize, base64_VARIANT_URLSAFE_NO_PADDING);
2511 req = calloc(1, r);
2512 if (!req) {
2513 warn("csr_gen: calloc failed");
2514 goto out;
2515 }
2516 if (!bin2base64(req, r, csrdata, csrsize,
2517 base64_VARIANT_URLSAFE_NO_PADDING)) {
2518 warnx("csr_gen: bin2base64 failed");
2519 free(req);
2520 req = NULL;
2521 goto out;
2522 }
2523 out:
2524 #if defined(USE_GNUTLS)
2525 gnutls_pubkey_deinit(pubkey);
2526 #if HAVE_GNUTLS_X509_CRQ_SET_TLSFEATURES
2527 if (tls_features)
2528 gnutls_x509_tlsfeatures_deinit(tls_features);
2529 #endif
2530 gnutls_x509_crq_deinit(crq);
2531 #elif defined(USE_OPENSSL)
2532 if (name)
2533 X509_NAME_free(name);
2534 if (crq)
2535 X509_REQ_free(crq);
2536 if (exts)
2537 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
2538 free(san);
2539 #elif defined(USE_MBEDTLS)
2540 mbedtls_x509write_csr_free(&csr);
2541 free(buf);
2542 free(cn);
2543 #endif
2544 free(csrdata);
2545 return req;
2546 }
2547
2548 #if defined(USE_GNUTLS)
2549 static char **csr_names(gnutls_x509_crq_t crq)
2550 {
2551 int i, r = 0, n = 0, ncn = 0, nsan = 0;
2552 char **ret = NULL;
2553 char **names = NULL;
2554 char *buf = NULL;
2555 char *ip = NULL;
2556 size_t size = 0;
2557 bool cn = true;
2558
2559 do {
2560 r = cn ?
2561 gnutls_x509_crq_get_dn_by_oid(crq, GNUTLS_OID_X520_COMMON_NAME,
2562 ncn, 0, buf, &size) :
2563 gnutls_x509_crq_get_subject_alt_name(crq, nsan, buf, &size,
2564 NULL, NULL);
2565
2566 switch (r) {
2567 case GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE:
2568 if (cn) {
2569 cn = false;
2570 r = GNUTLS_E_SUCCESS;
2571 }
2572 break;
2573
2574 case GNUTLS_E_SHORT_MEMORY_BUFFER:
2575 buf = calloc(1, size);
2576 if (!buf) {
2577 warn("csr_names: calloc failed");
2578 goto out;
2579 }
2580 break;
2581
2582 case GNUTLS_SAN_IPADDRESS:
2583 ip = calloc(1, INET6_ADDRSTRLEN);
2584 if (!ip) {
2585 warnx("csr_names: calloc failed");
2586 goto out;
2587 }
2588 if (!inet_ntop(size == 4 ? AF_INET : AF_INET6, buf, ip,
2589 INET6_ADDRSTRLEN)) {
2590 warnx("csr_names: invalid IP address in Subj Alt Name");
2591 free(ip);
2592 ip = NULL;
2593 continue;
2594 }
2595 free(buf);
2596 buf = ip;
2597 ip = NULL;
2598 // intentional fallthrough
2599 case GNUTLS_E_SUCCESS:
2600 case GNUTLS_SAN_DNSNAME:
2601 for (i = 0; i < n; i++) {
2602 if (strcasecmp(buf, names[i]) == 0)
2603 break;
2604 }
2605 if (i < n)
2606 free(buf);
2607 else {
2608 names = realloc(names, (n + 2) * sizeof(buf));
2609 if (!names) {
2610 warn("csr_names: realloc failed");
2611 goto out;
2612 }
2613 names[n++] = buf;
2614 names[n] = NULL;
2615 }
2616 buf = NULL;
2617 size = 0;
2618 if (cn)
2619 ncn++;
2620 else
2621 nsan++;
2622 break;
2623
2624 default:
2625 if (r < 0) {
2626 warnx("csr_names: %s: %s",
2627 cn ? "gnutls_x509_crq_get_dn_by_oid" :
2628 "gnutls_x509_crq_get_subject_alt_name",
2629 gnutls_strerror(r));
2630 goto out;
2631 }
2632 }
2633 } while (r != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
2634
2635 if (n > 0) {
2636 ret = names;
2637 names = NULL;
2638 }
2639
2640 out:
2641 for (i = 0; names && names[i]; i++)
2642 free(names[i]);
2643 free(names);
2644 return ret;
2645 }
2646 #elif defined(USE_OPENSSL)
2647 static char **csr_names(X509_REQ *crq)
2648 {
2649 int i, n = 0, ncn = -1, nsan = 0;
2650 char **ret = NULL;
2651 char **names = NULL;
2652 bool cn = true;
2653 X509_NAME *name = NULL;
2654 STACK_OF(X509_EXTENSION) *exts = NULL;
2655 GENERAL_NAMES* alts = NULL;
2656
2657 name = X509_REQ_get_subject_name(crq);
2658 if (!name)
2659 cn = false;
2660
2661 exts = X509_REQ_get_extensions(crq);
2662 if (exts)
2663 alts = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
2664
2665 while (1) {
2666 char *nm = NULL;
2667 if (cn) {
2668 ncn = X509_NAME_get_index_by_NID(name, NID_commonName, ncn);
2669 if (ncn < 0) {
2670 cn = false;
2671 continue;
2672 }
2673 X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, ncn);
2674 if (!entry)
2675 continue;
2676 ASN1_STRING *str = X509_NAME_ENTRY_get_data(entry);
2677 if (!str)
2678 continue;
2679 unsigned char *buf = NULL;
2680 int size = ASN1_STRING_to_UTF8(&buf, str);
2681 if (size < 0) {
2682 openssl_error("csr_names");
2683 continue;
2684 }
2685 nm = strndup((const char *)buf, size);
2686 if (!nm) {
2687 warn("csr_names: strndup failed");
2688 OPENSSL_free(buf);
2689 goto out;
2690 }
2691 OPENSSL_free(buf);
2692 } else if (alts && nsan < sk_GENERAL_NAME_num(alts)) {
2693 int type;
2694 GENERAL_NAME *gn = sk_GENERAL_NAME_value(alts, nsan++);
2695 if (!gn)
2696 continue;
2697 ASN1_STRING *value = GENERAL_NAME_get0_value(gn, &type);
2698 if (!value)
2699 continue;
2700 if (type == GEN_DNS) {
2701 unsigned char *buf = NULL;
2702 int size = ASN1_STRING_to_UTF8(&buf, value);
2703 if (size < 0) {
2704 openssl_error("csr_names");
2705 continue;
2706 }
2707 nm = strndup((const char *)buf, size);
2708 if (!nm) {
2709 warn("csr_names: strndup failed");
2710 OPENSSL_free(buf);
2711 goto out;
2712 }
2713 OPENSSL_free(buf);
2714 } else if (type == GEN_IPADD) {
2715 int af;
2716 int len;
2717 switch (ASN1_STRING_length(value)) {
2718 case 4:
2719 af = AF_INET;
2720 len = INET_ADDRSTRLEN;
2721 break;
2722 case 16:
2723 af = AF_INET6;
2724 len = INET6_ADDRSTRLEN;
2725 break;
2726 default:
2727 warnx("csr_names: invalid IP address in Subj Alt Name");
2728 continue;
2729 }
2730 nm = calloc(1, len);
2731 if (!nm) {
2732 warnx("csr_names: calloc failed");
2733 goto out;
2734 }
2735 if (!inet_ntop(af, ASN1_STRING_get0_data(value), nm, len)) {
2736 warnx("csr_names: invalid IP address in Subj Alt Name");
2737 free(nm);
2738 continue;
2739 }
2740 }
2741 } else
2742 break;
2743
2744 if (nm) {
2745 for (i = 0; i < n; i++) {
2746 if (strcasecmp(nm, names[i]) == 0)
2747 break;
2748 }
2749 if (i < n)
2750 free(nm);
2751 else {
2752 char **tmp = realloc(names, (n + 2) * sizeof(nm));
2753 if (!tmp) {
2754 warn("csr_names: realloc failed");
2755 free(nm);
2756 goto out;
2757 }
2758 names = tmp;
2759 names[n++] = nm;
2760 names[n] = NULL;
2761 }
2762 }
2763 }
2764
2765 if (n > 0) {
2766 ret = names;
2767 names = NULL;
2768 }
2769
2770 out:
2771 if (names) {
2772 for (i = 0; names[i]; i++)
2773 free(names[i]);
2774 free(names);
2775 }
2776 if (exts)
2777 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
2778 if (alts)
2779 sk_GENERAL_NAME_pop_free(alts, GENERAL_NAME_free);
2780 return ret;
2781 }
2782 #elif defined(USE_MBEDTLS)
2783 // Unlike the built-in mbedTLS parser this function supports IP identifiers
2784 static int ext_san(unsigned char *p, size_t len, mbedtls_x509_sequence *san)
2785 {
2786 unsigned char *end = p + len;
2787 unsigned char *end_ext;
2788 int r;
2789
2790 r = mbedtls_asn1_get_tag(&p, end, &len,
2791 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
2792 if (r)
2793 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
2794
2795 if (end != p + len)
2796 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
2797 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
2798
2799 while (p < end) {
2800 r = mbedtls_asn1_get_tag(&p, end, &len,
2801 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
2802 if (r)
2803 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
2804
2805 end_ext = p + len;
2806
2807 r = mbedtls_asn1_get_tag(&p, end_ext, &len, MBEDTLS_ASN1_OID);
2808 if (r)
2809 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
2810
2811 if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME) ||
2812 memcmp(MBEDTLS_OID_SUBJECT_ALT_NAME, p, len) != 0) {
2813 p = end_ext;
2814 continue;
2815 }
2816
2817 p += len;
2818
2819 int crit;
2820 r = mbedtls_asn1_get_bool(&p, end_ext, &crit);
2821 if (r && r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
2822 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
2823
2824 r = mbedtls_asn1_get_tag(&p, end_ext, &len, MBEDTLS_ASN1_OCTET_STRING);
2825 if (r)
2826 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
2827
2828 if (p + len != end_ext)
2829 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
2830 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
2831
2832 r = mbedtls_asn1_get_tag(&p, end_ext, &len,
2833 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
2834 if (r)
2835 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
2836
2837 if (p + len != end_ext)
2838 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
2839 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
2840
2841 while (p < end_ext) {
2842 unsigned char tag = *p++;
2843 r = mbedtls_asn1_get_len(&p, end_ext, &len);
2844 if (r)
2845 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
2846
2847 if ((tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
2848 MBEDTLS_ASN1_CONTEXT_SPECIFIC)
2849 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
2850 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
2851
2852 if (san->buf.p) {
2853 if (san->next)
2854 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
2855
2856 san->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
2857 if (!san->next)
2858 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
2859 MBEDTLS_ERR_ASN1_ALLOC_FAILED;
2860
2861 san = san->next;
2862 }
2863
2864 san->buf.tag = tag;
2865 san->buf.len = len;
2866 san->buf.p = p;
2867 p += len;
2868 }
2869
2870 san->next = NULL;
2871 if (p != end_ext)
2872 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
2873 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
2874 }
2875
2876 return 0;
2877 }
2878
2879 static int csr_san(const mbedtls_x509_csr *crq, mbedtls_x509_sequence *san)
2880 {
2881 unsigned char *p = crq->cri.p;
2882 size_t len = crq->cri.len;
2883 unsigned char *end = p + len;
2884 unsigned char *end_attr;
2885 int i = 0, r;
2886
2887 r = mbedtls_asn1_get_tag(&p, end, &len,
2888 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
2889 if (r)
2890 return MBEDTLS_ERR_X509_INVALID_FORMAT + r;
2891
2892 r = mbedtls_asn1_get_int(&p, end, &i);
2893 if (r && r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
2894 return MBEDTLS_ERR_X509_INVALID_VERSION + r;
2895
2896 if (i != 0)
2897 return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
2898
2899 for (i = 0; i < 2; i++) {
2900 r = mbedtls_asn1_get_tag(&p, end, &len,
2901 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
2902 if (r)
2903 return MBEDTLS_ERR_X509_INVALID_FORMAT + r;
2904 p += len;
2905 }
2906
2907 r = mbedtls_asn1_get_tag(&p, end, &len,
2908 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
2909 if (r)
2910 return MBEDTLS_ERR_X509_INVALID_FORMAT + r;
2911
2912 while (p < end) {
2913 r = mbedtls_asn1_get_tag(&p, end, &len,
2914 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
2915 if (r)
2916 return MBEDTLS_ERR_X509_INVALID_FORMAT + r;
2917
2918 end_attr = p + len;
2919
2920 r = mbedtls_asn1_get_tag(&p, end_attr, &len, MBEDTLS_ASN1_OID);
2921 if (r)
2922 return MBEDTLS_ERR_X509_INVALID_FORMAT + r;
2923
2924 if (len == MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ) &&
2925 memcmp(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, p, len) == 0) {
2926 p += len;
2927
2928 r = mbedtls_asn1_get_tag(&p, end_attr, &len,
2929 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET);
2930 if (r)
2931 return MBEDTLS_ERR_X509_INVALID_FORMAT + r;
2932 else
2933 return ext_san(p, len, san);
2934 }
2935
2936 p = end_attr;
2937 }
2938
2939 return 0;
2940 }
2941
2942 static char **csr_names(mbedtls_x509_csr *crq)
2943 {
2944 int i, n = 0;
2945 char **ret = NULL;
2946 char **names = NULL;
2947
2948 mbedtls_x509_name *name = &crq->subject;
2949 mbedtls_x509_sequence sans, *san = &sans;
2950 memset(&sans, 0, sizeof(sans));
2951
2952 i = csr_san(crq, san);
2953 if (i) {
2954 warnx("csr_names: csr_san failed: %s", _mbedtls_strerror(i));
2955 goto out;
2956 }
2957
2958 while (1) {
2959 char *nm = NULL;
2960 if (name) {
2961 if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0) {
2962 nm = strndup((const char *)name->val.p, name->val.len);
2963 if (!nm) {
2964 warn("csr_names: strndup failed");
2965 goto out;
2966 }
2967 }
2968 name = name->next;
2969 } else if (san) {
2970 if (san->buf.tag == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) {
2971 nm = strndup((const char *)san->buf.p, san->buf.len);
2972 if (!nm) {
2973 warn("csr_names: strndup failed");
2974 goto out;
2975 }
2976 } else if (san->buf.tag == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 7)) {
2977 int af;
2978 int len = 0;
2979 switch (san->buf.len) {
2980 case 4:
2981 af = AF_INET;
2982 len = INET_ADDRSTRLEN;
2983 break;
2984 case 16:
2985 af = AF_INET6;
2986 len = INET6_ADDRSTRLEN;
2987 break;
2988 default:
2989 warnx("csr_names: invalid IP address in Subj Alt Name");
2990 }
2991 if (len) {
2992 nm = calloc(1, len);
2993 if (!nm) {
2994 warnx("csr_names: calloc failed");
2995 goto out;
2996 }
2997 if (!inet_ntop(af, san->buf.p, nm, len)) {
2998 warnx("csr_names: invalid IP address in Subj Alt Name");
2999 free(nm);
3000 nm = NULL;
3001 }
3002 }
3003 }
3004 san = san->next;
3005 } else
3006 break;
3007
3008 if (nm) {
3009 for (i = 0; i < n; i++) {
3010 if (strcasecmp(nm, names[i]) == 0)
3011 break;
3012 }
3013 if (i < n)
3014 free(nm);
3015 else {
3016 char **tmp = realloc(names, (n + 2) * sizeof(nm));
3017 if (!tmp) {
3018 warn("csr_names: realloc failed");
3019 free(nm);
3020 goto out;
3021 }
3022 names = tmp;
3023 names[n++] = nm;
3024 names[n] = NULL;
3025 }
3026 }
3027 }
3028
3029 if (n > 0) {
3030 ret = names;
3031 names = NULL;
3032 }
3033
3034 out:
3035 if (names) {
3036 for (i = 0; names[i]; i++)
3037 free(names[i]);
3038 free(names);
3039 }
3040 while (sans.next) {
3041 san = sans.next;
3042 sans.next = san->next;
3043 mbedtls_free(san);
3044 }
3045 return ret;
3046 }
3047 #endif
3048
3049 char *csr_load(const char *file, char ***names)
3050 {
3051 int r;
3052 char *ret = NULL;
3053 void *csrdata = NULL;
3054 size_t csrsize = 0;
3055 #if defined(USE_GNUTLS)
3056 gnutls_x509_crq_t crq = NULL;
3057 #elif defined(USE_MBEDTLS)
3058 mbedtls_x509_csr _crq, *crq = &_crq;
3059 mbedtls_x509_csr_init(crq);
3060 #elif defined(USE_OPENSSL)
3061 X509_REQ *crq = NULL;
3062 #endif
3063
3064 msg(1, "loading certificate request from %s", file);
3065
3066 #if defined(USE_OPENSSL)
3067 FILE *f = NULL;
3068 if (!(f = fopen(file, "r"))) {
3069 warn("csr_load: failed to open %s", file);
3070 goto out;
3071 }
3072 crq = PEM_read_X509_REQ(f, NULL, NULL, NULL);
3073 fclose(f);
3074 if (!crq) {
3075 openssl_error("csr_load");
3076 warnx("csr_load: failed to load %s", file);
3077 goto out;
3078 }
3079 r = i2d_X509_REQ(crq, NULL);
3080 if (r < 0) {
3081 openssl_error("csr_load");
3082 goto out;
3083 }
3084 csrsize = r;
3085 csrdata = calloc(1, csrsize);
3086 if (!csrdata) {
3087 warn("csr_load: calloc failed");
3088 goto out;
3089 }
3090 unsigned char *tmp = csrdata;
3091 if (i2d_X509_REQ(crq, &tmp) != (int)csrsize) {
3092 openssl_error("csr_load");
3093 goto out;
3094 }
3095 #else
3096 csrdata = read_file(file, &csrsize);
3097 if (!csrdata) {
3098 warn("csr_load: failed to read %s", file);
3099 goto out;
3100 }
3101 #endif
3102 #if defined(USE_GNUTLS)
3103 gnutls_datum_t data = {csrdata, csrsize};
3104 r = gnutls_x509_crq_init(&crq);
3105 if (r < 0) {
3106 warnx("csr_load: gnutls_x509_crq_init: %s", gnutls_strerror(r));
3107 goto out;
3108 }
3109 r = gnutls_x509_crq_import(crq, &data, GNUTLS_X509_FMT_PEM);
3110 if (r < 0) {
3111 warnx("csr_load: gnutls_x509_crq_import: %s", gnutls_strerror(r));
3112 goto out;
3113 }
3114 free(csrdata);
3115 csrdata = NULL;
3116 data.data = NULL;
3117 data.size = 0;
3118 r = gnutls_x509_crq_export2(crq, GNUTLS_X509_FMT_DER, &data);
3119 if (r != GNUTLS_E_SUCCESS) {
3120 warnx("csr_load: gnutls_x509_crq_export2: %s", gnutls_strerror(r));
3121 goto out;
3122 }
3123 csrsize = data.size;
3124 csrdata = gnutls_datum_data(&data, true);
3125 if (!csrdata) {
3126 warnx("csr_load: gnutls_datum_data failed");
3127 goto out;
3128 }
3129 #elif defined(USE_MBEDTLS)
3130 r = mbedtls_x509_csr_parse(crq, csrdata, csrsize+1);
3131 if (r < 0) {
3132 warnx("csr_load: mbedtls_x509_csr_parse failed: %s",
3133 _mbedtls_strerror(r));
3134 goto out;
3135 }
3136 mbedtls_pem_context ctx;
3137 mbedtls_pem_init(&ctx);
3138 size_t len;
3139 r = mbedtls_pem_read_buffer(&ctx,
3140 "-----BEGIN CERTIFICATE REQUEST-----",
3141 "-----END CERTIFICATE REQUEST-----",
3142 csrdata, NULL, 0, &len);
3143 if (r) {
3144 warnx("csr_load: mbedtls_pem_read_buffer failed: %s",
3145 _mbedtls_strerror(r));
3146 mbedtls_pem_free(&ctx);
3147 goto out;
3148 }
3149 free(csrdata);
3150 csrsize = ctx.buflen;
3151 csrdata = calloc(1, csrsize);
3152 if (!csrdata) {
3153 warn("csr_load: calloc failed");
3154 mbedtls_pem_free(&ctx);
3155 goto out;
3156 }
3157 memcpy(csrdata, ctx.buf, ctx.buflen);
3158 mbedtls_pem_free(&ctx);
3159 #endif
3160 r = base64_ENCODED_LEN(csrsize, base64_VARIANT_URLSAFE_NO_PADDING);
3161 ret = calloc(1, r);
3162 if (!ret) {
3163 warn("csr_load: calloc failed");
3164 goto out;
3165 }
3166 if (!bin2base64(ret, r, csrdata, csrsize,
3167 base64_VARIANT_URLSAFE_NO_PADDING)) {
3168 warnx("csr_load: bin2base64 failed");
3169 free(ret);
3170 ret = NULL;
3171 goto out;
3172 }
3173 if (names) {
3174 char **tmp = csr_names(crq);
3175 if (tmp)
3176 *names = tmp;
3177 else {
3178 free(ret);
3179 ret = NULL;
3180 }
3181 }
3182 out:
3183 free(csrdata);
3184 #if defined(USE_GNUTLS)
3185 gnutls_x509_crq_deinit(crq);
3186 #elif defined(USE_MBEDTLS)
3187 mbedtls_x509_csr_free(crq);
3188 #elif defined(USE_OPENSSL)
3189 X509_REQ_free(crq);
3190 #endif
3191 return ret;
3192 }
3193
3194 #if defined(USE_GNUTLS)
3195 static int cert_load(gnutls_x509_crt_t *crt, unsigned int crt_size,
3196 const char *format, ...)
3197 #elif defined(USE_OPENSSL)
3198 static int cert_load(X509 **crt, unsigned int crt_size,
3199 const char *format, ...)
3200 #elif defined(USE_MBEDTLS)
3201 static int cert_load(mbedtls_x509_crt **crt, const char *format, ...)
3202 #endif
3203 {
3204 char *certfile = NULL;
3205 #if !defined(USE_OPENSSL)
3206 void *certdata = NULL;
3207 size_t certsize = 0;
3208 #endif
3209 int ret = 0;
3210 int r;
3211 va_list ap;
3212
3213 #if !defined(USE_MBEDTLS)
3214 if (crt_size < 1)
3215 return 0;
3216 #endif
3217
3218 va_start(ap, format);
3219 if (vasprintf(&certfile, format, ap) < 0)
3220 certfile = NULL;
3221 va_end(ap);
3222 if (!certfile) {
3223 warnx("cert_load: vasprintf failed");
3224 goto out;
3225 }
3226
3227 #if defined(USE_OPENSSL)
3228 FILE *f = NULL;
3229 if (!(f = fopen(certfile, "r"))) {
3230 if (errno == ENOENT)
3231 msg(1, "%s does not exist", certfile);
3232 else
3233 warn("cert_load: failed to open %s", certfile);
3234 goto out;
3235 }
3236 for (r = 0; r < (int)crt_size; r++) {
3237 crt[r] = PEM_read_X509(f, NULL, NULL, NULL);
3238 if (!crt[r])
3239 break;
3240 }
3241 fclose(f);
3242 if (r == 0) {
3243 openssl_error("cert_load");
3244 warnx("cert_load: failed to load %s", certfile);
3245 goto out;
3246 }
3247 ret = r;
3248 #else
3249 certdata = read_file(certfile, &certsize);
3250 if (!certdata) {
3251 if (errno == ENOENT)
3252 msg(1, "%s does not exist", certfile);
3253 else
3254 warn("cert_load: failed to read %s", certfile);
3255 goto out;
3256 }
3257 #endif
3258 #if defined(USE_GNUTLS)
3259 gnutls_datum_t data = {certdata, certsize};
3260 r = gnutls_x509_crt_list_import(crt, &crt_size, &data, GNUTLS_X509_FMT_PEM,
3261 GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
3262 if (r < 0) {
3263 warnx("cert_load: gnutls_x509_crt_list_import: %s", gnutls_strerror(r));
3264 goto out;
3265 }
3266 ret = r;
3267 #elif defined(USE_MBEDTLS)
3268 *crt = calloc(1, sizeof(**crt));
3269 if (!*crt) {
3270 warn("cert_load: calloc failed");
3271 goto out;
3272 }
3273 mbedtls_x509_crt_init(*crt);
3274 r = mbedtls_x509_crt_parse(*crt, certdata, certsize+1);
3275 if (r < 0) {
3276 warnx("cert_load: mbedtls_x509_crt_parse failed: %s",
3277 _mbedtls_strerror(r));
3278 mbedtls_x509_crt_free(*crt);
3279 free(*crt);
3280 goto out;
3281 }
3282 if (r > 0) {
3283 warnx("cert_load: failed to parse %d certificates", r);
3284 mbedtls_x509_crt_free(*crt);
3285 free(*crt);
3286 goto out;
3287 }
3288 for (mbedtls_x509_crt *c = *crt; c; c = c->next)
3289 ret++;
3290 #endif
3291 out:
3292 #if !defined(USE_OPENSSL)
3293 free(certdata);
3294 #endif
3295 free(certfile);
3296 return ret;
3297 }
3298
3299 bool cert_match(const char *cert, unsigned char *fingerprint,
3300 size_t fingerprint_len)
3301 {
3302 size_t certsize = strlen(cert);
3303 bool ret = false;
3304
3305 #if defined(USE_GNUTLS)
3306 gnutls_x509_crt_t *crt = NULL;
3307 unsigned int crt_size = 0;
3308 gnutls_datum_t data = {(unsigned char *)cert, certsize};
3309 int r = gnutls_x509_crt_list_import2(&crt, &crt_size, &data,
3310 GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
3311 if (r < 0) {
3312 warnx("cert_match: gnutls_x509_crt_list_import2: %s",
3313 gnutls_strerror(r));
3314 return ret;
3315 }
3316 for (unsigned int i = 0; i < crt_size; i++) {
3317 unsigned char fp[32];
3318 size_t s = sizeof(fp);
3319 r = gnutls_x509_crt_get_fingerprint(crt[i], GNUTLS_DIG_SHA256, fp, &s);
3320 if (r == 0 && fingerprint_len <= s &&
3321 memcmp(fp, fingerprint, fingerprint_len) == 0)
3322 ret = true;
3323 gnutls_x509_crt_deinit(crt[i]);
3324 }
3325 gnutls_free(crt);
3326 #elif defined(USE_OPENSSL)
3327 BIO *bio = BIO_new_mem_buf(cert, certsize);
3328 if (!bio) {
3329 openssl_error("cert_match");
3330 return ret;
3331 }
3332 while (!BIO_eof(bio) && !ret) {
3333 unsigned char fp[32];
3334 unsigned int s = sizeof(fp);
3335 X509 *crt = PEM_read_bio_X509(bio, NULL, NULL, NULL);
3336 if (!crt)
3337 break;
3338 if (X509_digest(crt, EVP_sha256(), fp, &s) &&
3339 fingerprint_len <= s &&
3340 memcmp(fp, fingerprint, fingerprint_len) == 0)
3341 ret = true;
3342 X509_free(crt);
3343 }
3344 BIO_free(bio);
3345 #elif defined(USE_MBEDTLS)
3346 mbedtls_x509_crt crt;
3347 mbedtls_x509_crt_init(&crt);
3348 int r = mbedtls_x509_crt_parse(&crt, (unsigned char *)cert, certsize+1);
3349 if (r < 0) {
3350 warnx("cert_match: mbedtls_x509_crt_parse failed: %s",
3351 _mbedtls_strerror(r));
3352 mbedtls_x509_crt_free(&crt);
3353 return ret;
3354 }
3355 if (r > 0) {
3356 warnx("cert_load: failed to parse %d certificates", r);
3357 mbedtls_x509_crt_free(&crt);
3358 return ret;
3359 }
3360 for (mbedtls_x509_crt *c = &crt; c; c = c->next) {
3361 unsigned char fp[32];
3362 r = mbedtls_hash_fast(MBEDTLS_MD_SHA256, c->raw.p, c->raw.len, fp);
3363 if (r == 0 && fingerprint_len <= sizeof(fp) &&
3364 memcmp(fp, fingerprint, fingerprint_len) == 0)
3365 ret = true;
3366 }
3367 mbedtls_x509_crt_free(&crt);
3368 #endif
3369 return ret;
3370 }
3371 #if defined(USE_GNUTLS)
3372 static bool ocsp_check(gnutls_x509_crt_t *crt)
3373 {
3374 bool result = true;
3375 char *ocsp_uri = NULL;
3376 gnutls_ocsp_req_t req = NULL;
3377 gnutls_ocsp_resp_t rsp = NULL;
3378 gnutls_datum_t nreq = {NULL, 0};
3379 gnutls_datum_t nrsp = {NULL, 0};
3380 gnutls_datum_t req_data = {NULL, 0};
3381 gnutls_datum_t d = {NULL, 0};
3382 curldata_t *cd = NULL;
3383 int rc;
3384
3385 if (!crt[0] || !crt[1])
3386 goto out;
3387
3388 for (unsigned int seq = 0; true; seq++) {
3389 d.data = NULL;
3390 d.size = 0;
3391 rc = gnutls_x509_crt_get_authority_info_access(crt[0], seq,
3392 GNUTLS_IA_OCSP_URI, &d, NULL);
3393 if (rc == GNUTLS_E_UNKNOWN_ALGORITHM)
3394 continue;
3395 else if (rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
3396 break;
3397 else if (rc != GNUTLS_E_SUCCESS) {
3398 warnx("ocsp_check: unable to retrieve OCSP URI: %s",
3399 gnutls_strerror(rc));
3400 break;
3401 }
3402 ocsp_uri = calloc(1, d.size+1);
3403 if (!ocsp_uri) {
3404 warn("ocsp_check: calloc failed");
3405 gnutls_free(d.data);
3406 break;
3407 }
3408 memcpy(ocsp_uri, d.data, d.size);
3409 gnutls_free(d.data);
3410 break;
3411 }
3412 if (!ocsp_uri)
3413 goto out;
3414
3415 rc = gnutls_ocsp_req_init(&req);
3416 if (rc != GNUTLS_E_SUCCESS) {
3417 warnx("ocsp_check: gnutls_ocsp_req_init failed: %s",
3418 gnutls_strerror(rc));
3419 goto out;
3420 }
3421
3422 rc = gnutls_ocsp_req_add_cert(req, GNUTLS_DIG_SHA1, crt[1], crt[0]);
3423 if (rc != GNUTLS_E_SUCCESS) {
3424 warnx("ocsp_check: gnutls_ocsp_req_add_cert failed: %s",
3425 gnutls_strerror(rc));
3426 goto out;
3427 }
3428
3429 rc = gnutls_ocsp_req_randomize_nonce(req);
3430 if (rc != GNUTLS_E_SUCCESS) {
3431 warnx("ocsp_check: gnutls_ocsp_req_randomize failed: %s",
3432 gnutls_strerror(rc));
3433 goto out;
3434 }
3435
3436 rc = gnutls_ocsp_req_export(req, &req_data);
3437 if (rc != GNUTLS_E_SUCCESS) {
3438 warnx("ocsp_check: gnutls_ocsp_req_export failed: %s",
3439 gnutls_strerror(rc));
3440 goto out;
3441 }
3442
3443 d.data = NULL;
3444 d.size = 0;
3445 rc = gnutls_ocsp_req_print(req, GNUTLS_OCSP_PRINT_FULL, &d);
3446 if (rc != GNUTLS_E_SUCCESS) {
3447 warnx("ocsp_check: gnutls_ocsp_req_print failed: %s",
3448 gnutls_strerror(rc));
3449 gnutls_free(d.data);
3450 goto out;
3451 }
3452 msg(2, "ocsp_check: %.*s", d.size, d.data);
3453 gnutls_free(d.data);
3454
3455 msg(1, "querying OCSP server at %s", ocsp_uri);
3456 msg_hd(3, "ocsp_check: HTTP post:\n", req_data.data, req_data.size);
3457 cd = curl_post(ocsp_uri, req_data.data, req_data.size,
3458 "Content-Type: application/ocsp-request", NULL);
3459 if (!cd) {
3460 warnx("ocsp_check: curl_post(\"%s\") failed", ocsp_uri);
3461 goto out;
3462 }
3463
3464 if (cd->headers)
3465 msg(3, "ocsp_check: HTTP headers:\n%s", cd->headers);
3466 if (cd->body)
3467 msg_hd(3, "ocsp_check: HTTP body:\n", cd->body, cd->body_len);
3468
3469 rc = gnutls_ocsp_resp_init(&rsp);
3470 if (rc != GNUTLS_E_SUCCESS) {
3471 warnx("ocsp_check: gnutls_ocsp_resp_init failed: %s",
3472 gnutls_strerror(rc));
3473 goto out;
3474 }
3475
3476 d.data = (unsigned char *)cd->body;
3477 d.size = cd->body_len;
3478 rc = gnutls_ocsp_resp_import(rsp, &d);
3479 if (rc != GNUTLS_E_SUCCESS) {
3480 warnx("ocsp_check: gnutls_ocsp_resp_import failed: %s",
3481 gnutls_strerror(rc));
3482 goto out;
3483 }
3484
3485 d.data = NULL;
3486 d.size = 0;
3487 rc = gnutls_ocsp_resp_print(rsp, GNUTLS_OCSP_PRINT_FULL, &d);
3488 if (rc != GNUTLS_E_SUCCESS) {
3489 warnx("ocsp_check: gnutls_ocsp_resp_print failed: %s",
3490 gnutls_strerror(rc));
3491 gnutls_free(d.data);
3492 goto out;
3493 }
3494 msg(2, "ocsp_check: %.*s", d.size, d.data);
3495 gnutls_free(d.data);
3496
3497 unsigned int verify;
3498 rc = gnutls_ocsp_resp_verify_direct(rsp, crt[1], &verify, 0);
3499 if (rc != GNUTLS_E_SUCCESS) {
3500 warnx("ocsp_check: gnutls_ocsp_resp_verify_direct failed: %s",
3501 gnutls_strerror(rc));
3502 goto out;
3503 }
3504
3505 if (verify != 0) {
3506 warnx("warning: failed to verify OCSP response (%d)", verify);
3507 goto out;
3508 }
3509
3510 rc = gnutls_ocsp_resp_get_status(rsp);
3511 if (rc != GNUTLS_OCSP_RESP_SUCCESSFUL) {
3512 if (rc < 0)
3513 warnx("ocsp_check: gnutls_ocsp_resp_get_status failed: %s",
3514 gnutls_strerror(rc));
3515 else
3516 warnx("OCSP response was unsuccessful (%d)", rc);
3517 goto out;
3518 }
3519
3520 rc = gnutls_ocsp_resp_check_crt(rsp, 0, crt[0]);
3521 if (rc != GNUTLS_E_SUCCESS) {
3522 warnx("ocsp_check: gnutls_ocsp_resp_check_crt failed: %s",
3523 gnutls_strerror(rc));
3524 goto out;
3525 }
3526
3527 rc = gnutls_ocsp_req_get_nonce(req, NULL, &nreq);
3528 if (rc != GNUTLS_E_SUCCESS) {
3529 warnx("ocsp_check: gnutls_ocsp_req_get_nonce failed: %s",
3530 gnutls_strerror(rc));
3531 goto out;
3532 }
3533
3534 rc = gnutls_ocsp_resp_get_nonce(rsp, NULL, &nrsp);
3535 if (rc != GNUTLS_E_SUCCESS) {
3536 if (rc != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
3537 warnx("ocsp_check: gnutls_ocsp_rsp_get_nonce failed: %s",
3538 gnutls_strerror(rc));
3539 goto out;
3540 } else
3541 msg(1, "OCSP response has no nonce");
3542 } else if (nreq.size != nrsp.size ||
3543 memcmp(nreq.data, nrsp.data, nreq.size)) {
3544 warnx("warning: OCSP response nonce mismatch");
3545 goto out;
3546 }
3547
3548 unsigned int cert_status;
3549 rc = gnutls_ocsp_resp_get_single(rsp, 0, NULL, NULL, NULL, NULL,
3550 &cert_status, NULL, NULL, NULL, NULL);
3551 if (rc != GNUTLS_E_SUCCESS) {
3552 warnx("ocsp_check: gnutls_ocsp_rsp_get_single failed: %s",
3553 gnutls_strerror(rc));
3554 goto out;
3555 }
3556
3557 switch (cert_status) {
3558 case GNUTLS_OCSP_CERT_GOOD:
3559 msg(1, "OCSP certificate status is GOOD");
3560 break;
3561
3562 case GNUTLS_OCSP_CERT_REVOKED:
3563 warnx("OCSP certificate status is REVOKED");
3564 result = false;
3565 break;
3566
3567 case GNUTLS_OCSP_CERT_UNKNOWN:
3568 default:
3569 msg(1, "OCSP certificate status is UNKNOWN");
3570 break;
3571 }
3572
3573 out:
3574 if (req)
3575 gnutls_ocsp_req_deinit(req);
3576 if (rsp)
3577 gnutls_ocsp_resp_deinit(rsp);
3578 gnutls_free(req_data.data);
3579 gnutls_free(nreq.data);
3580 gnutls_free(nrsp.data);
3581 curldata_free(cd);
3582 free(ocsp_uri);
3583 return result;
3584 }
3585 #elif defined(USE_OPENSSL)
3586 static bool ocsp_check(X509 **crt)
3587 {
3588 bool result = true;
3589 char *ocsp_uri = NULL;
3590 OCSP_REQUEST *req = NULL;
3591 unsigned char *reqdata = NULL;
3592 int reqsize = 0;
3593 OCSP_RESPONSE *rsp = NULL;
3594 OCSP_BASICRESP *brsp = NULL;
3595 OCSP_CERTID *id = NULL;
3596 STACK_OF(OCSP_CERTID) *ids = NULL;
3597 STACK_OF(OPENSSL_STRING) *ocsp_uris = NULL;
3598 STACK_OF(X509) *issuers = NULL;
3599 curldata_t *cd = NULL;
3600 int rc;
3601
3602 if (!crt[0] || !crt[1])
3603 goto out;
3604
3605 ocsp_uris = X509_get1_ocsp(crt[0]);
3606 if (!ocsp_uris) {
3607 openssl_error("ocsp_check");
3608 goto out;
3609 }
3610 for (int j = 0; !ocsp_uri && j < sk_OPENSSL_STRING_num(ocsp_uris); j++) {
3611 char *uri = sk_OPENSSL_STRING_value(ocsp_uris, j);
3612 if (uri && strlen(uri)) {
3613 ocsp_uri = strdup(uri);
3614 if (!ocsp_uri) {
3615 warn("ocsp_check: strdup failed");
3616 goto out;
3617 }
3618 }
3619 }
3620 if (!ocsp_uri)
3621 goto out;
3622
3623 req = OCSP_REQUEST_new();
3624 if (!req) {
3625 openssl_error("ocsp_check");
3626 goto out;
3627 }
3628
3629 ids = sk_OCSP_CERTID_new_null();
3630 if (!ids) {
3631 openssl_error("ocsp_check");
3632 goto out;
3633 }
3634
3635 id = OCSP_cert_to_id(EVP_sha1(), crt[0], crt[1]);
3636 if (!id || !sk_OCSP_CERTID_push(ids, id)) {
3637 openssl_error("ocsp_check");
3638 goto out;
3639 }
3640
3641 if (!OCSP_request_add0_id(req, id)) {
3642 openssl_error("ocsp_check");
3643 goto out;
3644 }
3645
3646 if (!OCSP_request_add1_nonce(req, NULL, -1)) {
3647 openssl_error("ocsp_check");
3648 goto out;
3649 }
3650
3651 rc = i2d_OCSP_REQUEST(req, NULL);
3652 if (rc < 0) {
3653 openssl_error("ocsp_check");
3654 goto out;
3655 }
3656 reqsize = rc;
3657 reqdata = calloc(1, reqsize);
3658 if (!reqdata) {
3659 warn("ocsp_check: calloc failed");
3660 goto out;
3661 }
3662 unsigned char *tmp = reqdata;
3663 if (i2d_OCSP_REQUEST(req, &tmp) != reqsize) {
3664 openssl_error("ocsp_check");
3665 goto out;
3666 }
3667
3668 if (g_loglevel > 1) {
3669 BIO *out = BIO_new(BIO_s_mem());
3670 if (out) {
3671 if (OCSP_REQUEST_print(out, req, 0)) {
3672 char *data = NULL;
3673 int size = BIO_get_mem_data(out, &data);
3674 warnx("ocsp_check: %.*s", size, data);
3675 }
3676 BIO_free(out);
3677 }
3678 }
3679
3680 msg(1, "querying OCSP server at %s", ocsp_uri);
3681 msg_hd(3, "ocsp_check: HTTP post:\n", reqdata, reqsize);
3682 cd = curl_post(ocsp_uri, reqdata, reqsize,
3683 "Content-Type: application/ocsp-request", NULL);
3684 if (!cd) {
3685 warnx("ocsp_check: curl_post(\"%s\") failed", ocsp_uri);
3686 goto out;
3687 }
3688
3689 if (cd->headers)
3690 msg(3, "ocsp_check: HTTP headers:\n%s", cd->headers);
3691 if (cd->body)
3692 msg_hd(3, "ocsp_check: HTTP body:\n", cd->body, cd->body_len);
3693
3694 const unsigned char *tmp2 = (const unsigned char *)cd->body;
3695 rsp = d2i_OCSP_RESPONSE(NULL, &tmp2, cd->body_len);
3696 if (!rsp) {
3697 openssl_error("ocsp_check");
3698 goto out;
3699 }
3700
3701 if (g_loglevel > 1) {
3702 BIO *out = BIO_new(BIO_s_mem());
3703 if (out) {
3704 if (OCSP_RESPONSE_print(out, rsp, 0)) {
3705 char *data = NULL;
3706 int size = BIO_get_mem_data(out, &data);
3707 warnx("ocsp_check: %.*s", size, data);
3708 }
3709 BIO_free(out);
3710 }
3711 }
3712
3713 rc = OCSP_response_status(rsp);
3714 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
3715 if (rc < 0)
3716 openssl_error("ocsp_check");
3717 else
3718 warnx("OCSP response was unsuccessful (%d)", rc);
3719 goto out;
3720 }
3721
3722 brsp = OCSP_response_get1_basic(rsp);
3723 if (!brsp) {
3724 openssl_error("ocsp_check");
3725 goto out;
3726 }
3727
3728 rc = OCSP_check_nonce(req, brsp);
3729 if (rc < 0)
3730 msg(1, "OCSP response has no nonce");
3731 else if (rc == 0) {
3732 warnx("ocsp_check: OCSP_check_nonce failed");
3733 goto out;
3734 }
3735
3736 issuers = sk_X509_new_null();
3737 if (!issuers) {
3738 openssl_error("ocsp_check");
3739 goto out;
3740 }
3741 sk_X509_push(issuers, crt[1]);
3742
3743 if (OCSP_basic_verify(brsp, issuers, NULL, OCSP_TRUSTOTHER) <= 0) {
3744 openssl_error("ocsp_check");
3745 goto out;
3746 }
3747
3748 int status;
3749 if (!OCSP_resp_find_status(brsp, id, &status, NULL, NULL, NULL, NULL)) {
3750 openssl_error("ocsp_check");
3751 goto out;
3752 }
3753
3754 switch (status) {
3755 case V_OCSP_CERTSTATUS_GOOD:
3756 msg(1, "OCSP certificate status is GOOD");
3757 break;
3758
3759 case V_OCSP_CERTSTATUS_REVOKED:
3760 warnx("OCSP certificate status is REVOKED");
3761 result = false;
3762 break;
3763
3764 case V_OCSP_CERTSTATUS_UNKNOWN:
3765 default:
3766 msg(1, "OCSP certificate status is UNKNOWN");
3767 break;
3768 }
3769
3770 out:
3771 free(ocsp_uri);
3772 free(reqdata);
3773 if (cd)
3774 curldata_free(cd);
3775 if (req)
3776 OCSP_REQUEST_free(req);
3777 if (rsp)
3778 OCSP_RESPONSE_free(rsp);
3779 if (brsp)
3780 OCSP_BASICRESP_free(brsp);
3781 if (ids)
3782 sk_OCSP_CERTID_free(ids);
3783 if (ocsp_uris)
3784 X509_email_free(ocsp_uris);
3785 if (issuers)
3786 sk_X509_free(issuers);
3787 return result;
3788 }
3789 #elif defined(USE_MBEDTLS)
3790 #define OID_AUTHORITY_INFO_ACCESS MBEDTLS_OID_PKIX "\x01\x01"
3791 #define OID_AD_OCSP MBEDTLS_OID_PKIX "\x30\x01"
3792 #define OID_AD_OCSP_BASIC OID_AD_OCSP "\x01"
3793 #define OID_AD_OCSP_NONCE OID_AD_OCSP "\x02"
3794
3795 static int ext_parse_ocsp_uri(unsigned char *p, size_t len, const char **out)
3796 {
3797 unsigned char *end = p + len;
3798 unsigned char *end_ext;
3799 unsigned char *end_ad;
3800 int r;
3801
3802 r = mbedtls_asn1_get_tag(&p, end, &len,
3803 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
3804 if (r)
3805 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
3806
3807 if (end != p + len)
3808 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
3809 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
3810
3811 while (p < end) {
3812 r = mbedtls_asn1_get_tag(&p, end, &len,
3813 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
3814 if (r)
3815 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
3816
3817 end_ext = p + len;
3818
3819 r = mbedtls_asn1_get_tag(&p, end_ext, &len, MBEDTLS_ASN1_OID);
3820 if (r)
3821 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
3822
3823 if (len != MBEDTLS_OID_SIZE(OID_AUTHORITY_INFO_ACCESS) ||
3824 memcmp(OID_AUTHORITY_INFO_ACCESS, p, len) != 0) {
3825 p = end_ext;
3826 continue;
3827 }
3828
3829 p += len;
3830
3831 int crit;
3832 r = mbedtls_asn1_get_bool(&p, end_ext, &crit);
3833 if (r && r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
3834 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
3835
3836 r = mbedtls_asn1_get_tag(&p, end_ext, &len, MBEDTLS_ASN1_OCTET_STRING);
3837 if (r)
3838 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
3839
3840 if (p + len != end_ext)
3841 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
3842 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
3843
3844 r = mbedtls_asn1_get_tag(&p, end_ext, &len,
3845 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
3846 if (r)
3847 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
3848
3849 if (p + len != end_ext)
3850 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
3851 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
3852
3853 while (p < end_ext) {
3854 r = mbedtls_asn1_get_tag(&p, end_ext, &len,
3855 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
3856 if (r)
3857 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
3858
3859 end_ad = p + len;
3860
3861 r = mbedtls_asn1_get_tag(&p, end_ad, &len, MBEDTLS_ASN1_OID);
3862 if (r)
3863 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + r;
3864
3865 if (len != MBEDTLS_OID_SIZE(OID_AD_OCSP) ||
3866 memcmp(OID_AD_OCSP, p, len) != 0) {
3867 p = end_ad;
3868 continue;
3869 }
3870
3871 p += len;
3872
3873 r = mbedtls_asn1_get_tag(&p, end_ad, &len,
3874 MBEDTLS_ASN1_CONTEXT_SPECIFIC | 6);
3875 if (r) {
3876 p = end_ad;
3877 continue;
3878 }
3879
3880 *out = (const char *)p;
3881 return len;
3882 }
3883
3884 if (p != end_ext)
3885 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
3886 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
3887 }
3888 return 0;
3889 }
3890
3891 static int ocsp_req(mbedtls_x509_crt *crt, unsigned char *req, size_t size,
3892 const unsigned char **certid, size_t *certid_size)
3893 {
3894 int ret = 0;
3895 size_t ext_len = 0;
3896 size_t len = 0;
3897 const char *alg_oid;
3898 size_t alg_oid_len = 0;
3899 unsigned char hash[20];
3900 unsigned char *p = req + size;
3901 mbedtls_x509_crt *issuer = crt->next;
3902
3903 if (!issuer)
3904 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
3905
3906 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&p, req,
3907 crt->serial.p, crt->serial.len));
3908 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, req,
3909 crt->serial.len));
3910 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, req,
3911 crt->serial.tag));
3912
3913 for (size_t buf_size = 0x400; ; ) {
3914 unsigned char *buf = mbedtls_calloc(1, buf_size);
3915 if (!buf)
3916 return MBEDTLS_ERR_X509_ALLOC_FAILED;
3917 unsigned char *c = buf + buf_size;
3918 ret = mbedtls_pk_write_pubkey(&c, buf, &issuer->pk);
3919 if (ret >= 0)
3920 ret = mbedtls_sha1_ret(buf + buf_size - ret, ret, hash);
3921 mbedtls_free(buf);
3922 if (ret == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {
3923 buf_size *= 2;
3924 continue;
3925 }
3926 if (ret < 0)
3927 return ret;
3928 break;
3929 }
3930
3931 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_octet_string(&p, req,
3932 hash, sizeof(hash)));
3933
3934 ret = mbedtls_sha1_ret(crt->issuer_raw.p, crt->issuer_raw.len, hash);
3935 if (ret)
3936 return ret;
3937
3938 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_octet_string(&p, req,
3939 hash, sizeof(hash)));
3940
3941 ret = mbedtls_oid_get_oid_by_md(MBEDTLS_MD_SHA1, &alg_oid, &alg_oid_len);
3942 if (ret)
3943 return ret;
3944
3945 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(&p, req,
3946 alg_oid, alg_oid_len, 0));
3947
3948 if (certid)
3949 *certid = p;
3950 if (certid_size)
3951 *certid_size = len;
3952
3953 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, req, len));
3954 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, req,
3955 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
3956
3957 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, req, len));
3958 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, req,
3959 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
3960
3961 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, req, len));
3962 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, req,
3963 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
3964
3965 len += ext_len;
3966
3967 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, req, len));
3968 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, req,
3969 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
3970
3971 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, req, len));
3972 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, req,
3973 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
3974
3975 memmove(req, p, len);
3976 if (certid)
3977 *certid -= p - req;
3978 return len;
3979 }
3980
3981 static int ocsp_resp(unsigned char *p, size_t len,
3982 const unsigned char *certid, size_t certid_size, int *status)
3983 {
3984 const unsigned char *end = p + len;
3985 int i, r;
3986
3987 r = mbedtls_asn1_get_tag(&p, end, &len,
3988 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
3989 if (r)
3990 return r;
3991
3992 r = mbedtls_asn1_get_tag(&p, end, &len, 10); // ASN1_ENUMERATED
3993 if (r)
3994 return r;
3995
3996 if (len == 0 || len > sizeof(int) || (*p & 0x80))
3997 return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
3998
3999 while (len--)
4000 r = (r << 8) | *p++;
4001 if (r)
4002 return r;
4003
4004 r = mbedtls_asn1_get_tag(&p, end, &len,
4005 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
4006 if (r)
4007 return r;
4008
4009 r = mbedtls_asn1_get_tag(&p, end, &len,
4010 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
4011 if (r)
4012 return r;
4013 end = p + len;
4014
4015 r = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID);
4016 if (r)
4017 return r;
4018
4019 if (len != MBEDTLS_OID_SIZE(OID_AD_OCSP_BASIC) ||
4020 memcmp(OID_AD_OCSP_BASIC, p, len) != 0)
4021 return MBEDTLS_ERR_ASN1_INVALID_DATA;
4022 p += len;
4023
4024 r = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
4025 if (r)
4026 return r;
4027 end = p + len;
4028
4029 r = mbedtls_asn1_get_tag(&p, end, &len,
4030 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
4031 if (r)
4032 return r;
4033 end = p + len;
4034
4035 r = mbedtls_asn1_get_tag(&p, end, &len,
4036 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
4037 if (r)
4038 return r;
4039 end = p + len;
4040
4041 r = mbedtls_asn1_get_tag(&p, end, &len,
4042 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
4043 if (r && r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
4044 return r;
4045 if (r == 0) {
4046 int ver = 0;
4047 r = mbedtls_asn1_get_int(&p, end, &ver);
4048 if (r)
4049 return r;
4050 if (ver)
4051 return MBEDTLS_ERR_ASN1_INVALID_DATA;
4052 }
4053
4054 for (i = 1; i < 3; i++) {
4055 r = mbedtls_asn1_get_tag(&p, end, &len,
4056 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC | i);
4057 if (r && r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
4058 return r;
4059 if (r == 0)
4060 break;
4061 }
4062 if (i > 2)
4063 return MBEDTLS_ERR_ASN1_INVALID_DATA;
4064 p += len;
4065
4066 r = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_GENERALIZED_TIME);
4067 if (r)
4068 return r;
4069 p += len;
4070
4071 r = mbedtls_asn1_get_tag(&p, end, &len,
4072 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
4073 if (r)
4074 return r;
4075
4076 r = mbedtls_asn1_get_tag(&p, end, &len,
4077 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
4078 if (r)
4079 return r;
4080
4081 r = mbedtls_asn1_get_tag(&p, end, &len,
4082 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
4083 if (r)
4084 return r;
4085 if (certid_size != len || memcmp(certid, p, len) != 0)
4086 return MBEDTLS_ERR_ASN1_INVALID_DATA;
4087 p += len;
4088
4089 for (i = 0; i < 3; i++) {
4090 r = mbedtls_asn1_get_tag(&p, end, &len,
4091 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC | i);
4092 if (r && r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
4093 return r;
4094 if (r == 0)
4095 break;
4096
4097 r = mbedtls_asn1_get_tag(&p, end, &len,
4098 MBEDTLS_ASN1_CONTEXT_SPECIFIC | i);
4099 if (r && r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
4100 return r;
4101 if (r == 0)
4102 break;
4103 }
4104 if (i > 2)
4105 return MBEDTLS_ERR_ASN1_INVALID_DATA;
4106 else if (status)
4107 *status = i;
4108
4109 return 0;
4110 }
4111
4112 static bool ocsp_check(mbedtls_x509_crt *crt)
4113 {
4114 bool result = true;
4115 char *ocsp_uri = NULL;
4116 curldata_t *cd = NULL;
4117 unsigned char *req = NULL;
4118 size_t req_size = 0x100;
4119 const unsigned char *certid = NULL;
4120 size_t certid_size = 0;
4121
4122 if (!crt->v3_ext.p || crt->v3_ext.len == 0)
4123 goto out;
4124
4125 const char *tmp = NULL;
4126 int r = ext_parse_ocsp_uri(crt->v3_ext.p, crt->v3_ext.len, &tmp);
4127 if (r < 0)
4128 warnx("ocsp_check: ext_parse_ocsp_uri failed: %s",
4129 _mbedtls_strerror(r));
4130 else if (r == 0)
4131 goto out;
4132
4133 ocsp_uri = strndup(tmp, r);
4134 if (!ocsp_uri) {
4135 warn("ocsp_check: strndup failed");
4136 goto out;
4137 }
4138
4139 while (!req) {
4140 req = calloc(1, req_size);
4141 if (!req) {
4142 warn("ocsp_check: calloc failed");
4143 goto out;
4144 }
4145 r = ocsp_req(crt, req, req_size, &certid, &certid_size);
4146 if (r == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {
4147 free(req);
4148 req = NULL;
4149 req_size *= 2;
4150 }
4151 else if (r < 0) {
4152 warnx("ocsp_check: ocsp_req failed: %s", _mbedtls_strerror(r));
4153 goto out;
4154 } else
4155 req_size = r;
4156 }
4157
4158 msg(1, "querying OCSP server at %s", ocsp_uri);
4159 msg_hd(3, "ocsp_check: HTTP post:\n", req, req_size);
4160 cd = curl_post(ocsp_uri, req, req_size,
4161 "Content-Type: application/ocsp-request", NULL);
4162 if (!cd) {
4163 warnx("ocsp_check: curl_post(\"%s\") failed", ocsp_uri);
4164 goto out;
4165 }
4166
4167 if (cd->headers)
4168 msg(3, "ocsp_check: HTTP headers:\n%s", cd->headers);
4169 if (cd->body)
4170 msg_hd(3, "ocsp_check: HTTP body:\n", cd->body, cd->body_len);
4171
4172 int status;
4173 r = ocsp_resp((unsigned char *)cd->body, cd->body_len, certid, certid_size,
4174 &status);
4175 if (r < 0) {
4176 warnx("ocsp_check: ocsp_resp failed: %s",
4177 _mbedtls_strerror(r));
4178 goto out;
4179 } else if (r > 0) {
4180 warnx("OCSP response was unsuccessful (%d)", r);
4181 goto out;
4182 } else switch (status) {
4183 case 0: // GOOD
4184 msg(1, "OCSP certificate status is GOOD");
4185 break;
4186
4187 case 1: // REVOKED
4188 warnx("OCSP certificate status is REVOKED");
4189 result = false;
4190 break;
4191
4192 case 2: // UNKNOWN
4193 default:
4194 msg(1, "OCSP certificate status is UNKNOWN");
4195 break;
4196 }
4197
4198 out:
4199 free(ocsp_uri);
4200 free(req);
4201 if (cd)
4202 curldata_free(cd);
4203 return result;
4204 }
4205 #endif
4206
4207 bool cert_valid(const char *certfile, char * const *names, int validity,
4208 bool status_check)
4209 {
4210 bool valid = false;
4211 #if defined(USE_GNUTLS)
4212 gnutls_x509_crt_t crt[2] = {NULL, NULL};
4213 int ncrt = cert_load(crt, 2, "%s", certfile);
4214 if (ncrt <= 0)
4215 goto out;
4216
4217 time_t expiration = gnutls_x509_crt_get_expiration_time(crt[0]);
4218 if (expiration == (time_t)-1) {
4219 warnx("cert_valid: gnutls_x509_crt_get_expiration_time failed");
4220 goto out;
4221 }
4222
4223 int days_left = (expiration - time(NULL))/(24*3600);
4224 msg(1, "%s expires in %d days", certfile, days_left);
4225 if (days_left < validity) {
4226 msg(1, "%s is due for renewal", certfile);
4227 goto out;
4228 }
4229
4230 while (names && *names) {
4231 if (!gnutls_x509_crt_check_hostname2(crt[0], *names,
4232 GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
4233 msg(1, "%s does not include %s", certfile, *names);
4234 goto out;
4235 }
4236 names++;
4237 }
4238
4239 valid = true;
4240 if (status_check) {
4241 if (ncrt < 2)
4242 warn("no issuer certificate in %s, skipping OCSP check", certfile);
4243 else
4244 valid = ocsp_check(crt);
4245 }
4246 out:
4247 for (int i = 0; i < ncrt; i++)
4248 if (crt[i])
4249 gnutls_x509_crt_deinit(crt[i]);
4250 #elif defined(USE_OPENSSL)
4251 GENERAL_NAMES *san = NULL;
4252 X509_NAME *sname = NULL;
4253 X509 *crt[2] = {NULL, NULL};
4254 int ncrt = cert_load(crt, 2, "%s", certfile);
4255 if (ncrt <= 0)
4256 goto out;
4257 int days_left, sec;
4258 const ASN1_TIME *tm = X509_get0_notAfter(crt[0]);
4259 if (!tm || !ASN1_TIME_diff(&days_left, &sec, NULL, tm)) {
4260 warnx("cert_valid: invalid expiration time format in %s", certfile);
4261 goto out;
4262 }
4263 msg(1, "%s expires in %d days", certfile, days_left);
4264 if (days_left < validity) {
4265 msg(1, "%s is due for renewal", certfile);
4266 goto out;
4267 }
4268
4269 int crit = 0;
4270 san = X509_get_ext_d2i(crt[0], NID_subject_alt_name, &crit, NULL);
4271 if (!san && crit < 0) {
4272 openssl_error("cert_valid");
4273 goto out;
4274 }
4275
4276 sname = X509_get_subject_name(crt[0]);
4277
4278 while (names && *names) {
4279 bool found = false;
4280
4281 int count = sk_GENERAL_NAME_num(san);
4282 while (count-- && !found) {
4283 GENERAL_NAME *name = sk_GENERAL_NAME_value(san, count);
4284 if (!name)
4285 continue;
4286 int type;
4287 ASN1_STRING *value = GENERAL_NAME_get0_value(name, &type);
4288 if (!value)
4289 continue;
4290 if (type == GEN_DNS) {
4291 unsigned char *s = NULL;
4292 if (ASN1_STRING_to_UTF8(&s, (ASN1_STRING *)value) < 0) {
4293 openssl_error("cert_valid");
4294 continue;
4295 } else if (s) {
4296 if (strcasecmp((char *)s, *names) == 0)
4297 found = true;
4298 OPENSSL_free(s);
4299 }
4300 } else if (type == GEN_IPADD) {
4301 char s[INET6_ADDRSTRLEN];
4302 int af;
4303 switch (ASN1_STRING_length(value)) {
4304 case 4:
4305 af = AF_INET;
4306 break;
4307 case 16:
4308 af = AF_INET6;
4309 break;
4310 default:
4311 continue;
4312 }
4313 memset(s, 0, sizeof(s));
4314 if (!inet_ntop(af, ASN1_STRING_get0_data(value), s, sizeof(s)))
4315 continue;
4316 if (strcasecmp(s, *names) == 0)
4317 found = true;
4318 }
4319 }
4320
4321 if (sname) {
4322 for (int i = -1; !found; ) {
4323 i = X509_NAME_get_index_by_NID(sname, NID_commonName, i);
4324 if (i < 0)
4325 break;
4326 X509_NAME_ENTRY *entry = X509_NAME_get_entry(sname, i);
4327 if (!entry)
4328 continue;
4329 ASN1_STRING *str = X509_NAME_ENTRY_get_data(entry);
4330 if (!str)
4331 continue;
4332 unsigned char *s = NULL;
4333 if (ASN1_STRING_to_UTF8(&s, str) < 0) {
4334 openssl_error("cert_valid");
4335 continue;
4336 }
4337 if (strcasecmp((char *)s, *names) == 0)
4338 found = true;
4339 OPENSSL_free(s);
4340 }
4341 }
4342
4343 if (!found) {
4344 msg(1, "%s does not include %s", certfile, *names);
4345 goto out;
4346 }
4347 names++;
4348 }
4349
4350 valid = true;
4351 if (status_check) {
4352 if (ncrt < 2)
4353 warn("no issuer certificate in %s, skipping OCSP check", certfile);
4354 else
4355 valid = ocsp_check(crt);
4356 }
4357 out:
4358 for (int i = 0; i < ncrt; i++)
4359 if (crt[i])
4360 X509_free(crt[i]);
4361 if (san)
4362 GENERAL_NAMES_free(san);
4363 #elif defined(USE_MBEDTLS)
4364 mbedtls_x509_crt *crt = NULL;
4365 mbedtls_x509_sequence san;
4366 memset(&san, 0, sizeof(san));
4367
4368 int ncrt = cert_load(&crt, "%s", certfile);
4369 if (ncrt < 1)
4370 goto out;
4371
4372 struct tm texp = {
4373 .tm_sec = crt->valid_to.sec,
4374 .tm_min = crt->valid_to.min,
4375 .tm_hour = crt->valid_to.hour,
4376 .tm_mday = crt->valid_to.day,
4377 .tm_mon = crt->valid_to.mon - 1,
4378 .tm_year = crt->valid_to.year - 1900,
4379 .tm_isdst = -1
4380 };
4381
4382 time_t expiration = mktime(&texp);
4383 if (expiration == (time_t)-1) {
4384 warnx("cert_valid: failed to determine expiration time");
4385 goto out;
4386 }
4387
4388 int days_left = (expiration - time(NULL))/(24*3600);
4389 msg(1, "%s expires in %d days", certfile, days_left);
4390 if (days_left < validity) {
4391 msg(1, "%s is due for renewal", certfile);
4392 goto out;
4393 }
4394
4395 if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
4396 int r = ext_san(crt->v3_ext.p, crt->v3_ext.len, &san);
4397 if (r) {
4398 warnx("cert_valid: ext_san failed: %s", _mbedtls_strerror(r));
4399 goto out;
4400 }
4401 }
4402
4403 while (names && *names) {
4404 bool found = false;
4405 const mbedtls_x509_name *name = NULL;
4406 const mbedtls_x509_sequence *cur = NULL;
4407
4408 for (cur = &san; cur && !found; cur = cur->next) {
4409 if (cur->buf.tag == (MBEDTLS_ASN1_CONTEXT_SPECIFIC|2)) {
4410 if (strncasecmp(*names, (const char *)cur->buf.p,
4411 strlen(*names)) == 0)
4412 found = true;
4413 } else if (cur->buf.tag == (MBEDTLS_ASN1_CONTEXT_SPECIFIC|7)) {
4414 char s[INET6_ADDRSTRLEN];
4415 int af;
4416 switch (cur->buf.len) {
4417 case 4:
4418 af = AF_INET;
4419 break;
4420 case 16:
4421 af = AF_INET6;
4422 break;
4423 default:
4424 continue;
4425 }
4426 memset(s, 0, sizeof(s));
4427 if (!inet_ntop(af, cur->buf.p, s, sizeof(s)))
4428 continue;
4429 if (strcasecmp(s, *names) == 0)
4430 found = true;
4431 }
4432 }
4433 for (name = &crt->subject; name != NULL && !found; name = name->next) {
4434 if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 &&
4435 strncasecmp(*names, (const char *)name->val.p,
4436 strlen(*names)) == 0)
4437 found = true;
4438 }
4439 if (!found) {
4440 msg(1, "%s does not include %s", certfile, *names);
4441 goto out;
4442 }
4443 names++;
4444 }
4445
4446 valid = true;
4447 if (status_check) {
4448 if (ncrt < 2)
4449 warn("no issuer certificate in %s, skipping OCSP check", certfile);
4450 else
4451 valid = ocsp_check(crt);
4452 }
4453 out:
4454 if (crt) {
4455 mbedtls_x509_crt_free(crt);
4456 free(crt);
4457 }
4458 while (san.next) {
4459 mbedtls_x509_sequence *tmp = san.next;
4460 san.next = tmp->next;
4461 mbedtls_free(tmp);
4462 }
4463 #endif
4464 return valid;
4465 }
4466
4467 char *cert_der_base64url(const char *certfile)
4468 {
4469 char *ret = NULL;
4470 void *certdata = NULL;
4471 size_t certsize = 0;
4472 int r;
4473 #if defined(USE_GNUTLS)
4474 gnutls_x509_crt_t crt = NULL;
4475 if (cert_load(&crt, 1, certfile) <= 0) {
4476 warnx("cert_der_base64url: cert_load failed");
4477 goto out;
4478 }
4479
4480 gnutls_datum_t data = {NULL, 0};
4481 r = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &data);
4482 gnutls_x509_crt_deinit(crt);
4483 if (r != GNUTLS_E_SUCCESS) {
4484 warnx("cert_der_base64url: gnutls_x509_crt_export2: %s",
4485 gnutls_strerror(r));
4486 goto out;
4487 }
4488 certsize = data.size;
4489 certdata = gnutls_datum_data(&data, true);
4490 if (!certdata)
4491 goto out;
4492 #elif defined(USE_OPENSSL)
4493 X509 *crt = NULL;
4494 if (cert_load(&crt, 1, certfile) <= 0) {
4495 warnx("cert_der_base64url: cert_load failed");
4496 goto out;
4497 }
4498 r = i2d_X509(crt, NULL);
4499 if (r < 0) {
4500 openssl_error("cert_der_base64url");
4501 X509_free(crt);
4502 goto out;
4503 }
4504 certsize = r;
4505 certdata = calloc(1, certsize);
4506 if (!certdata) {
4507 warn("cert_der_base64url: calloc failed");
4508 X509_free(crt);
4509 goto out;
4510 }
4511 unsigned char *tmp = certdata;
4512 r = i2d_X509(crt, &tmp);
4513 X509_free(crt);
4514 if (r != (int)certsize) {
4515 openssl_error("cert_der_base64url");
4516 goto out;
4517 }
4518 #elif defined(USE_MBEDTLS)
4519 certdata = read_file(certfile, &certsize);
4520 if (!certdata) {
4521 warn("cert_der_base64url: error reading %s", certfile);
4522 goto out;
4523 }
4524 mbedtls_pem_context ctx;
4525 mbedtls_pem_init(&ctx);
4526 size_t len;
4527 r = mbedtls_pem_read_buffer(&ctx, "-----BEGIN CERTIFICATE-----",
4528 "-----END CERTIFICATE-----", certdata, NULL, 0, &len);
4529 if (r) {
4530 warnx("cert_der_base64url: mbedtls_pem_read_buffer failed: %s",
4531 _mbedtls_strerror(r));
4532 mbedtls_pem_free(&ctx);
4533 goto out;
4534 }
4535 free(certdata);
4536 certsize = ctx.buflen;
4537 certdata = calloc(1, certsize);
4538 if (!certdata) {
4539 warn("cert_der_base64url: calloc failed");
4540 mbedtls_pem_free(&ctx);
4541 goto out;
4542 }
4543 memcpy(certdata, ctx.buf, ctx.buflen);
4544 mbedtls_pem_free(&ctx);
4545 #endif
4546 r = base64_ENCODED_LEN(certsize, base64_VARIANT_URLSAFE_NO_PADDING);
4547 if (!(ret = calloc(1, r))) {
4548 warn("cert_der_base64url: calloc failed");
4549 goto out;
4550 }
4551 if (!bin2base64(ret, r, certdata, certsize,
4552 base64_VARIANT_URLSAFE_NO_PADDING)) {
4553 warnx("cert_der_base64url: bin2base64 failed");
4554 free(ret);
4555 ret = NULL;
4556 goto out;
4557 }
4558 out:
4559 free(certdata);
4560 return ret;
4561 }
4562