Apache HTTPD
md_crypt.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <assert.h>
18#include <stdio.h>
19#include <stdlib.h>
20
21#include <apr_lib.h>
22#include <apr_buckets.h>
23#include <apr_file_io.h>
24#include <apr_strings.h>
25#include <httpd.h>
26#include <http_core.h>
27
28#include <openssl/err.h>
29#include <openssl/evp.h>
30#include <openssl/hmac.h>
31#include <openssl/pem.h>
32#include <openssl/rand.h>
33#include <openssl/rsa.h>
34#include <openssl/x509v3.h>
35#if OPENSSL_VERSION_NUMBER >= 0x30000000L
36#include <openssl/core_names.h>
37#endif
38
39#include "md.h"
40#include "md_crypt.h"
41#include "md_json.h"
42#include "md_log.h"
43#include "md_http.h"
44#include "md_time.h"
45#include "md_util.h"
46
47/* getpid for *NIX */
48#if APR_HAVE_SYS_TYPES_H
49#include <sys/types.h>
50#endif
51#if APR_HAVE_UNISTD_H
52#include <unistd.h>
53#endif
54
55/* getpid for Windows */
56#if APR_HAVE_PROCESS_H
57#include <process.h>
58#endif
59
60#if !defined(OPENSSL_NO_CT) \
61 && OPENSSL_VERSION_NUMBER >= 0x10100000L \
62 && (!defined(LIBRESSL_VERSION_NUMBER) \
63 || LIBRESSL_VERSION_NUMBER >= 0x3050000fL)
64/* Missing from LibreSSL < 3.5.0 and only available since OpenSSL v1.1.x */
65#include <openssl/ct.h>
66#endif
67
68static int initialized;
69
74
75#ifdef MD_HAVE_ARC4RANDOM
76
77static void seed_RAND(int pid)
78{
79 char seed[128];
80
81 (void)pid;
82 arc4random_buf(seed, sizeof(seed));
83 RAND_seed(seed, sizeof(seed));
84}
85
86#else /* ifdef MD_HAVE_ARC4RANDOM */
87
88static int rand_choosenum(int l, int h)
89{
90 int i;
91 char buf[50];
92
93 apr_snprintf(buf, sizeof(buf), "%.0f",
94 (((double)(rand()%RAND_MAX)/RAND_MAX)*(h-l)));
95 i = atoi(buf)+1;
96 if (i < l) i = l;
97 if (i > h) i = h;
98 return i;
99}
100
101static void seed_RAND(int pid)
102{
103 unsigned char stackdata[256];
104 /* stolen from mod_ssl/ssl_engine_rand.c */
105 int n;
106 struct {
107 time_t t;
108 pid_t pid;
109 } my_seed;
110
111 /*
112 * seed in the current time (usually just 4 bytes)
113 */
114 my_seed.t = time(NULL);
115
116 /*
117 * seed in the current process id (usually just 4 bytes)
118 */
119 my_seed.pid = pid;
120
121 RAND_seed((unsigned char *)&my_seed, sizeof(my_seed));
122
123 /*
124 * seed in some current state of the run-time stack (128 bytes)
125 */
126 n = rand_choosenum(0, sizeof(stackdata)-128-1);
127 RAND_seed(stackdata+n, 128);
128}
129
130#endif /*ifdef MD_HAVE_ARC4RANDOM (else part) */
131
132
134{
135 (void)pool;
136
137 if (!initialized) {
138 int pid = getpid();
139
142
143 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, 0, pool, "initializing RAND");
144 while (!RAND_status()) {
145 seed_RAND(pid);
146 }
147
148 initialized = 1;
149 }
150 return APR_SUCCESS;
151}
152
154{
157
158 (void)p;
159 return apr_file_write_full(f, buf->data, buf->len, &wlen);
160}
161
163{
164 apr_status_t rv;
165
166 if (len > INT_MAX) {
167 return APR_ENOTIMPL;
168 }
169 if (APR_SUCCESS == (rv = md_crypt_init(p))) {
170 RAND_bytes((unsigned char*)buf, (int)len);
171 }
172 return rv;
173}
174
175typedef struct {
176 const char *pass_phrase;
178} passwd_ctx;
179
180static int pem_passwd(char *buf, int size, int rwflag, void *baton)
181{
183
184 (void)rwflag;
185 if (ctx->pass_len > 0) {
186 if (ctx->pass_len < size) {
187 size = (int)ctx->pass_len;
188 }
189 memcpy(buf, ctx->pass_phrase, (size_t)size);
190 } else {
191 return 0;
192 }
193 return size;
194}
195
196/**************************************************************************************************/
197/* date time things */
198
199/* Get the apr time (micro seconds, since 1970) from an ASN1 time, as stored in X509
200 * certificates. OpenSSL now has a utility function, but other *SSL derivatives have
201 * not caughts up yet or chose to ignore. An alternative is implemented, we prefer
202 * however the *SSL to maintain such things.
203 */
205{
206#if OPENSSL_VERSION_NUMBER < 0x10002000L || (defined(LIBRESSL_VERSION_NUMBER) && \
207 LIBRESSL_VERSION_NUMBER < 0x3060000fL)
208 /* courtesy: https://stackoverflow.com/questions/10975542/asn1-time-to-time-t-conversion#11263731
209 * all bugs are mine */
211 apr_time_t ts;
212 const char* str = (const char*) time->data;
213 apr_size_t i = 0;
214
215 memset(&t, 0, sizeof(t));
216
217 if (time->type == V_ASN1_UTCTIME) {/* two digit year */
218 t.tm_year = (str[i++] - '0') * 10;
219 t.tm_year += (str[i++] - '0');
220 if (t.tm_year < 70)
221 t.tm_year += 100;
222 }
223 else if (time->type == V_ASN1_GENERALIZEDTIME) {/* four digit year */
224 t.tm_year = (str[i++] - '0') * 1000;
225 t.tm_year+= (str[i++] - '0') * 100;
226 t.tm_year+= (str[i++] - '0') * 10;
227 t.tm_year+= (str[i++] - '0');
228 t.tm_year -= 1900;
229 }
230 t.tm_mon = (str[i++] - '0') * 10;
231 t.tm_mon += (str[i++] - '0') - 1; /* -1 since January is 0 not 1. */
232 t.tm_mday = (str[i++] - '0') * 10;
233 t.tm_mday+= (str[i++] - '0');
234 t.tm_hour = (str[i++] - '0') * 10;
235 t.tm_hour+= (str[i++] - '0');
236 t.tm_min = (str[i++] - '0') * 10;
237 t.tm_min += (str[i++] - '0');
238 t.tm_sec = (str[i++] - '0') * 10;
239 t.tm_sec += (str[i++] - '0');
240
241 if (APR_SUCCESS == apr_time_exp_gmt_get(&ts, &t)) {
242 return ts;
243 }
244 return 0;
245#else
246 int secs, days;
248
249 if (ASN1_TIME_diff(&days, &secs, NULL, time)) {
251 }
252 return ts;
253#endif
254}
255
260
261/**************************************************************************************************/
262/* OID/NID things */
263
264static int get_nid(const char *num, const char *sname, const char *lname)
265{
266 /* Funny API, an OID for a feature might be configured or
267 * maybe not. In the second case, we need to add it. But adding
268 * when it already is there is an error... */
269 int nid = OBJ_txt2nid(num);
270 if (NID_undef == nid) {
271 nid = OBJ_create(num, sname, lname);
272 }
273 return nid;
274}
275
276#define MD_GET_NID(x) get_nid(MD_OID_##x##_NUM, MD_OID_##x##_SNAME, MD_OID_##x##_LNAME)
277
278/**************************************************************************************************/
279/* private keys */
280
282{
283 md_pkeys_spec_t *pks;
284
285 pks = apr_pcalloc(p, sizeof(*pks));
286 pks->p = p;
287 pks->specs = apr_array_make(p, 2, sizeof(md_pkey_spec_t*));
288 return pks;
289}
290
295
297{
298 md_pkey_spec_t *spec;
299
300 spec = apr_pcalloc(pks->p, sizeof(*spec));
302 md_pkeys_spec_add(pks, spec);
303}
304
306{
307 md_pkey_spec_t *spec;
308 int i;
309 for (i = 0; i < pks->specs->nelts; ++i) {
310 spec = APR_ARRAY_IDX(pks->specs, i, md_pkey_spec_t*);
311 if (MD_PKEY_TYPE_RSA == spec->type) return 1;
312 }
313 return 0;
314}
315
316void md_pkeys_spec_add_rsa(md_pkeys_spec_t *pks, unsigned int bits)
317{
318 md_pkey_spec_t *spec;
319
320 spec = apr_pcalloc(pks->p, sizeof(*spec));
321 spec->type = MD_PKEY_TYPE_RSA;
322 spec->params.rsa.bits = bits;
323 md_pkeys_spec_add(pks, spec);
324}
325
326int md_pkeys_spec_contains_ec(md_pkeys_spec_t *pks, const char *curve)
327{
328 md_pkey_spec_t *spec;
329 int i;
330 for (i = 0; i < pks->specs->nelts; ++i) {
331 spec = APR_ARRAY_IDX(pks->specs, i, md_pkey_spec_t*);
332 if (MD_PKEY_TYPE_EC == spec->type
333 && !apr_strnatcasecmp(curve, spec->params.ec.curve)) return 1;
334 }
335 return 0;
336}
337
338void md_pkeys_spec_add_ec(md_pkeys_spec_t *pks, const char *curve)
339{
340 md_pkey_spec_t *spec;
341
342 spec = apr_pcalloc(pks->p, sizeof(*spec));
343 spec->type = MD_PKEY_TYPE_EC;
344 spec->params.ec.curve = apr_pstrdup(pks->p, curve);
345 md_pkeys_spec_add(pks, spec);
346}
347
349{
350 md_json_t *json = md_json_create(p);
351 if (json) {
352 switch (spec->type) {
354 md_json_sets("Default", json, MD_KEY_TYPE, NULL);
355 break;
356 case MD_PKEY_TYPE_RSA:
357 md_json_sets("RSA", json, MD_KEY_TYPE, NULL);
358 if (spec->params.rsa.bits >= MD_PKEY_RSA_BITS_MIN) {
359 md_json_setl((long)spec->params.rsa.bits, json, MD_KEY_BITS, NULL);
360 }
361 break;
362 case MD_PKEY_TYPE_EC:
363 md_json_sets("EC", json, MD_KEY_TYPE, NULL);
364 if (spec->params.ec.curve) {
366 }
367 break;
368 default:
369 md_json_sets("Unsupported", json, MD_KEY_TYPE, NULL);
370 break;
371 }
372 }
373 return json;
374}
375
377{
379
380 (void)baton;
382 return md_json_setj(jspec, json, NULL);
383}
384
386{
387 md_json_t *j;
388
389 if (pks->specs->nelts == 1) {
391 }
392 j = md_json_create(p);
393 md_json_seta(pks->specs, spec_to_json, (void*)pks, j, "specs", NULL);
394 return md_json_getj(j, "specs", NULL);
395}
396
398{
399 md_pkey_spec_t *spec = apr_pcalloc(p, sizeof(*spec));
400 const char *s;
401 long l;
402
403 if (spec) {
404 s = md_json_gets(json, MD_KEY_TYPE, NULL);
405 if (!s || !apr_strnatcasecmp("Default", s)) {
407 }
408 else if (!apr_strnatcasecmp("RSA", s)) {
409 spec->type = MD_PKEY_TYPE_RSA;
410 l = md_json_getl(json, MD_KEY_BITS, NULL);
411 if (l >= MD_PKEY_RSA_BITS_MIN) {
412 spec->params.rsa.bits = (unsigned int)l;
413 }
414 else {
416 }
417 }
418 else if (!apr_strnatcasecmp("EC", s)) {
419 spec->type = MD_PKEY_TYPE_EC;
421 if (s) {
422 spec->params.ec.curve = apr_pstrdup(p, s);
423 }
424 else {
425 spec->params.ec.curve = NULL;
426 }
427 }
428 }
429 return spec;
430}
431
433{
434 (void)baton;
436 return APR_SUCCESS;
437}
438
440{
441 md_pkeys_spec_t *pks;
442 md_pkey_spec_t *spec;
443
444 pks = md_pkeys_spec_make(p);
445 if (md_json_is(MD_JSON_TYPE_ARRAY, json, NULL)) {
446 md_json_geta(pks->specs, spec_from_json, pks, json, NULL);
447 }
448 else {
449 spec = md_pkey_spec_from_json(json, p);
450 md_pkeys_spec_add(pks, spec);
451 }
452 return pks;
453}
454
456{
457 if (s1 == s2) {
458 return 1;
459 }
460 if (s1 && s2 && s1->type == s2->type) {
461 switch (s1->type) {
463 return 1;
464 case MD_PKEY_TYPE_RSA:
465 if (s1->params.rsa.bits == s2->params.rsa.bits) {
466 return 1;
467 }
468 break;
469 case MD_PKEY_TYPE_EC:
470 if (s1->params.ec.curve == s2->params.ec.curve) {
471 return 1;
472 }
473 else if (!s1->params.ec.curve || !s2->params.ec.curve) {
474 return 0;
475 }
476 return !strcmp(s1->params.ec.curve, s2->params.ec.curve);
477 }
478 }
479 return 0;
480}
481
483{
484 int i;
485
486 if (pks1 == pks2) {
487 return 1;
488 }
489 if (pks1 && pks2 && pks1->specs->nelts == pks2->specs->nelts) {
490 for(i = 0; i < pks1->specs->nelts; ++i) {
492 APR_ARRAY_IDX(pks2->specs, i, md_pkey_spec_t *))) {
493 return 0;
494 }
495 }
496 return 1;
497 }
498 return 0;
499}
500
502{
504
505 nspec = apr_pcalloc(p, sizeof(*nspec));
506 nspec->type = spec->type;
507 switch (spec->type) {
509 break;
510 case MD_PKEY_TYPE_RSA:
511 nspec->params.rsa.bits = spec->params.rsa.bits;
512 break;
513 case MD_PKEY_TYPE_EC:
514 nspec->params.ec.curve = apr_pstrdup(p, spec->params.ec.curve);
515 break;
516 }
517 return nspec;
518}
519
520const char *md_pkey_spec_name(const md_pkey_spec_t *spec)
521{
522 if (!spec) return "rsa";
523 switch (spec->type) {
525 case MD_PKEY_TYPE_RSA:
526 return "rsa";
527 case MD_PKEY_TYPE_EC:
528 return spec->params.ec.curve;
529 }
530 return "unknown";
531}
532
534{
535 return NULL == pks || 0 == pks->specs->nelts;
536}
537
539{
541 md_pkey_spec_t *spec;
542 int i;
543
544 if (pks && pks->specs->nelts > 0) {
545 npks = apr_pcalloc(p, sizeof(*npks));
546 npks->specs = apr_array_make(p, pks->specs->nelts, sizeof(md_pkey_spec_t*));
547 for (i = 0; i < pks->specs->nelts; ++i) {
548 spec = APR_ARRAY_IDX(pks->specs, i, md_pkey_spec_t*);
550 }
551 }
552 return npks;
553}
554
556{
557 return md_pkeys_spec_is_empty(pks)? 1 : pks->specs->nelts;
558}
559
561
563{
564 if (md_pkeys_spec_is_empty(pks)) {
565 return index == 1? &PkeySpecDef : NULL;
566 }
567 else if (pks && index >= 0 && index < pks->specs->nelts) {
568 return APR_ARRAY_IDX(pks->specs, index, md_pkey_spec_t*);
569 }
570 return NULL;
571}
572
574{
575 md_pkey_t *pkey = apr_pcalloc(p, sizeof(*pkey));
576 pkey->pool = p;
577 return pkey;
578}
579
581{
583 if (pkey->pkey) {
584 EVP_PKEY_free(pkey->pkey);
585 pkey->pkey = NULL;
586 }
587 return APR_SUCCESS;
588}
589
594
596{
597 return pkey->pkey;
598}
599
601 const char *key, apr_size_t key_len,
602 const char *fname)
603{
606 BIO *bf;
608
609 pkey = make_pkey(p);
610 if (NULL != (bf = BIO_new_file(fname, "r"))) {
611 ctx.pass_phrase = key;
612 ctx.pass_len = (int)key_len;
613
616 BIO_free(bf);
617
618 if (pkey->pkey != NULL) {
619 rv = APR_SUCCESS;
621 }
622 else {
623 unsigned long err = ERR_get_error();
624 rv = APR_EINVAL;
626 "error loading pkey %s: %s (pass phrase was %snull)", fname,
627 ERR_error_string(err, NULL), key? "not " : "");
628 }
629 }
630 *ppkey = (APR_SUCCESS == rv)? pkey : NULL;
631 return rv;
632}
633
635 const char *pass, apr_size_t pass_len)
636{
637 BIO *bio = BIO_new(BIO_s_mem());
638 const EVP_CIPHER *cipher = NULL;
639 pem_password_cb *cb = NULL;
640 void *cb_baton = NULL;
643 unsigned long err;
644 int i;
645
646 if (!bio) {
647 return APR_ENOMEM;
648 }
649 if (pass_len > INT_MAX) {
650 rv = APR_EINVAL;
651 goto cleanup;
652 }
653 if (pass && pass_len > 0) {
655 ctx.pass_len = (int)pass_len;
656 cb = pem_passwd;
657 cb_baton = &ctx;
659 if (!cipher) {
660 rv = APR_ENOTIMPL;
661 goto cleanup;
662 }
663 }
664
666#if 1
667 if (!PEM_write_bio_PKCS8PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_baton)) {
668#else
669 if (!PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_baton)) {
670#endif
671 err = ERR_get_error();
672 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "PEM_write key: %ld %s",
674 rv = APR_EINVAL;
675 goto cleanup;
676 }
677
679 i = BIO_pending(bio);
680 if (i > 0) {
681 buf->data = apr_palloc(p, (apr_size_t)i);
682 i = BIO_read(bio, (char*)buf->data, i);
683 buf->len = (apr_size_t)i;
684 }
685
686cleanup:
687 BIO_free(bio);
688 return rv;
689}
690
692 const char *pass_phrase, apr_size_t pass_len,
693 const char *fname, apr_fileperms_t perms)
694{
696 apr_status_t rv;
697
698 if (APR_SUCCESS == (rv = pkey_to_buffer(&buffer, pkey, p, pass_phrase, pass_len))) {
700 }
701 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "save pkey %s (%s pass phrase, len=%d)",
702 fname, pass_len > 0? "with" : "without", (int)pass_len);
703 return rv;
704}
705
707 const struct md_http_response_t *res)
708{
709 apr_status_t rv;
711 char *pem_data;
714 BIO *bf;
716
717 rv = apr_brigade_length(res->body, 1, &data_len);
718 if (APR_SUCCESS != rv) goto leave;
719 if (data_len > 1024*1024) { /* certs usually are <2k each */
720 rv = APR_EINVAL;
721 goto leave;
722 }
723 rv = apr_brigade_pflatten(res->body, &pem_data, &pem_len, res->req->pool);
724 if (APR_SUCCESS != rv) goto leave;
725
726 if (NULL == (bf = BIO_new_mem_buf(pem_data, (int)pem_len))) {
727 rv = APR_ENOMEM;
728 goto leave;
729 }
731 ctx.pass_phrase = NULL;
732 ctx.pass_len = 0;
735 BIO_free(bf);
736
737 if (pkey->pkey == NULL) {
738 unsigned long err = ERR_get_error();
739 rv = APR_EINVAL;
741 "error loading pkey from http response: %s",
743 goto leave;
744 }
745 rv = APR_SUCCESS;
747
748leave:
749 *ppkey = (APR_SUCCESS == rv)? pkey : NULL;
750 return rv;
751}
752
753/* Determine the message digest used for signing with the given private key.
754 */
756{
757 switch (EVP_PKEY_id(pkey->pkey)) {
758#ifdef NID_ED25519
759 case NID_ED25519:
760 return NULL;
761#endif
762#ifdef NID_ED448
763 case NID_ED448:
764 return NULL;
765#endif
766 default:
767 return EVP_sha256();
768 }
769}
770
771static apr_status_t gen_rsa(md_pkey_t **ppkey, apr_pool_t *p, unsigned int bits)
772{
774 apr_status_t rv;
775
776 *ppkey = make_pkey(p);
778 if (ctx
780 && EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, (int)bits) >= 0
781 && EVP_PKEY_keygen(ctx, &(*ppkey)->pkey) >= 0) {
782 rv = APR_SUCCESS;
783 }
784 else {
785 md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, p, "error generate pkey RSA %d", bits);
786 *ppkey = NULL;
787 rv = APR_EGENERAL;
788 }
789
790 if (ctx != NULL) {
792 }
793 return rv;
794}
795
798 size_t nc, i;
799 int rv = APR_ENOENT;
800
802 if (NULL == (curves = OPENSSL_malloc(sizeof(*curves) * nc)) ||
804 rv = APR_EGENERAL;
806 "error looking up OpenSSL builtin EC curves");
807 goto leave;
808 }
809 for (i = 0; i < nc; ++i) {
810 if (nid == curves[i].nid) {
811 rv = APR_SUCCESS;
812 break;
813 }
814 }
815leave:
817 return rv;
818}
819
820static apr_status_t gen_ec(md_pkey_t **ppkey, apr_pool_t *p, const char *curve)
821{
823 apr_status_t rv;
824 int curve_nid = NID_undef;
825
826 /* 1. Convert the cure into its registered identifier. Curves can be known under
827 * different names.
828 * 2. Determine, if the curve is supported by OpenSSL (or whatever is linked).
829 * 3. Generate the key, respecting the specific quirks some curves require.
830 */
832 /* In case this fails, try some names from other standards, like SECG */
833#ifdef NID_secp384r1
834 if (NID_undef == curve_nid && !apr_strnatcasecmp("secp384r1", curve)) {
837 }
838#endif
839#ifdef NID_X9_62_prime256v1
840 if (NID_undef == curve_nid && !apr_strnatcasecmp("secp256r1", curve)) {
843 }
844#endif
845#ifdef NID_X9_62_prime192v1
846 if (NID_undef == curve_nid && !apr_strnatcasecmp("secp192r1", curve)) {
849 }
850#endif
851#if defined(NID_X25519) && (!defined(LIBRESSL_VERSION_NUMBER) || \
852 LIBRESSL_VERSION_NUMBER >= 0x3070000fL)
853 if (NID_undef == curve_nid && !apr_strnatcasecmp("X25519", curve)) {
856 }
857#endif
858 if (NID_undef == curve_nid) {
859 /* OpenSSL object/curve names */
860 curve_nid = OBJ_sn2nid(curve);
861 }
862 if (NID_undef == curve_nid) {
863 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "ec curve unknown: %s", curve);
864 rv = APR_ENOTIMPL; goto leave;
865 }
866
867 *ppkey = make_pkey(p);
868 switch (curve_nid) {
869
870#if defined(NID_X25519) && (!defined(LIBRESSL_VERSION_NUMBER) || \
871 LIBRESSL_VERSION_NUMBER >= 0x3070000fL)
872 case NID_X25519:
873 /* no parameters */
876 || EVP_PKEY_keygen(ctx, &(*ppkey)->pkey) <= 0) {
878 "error generate EC key for group: %s", curve);
879 rv = APR_EGENERAL; goto leave;
880 }
881 rv = APR_SUCCESS;
882 break;
883#endif
884
885#if defined(NID_X448) && !defined(LIBRESSL_VERSION_NUMBER)
886 case NID_X448:
887 /* no parameters */
890 || EVP_PKEY_keygen(ctx, &(*ppkey)->pkey) <= 0) {
892 "error generate EC key for group: %s", curve);
893 rv = APR_EGENERAL; goto leave;
894 }
895 rv = APR_SUCCESS;
896 break;
897#endif
898
899 default:
900#if OPENSSL_VERSION_NUMBER < 0x30000000L
901 if (APR_SUCCESS != (rv = check_EC_curve(curve_nid, p))) goto leave;
907 || EVP_PKEY_keygen(ctx, &(*ppkey)->pkey) <= 0) {
909 "error generate EC key for group: %s", curve);
910 rv = APR_EGENERAL; goto leave;
911 }
912#else
913 if (APR_SUCCESS != (rv = check_EC_curve(curve_nid, p))) goto leave;
916 || EVP_PKEY_CTX_ctrl_str(ctx, "ec_paramgen_curve", curve) <= 0
917 || EVP_PKEY_keygen(ctx, &(*ppkey)->pkey) <= 0) {
919 "error generate EC key for group: %s", curve);
920 rv = APR_EGENERAL; goto leave;
921 }
922#endif
923 rv = APR_SUCCESS;
924 break;
925 }
926
927leave:
928 if (APR_SUCCESS != rv) *ppkey = NULL;
930 return rv;
931}
932
934{
935 md_pkey_type_t ptype = spec? spec->type : MD_PKEY_TYPE_DEFAULT;
936 switch (ptype) {
939 case MD_PKEY_TYPE_RSA:
940 return gen_rsa(ppkey, p, spec->params.rsa.bits);
941 case MD_PKEY_TYPE_EC:
942 return gen_ec(ppkey, p, spec->params.ec.curve);
943 default:
944 return APR_ENOTIMPL;
945 }
946}
947
948#if OPENSSL_VERSION_NUMBER < 0x10100000L \
949 || (defined(LIBRESSL_VERSION_NUMBER) \
950 && LIBRESSL_VERSION_NUMBER < 0x2070000f)
951
952static void RSA_get0_key(const RSA *r,
953 const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
954{
955 if (n != NULL)
956 *n = r->n;
957 if (e != NULL)
958 *e = r->e;
959 if (d != NULL)
960 *d = r->d;
961}
962
963#endif
964
965static const char *bn64(const BIGNUM *b, apr_pool_t *p)
966{
967 if (b) {
969
971 if (buffer.data) {
972 BN_bn2bin(b, (unsigned char *)buffer.data);
974 }
975 }
976 return NULL;
977}
978
980{
981#if OPENSSL_VERSION_NUMBER < 0x30000000L
982 const RSA *rsa = EVP_PKEY_get0_RSA(pkey->pkey);
983 if (rsa) {
984 const BIGNUM *e;
985 RSA_get0_key(rsa, NULL, &e, NULL);
986 return bn64(e, p);
987 }
988#else
989 BIGNUM *e = NULL;
991 const char *e64 = bn64(e, p);
992 BN_free(e);
993 return e64;
994 }
995#endif
996 return NULL;
997}
998
1000{
1001#if OPENSSL_VERSION_NUMBER < 0x30000000L
1002 const RSA *rsa = EVP_PKEY_get0_RSA(pkey->pkey);
1003 if (rsa) {
1004 const BIGNUM *n;
1005 RSA_get0_key(rsa, &n, NULL, NULL);
1006 return bn64(n, p);
1007 }
1008#else
1009 BIGNUM *n = NULL;
1011 const char *n64 = bn64(n, p);
1012 BN_free(n);
1013 return n64;
1014 }
1015#endif
1016 return NULL;
1017}
1018
1020 const char *d, size_t dlen)
1021{
1022 EVP_MD_CTX *ctx = NULL;
1024 unsigned int blen;
1025 const char *sign64 = NULL;
1027
1029 if (buffer.data) {
1031 if (ctx) {
1032 rv = APR_ENOTIMPL;
1034 rv = APR_EGENERAL;
1035 if (EVP_SignUpdate(ctx, d, dlen)) {
1036 if (EVP_SignFinal(ctx, (unsigned char*)buffer.data, &blen, pkey->pkey)) {
1037 buffer.len = blen;
1039 if (sign64) {
1040 rv = APR_SUCCESS;
1041 }
1042 }
1043 }
1044 }
1045 }
1046
1047 if (ctx) {
1049 }
1050 }
1051
1052 if (rv != APR_SUCCESS) {
1053 md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, "signing");
1054 }
1055
1056 *psign64 = sign64;
1057 return rv;
1058}
1059
1061{
1062 EVP_MD_CTX *ctx = NULL;
1065 unsigned int dlen;
1066
1069 if (ctx) {
1070 rv = APR_ENOTIMPL;
1072 rv = APR_EGENERAL;
1073 if (EVP_DigestUpdate(ctx, (unsigned char*)buf->data, buf->len)) {
1074 if (EVP_DigestFinal(ctx, (unsigned char*)digest->data, &dlen)) {
1075 digest->len = dlen;
1076 rv = APR_SUCCESS;
1077 }
1078 }
1079 }
1080 }
1081 if (ctx) {
1083 }
1084 *pdigest = (APR_SUCCESS == rv)? digest : NULL;
1085 return rv;
1086}
1087
1089{
1090 const char *digest64 = NULL;
1092 apr_status_t rv;
1093
1094 if (APR_SUCCESS == (rv = sha256_digest(&digest, p, d))) {
1096 rv = APR_EGENERAL;
1097 }
1098 }
1100 return rv;
1101}
1102
1104 const md_data_t *data)
1105{
1107 apr_status_t rv;
1108
1109 if (APR_SUCCESS == (rv = sha256_digest(&digest, p, data))) {
1110 return md_data_to_hex(pdigesthex, 0, p, digest);
1111 }
1112 *pdigesthex = NULL;
1113 return rv;
1114}
1115
1117 apr_pool_t *p, const char *d, size_t dlen)
1118{
1119 const char *mac64 = NULL;
1120 unsigned char *s;
1121 unsigned int digest_len = 0;
1124
1126 s = HMAC(EVP_sha256(), (const unsigned char*)hmac_key->data, (int)hmac_key->len,
1127 (const unsigned char*)d, (size_t)dlen,
1128 (unsigned char*)digest->data, &digest_len);
1129 if (!s) {
1130 rv = APR_EINVAL;
1131 goto cleanup;
1132 }
1133 digest->len = digest_len;
1135
1136cleanup:
1137 *pmac64 = (APR_SUCCESS == rv)? mac64 : NULL;
1138 return rv;
1139}
1140
1141/**************************************************************************************************/
1142/* certificates */
1143
1149
1151{
1152 md_cert_t *cert = data;
1153 if (cert->x509) {
1154 X509_free(cert->x509);
1155 cert->x509 = NULL;
1156 }
1157 return APR_SUCCESS;
1158}
1159
1161{
1162 md_cert_t *cert = apr_pcalloc(p, sizeof(*cert));
1163 cert->pool = p;
1164 cert->x509 = x509;
1165 return cert;
1166}
1167
1174
1176{
1177 return cert->x509;
1178}
1179
1181{
1182 const char *s = "";
1183 BIGNUM *bn;
1184 const char *serial;
1185 const ASN1_INTEGER *ai = X509_get_serialNumber(cert->x509);
1186 if (ai) {
1188 serial = BN_bn2hex(bn);
1189 s = apr_pstrdup(p, serial);
1190 OPENSSL_free((void*)serial);
1191 OPENSSL_free((void*)bn);
1192 }
1193 return s;
1194}
1195
1197{
1198 return X509_cmp(a->x509, b->x509) == 0;
1199}
1200
1202{
1203 return ((X509_cmp_current_time(X509_get_notBefore(cert->x509)) < 0)
1205}
1206
1208{
1209 return (X509_cmp_current_time(X509_get_notAfter(cert->x509)) <= 0);
1210}
1211
1216
1221
1223{
1225 p.start = md_cert_get_not_before(cert);
1227 return p;
1228}
1229
1231{
1233
1235 if (alt_names) {
1236 return md_array_str_index(alt_names, domain_name, 0, 0) >= 0;
1237 }
1238 return 0;
1239}
1240
1242{
1243 const char *name;
1244 int i;
1245
1246 if (!cert->alt_names) {
1247 md_cert_get_alt_names(&cert->alt_names, cert, cert->pool);
1248 }
1249 if (cert->alt_names) {
1250 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, cert->pool, "cert has %d alt names",
1251 cert->alt_names->nelts);
1252 for (i = 0; i < md->domains->nelts; ++i) {
1253 name = APR_ARRAY_IDX(md->domains, i, const char *);
1254 if (!md_dns_domains_match(cert->alt_names, name)) {
1256 "md domain %s not covered by cert", name);
1257 return 0;
1258 }
1259 }
1260 return 1;
1261 }
1262 else {
1263 md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, cert->pool, "cert has NO alt names");
1264 }
1265 return 0;
1266}
1267
1269{
1272 const char *uri = NULL;
1273 unsigned char *buf;
1274 int i;
1275
1277 if (xinfos) {
1278 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(xinfos); i++) {
1280 if (OBJ_obj2nid(val->method) == NID_ad_ca_issuers
1281 && val->location && val->location->type == GEN_URI) {
1282 ASN1_STRING_to_UTF8(&buf, val->location->d.uniformResourceIdentifier);
1283 uri = apr_pstrdup(p, (char *)buf);
1285 rv = APR_SUCCESS;
1286 break;
1287 }
1288 }
1290 }
1291 *puri = (APR_SUCCESS == rv)? uri : NULL;
1292 return rv;
1293}
1294
1296{
1300 unsigned char *buf;
1301 int i;
1302
1304 if (xalt_names) {
1306 const unsigned char *ip;
1307 int len;
1308
1310 for (i = 0; i < sk_GENERAL_NAME_num(xalt_names); ++i) {
1312 switch (cval->type) {
1313 case GEN_DNS:
1314 case GEN_URI:
1315 ASN1_STRING_to_UTF8(&buf, cval->d.ia5);
1316 APR_ARRAY_PUSH(names, const char *) = apr_pstrdup(p, (char*)buf);
1318 break;
1319 case GEN_IPADD:
1320 len = ASN1_STRING_length(cval->d.iPAddress);
1321#if OPENSSL_VERSION_NUMBER < 0x10100000L
1322 ip = ASN1_STRING_data(cval->d.iPAddress);
1323#else
1324 ip = ASN1_STRING_get0_data(cval->d.iPAddress);
1325#endif
1326 if (len == 4) /* IPv4 address */
1327 APR_ARRAY_PUSH(names, const char *) = apr_psprintf(p, "%u.%u.%u.%u",
1328 ip[0], ip[1], ip[2], ip[3]);
1329 else if (len == 16) /* IPv6 address */
1330 APR_ARRAY_PUSH(names, const char *) = apr_psprintf(p, "%02x%02x%02x%02x:"
1331 "%02x%02x%02x%02x:"
1332 "%02x%02x%02x%02x:"
1333 "%02x%02x%02x%02x",
1334 ip[0], ip[1], ip[2], ip[3],
1335 ip[4], ip[5], ip[6], ip[7],
1336 ip[8], ip[9], ip[10], ip[11],
1337 ip[12], ip[13], ip[14], ip[15]);
1338 else {
1339 ; /* Unknown address type - Log? Assert? */
1340 }
1341 break;
1342 default:
1343 break;
1344 }
1345 }
1347 rv = APR_SUCCESS;
1348 }
1349 *pnames = (APR_SUCCESS == rv)? names : NULL;
1350 return rv;
1351}
1352
1354{
1355 FILE *f;
1356 apr_status_t rv;
1357 md_cert_t *cert;
1358 X509 *x509;
1359
1360 rv = md_util_fopen(&f, fname, "r");
1361 if (rv == APR_SUCCESS) {
1362
1363 x509 = PEM_read_X509(f, NULL, NULL, NULL);
1364 rv = fclose(f);
1365 if (x509 != NULL) {
1366 cert = md_cert_make(p, x509);
1367 }
1368 else {
1369 rv = APR_EINVAL;
1370 }
1371 }
1372
1373 *pcert = (APR_SUCCESS == rv)? cert : NULL;
1374 return rv;
1375}
1376
1378{
1379 BIO *bio = BIO_new(BIO_s_mem());
1380 int i;
1381
1382 if (!bio) {
1383 return APR_ENOMEM;
1384 }
1385
1387 PEM_write_bio_X509(bio, cert->x509);
1388 if (ERR_get_error() > 0) {
1389 BIO_free(bio);
1390 return APR_EINVAL;
1391 }
1392
1393 i = BIO_pending(bio);
1394 if (i > 0) {
1395 buffer->data = apr_palloc(p, (apr_size_t)i);
1396 i = BIO_read(bio, (char*)buffer->data, i);
1397 buffer->len = (apr_size_t)i;
1398 }
1399 BIO_free(bio);
1400 return APR_SUCCESS;
1401}
1402
1404 const char *fname, apr_fileperms_t perms)
1405{
1407 apr_status_t rv;
1408
1410 if (APR_SUCCESS == (rv = cert_to_buffer(&buffer, cert, p))) {
1412 }
1413 return rv;
1414}
1415
1417{
1419 apr_status_t rv;
1420
1422 if (APR_SUCCESS == (rv = cert_to_buffer(&buffer, cert, p))) {
1424 return APR_SUCCESS;
1425 }
1426 *ps64 = NULL;
1427 return rv;
1428}
1429
1431{
1433 unsigned int dlen;
1434
1436 X509_digest(cert->x509, EVP_sha256(), (unsigned char*)digest->data, &dlen);
1437 digest->len = dlen;
1438
1439 *pdigest = digest;
1440 return APR_SUCCESS;
1441}
1442
1444{
1446 apr_status_t rv;
1447
1449 if (APR_SUCCESS == rv) {
1450 return md_data_to_hex(pfinger, 0, p, digest);
1451 }
1452 *pfinger = NULL;
1453 return rv;
1454}
1455
1457{
1458 md_cert_t *cert;
1459 X509 *x509;
1461
1463 x509 = PEM_read_bio_X509(bf, NULL, NULL, NULL);
1464 if (x509 == NULL) goto cleanup;
1465 cert = md_cert_make(p, x509);
1466 rv = APR_SUCCESS;
1467cleanup:
1468 *pcert = (APR_SUCCESS == rv)? cert : NULL;
1469 return rv;
1470}
1471
1473 const char *pem, apr_size_t pem_len)
1474{
1475 BIO *bf = NULL;
1477 md_cert_t *cert;
1478 int added = 0;
1479
1480 if (NULL == (bf = BIO_new_mem_buf(pem, (int)pem_len))) {
1481 rv = APR_ENOMEM;
1482 goto cleanup;
1483 }
1484 while (APR_SUCCESS == (rv = md_cert_read_pem(bf, chain->pool, &cert))) {
1485 APR_ARRAY_PUSH(chain, md_cert_t *) = cert;
1486 added = 1;
1487 }
1488 if (APR_ENOENT == rv && added) {
1489 rv = APR_SUCCESS;
1490 }
1491
1492cleanup:
1493 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, rv, p, "read chain with %d certs", chain->nelts);
1494 if (bf) BIO_free(bf);
1495 return rv;
1496}
1497
1499 const md_http_response_t *res)
1500{
1501 const char *ct;
1503 char *der;
1504 apr_size_t der_len;
1505 md_cert_t *cert = NULL;
1506 apr_status_t rv;
1507
1508 ct = apr_table_get(res->headers, "Content-Type");
1509 ct = md_util_parse_ct(res->req->pool, ct);
1510 if (!res->body || !ct || strcmp("application/pkix-cert", ct)) {
1511 rv = APR_ENOENT;
1512 goto out;
1513 }
1514
1515 if (APR_SUCCESS == (rv = apr_brigade_length(res->body, 1, &data_len))) {
1516 if (data_len > 1024*1024) { /* certs usually are <2k each */
1517 return APR_EINVAL;
1518 }
1519 if (APR_SUCCESS == (rv = apr_brigade_pflatten(res->body, &der, &der_len, res->req->pool))) {
1520 const unsigned char *bf = (const unsigned char*)der;
1521 X509 *x509;
1522
1523 if (NULL == (x509 = d2i_X509(NULL, &bf, (long)der_len))) {
1524 rv = APR_EINVAL;
1525 goto out;
1526 }
1527 else {
1528 cert = md_cert_make(p, x509);
1529 rv = APR_SUCCESS;
1531 "parsing cert from content-type=%s, content-length=%ld", ct, (long)data_len);
1532 }
1533 }
1534 }
1535out:
1536 *pcert = (APR_SUCCESS == rv)? cert : NULL;
1537 return rv;
1538}
1539
1541 apr_pool_t *p, const struct md_http_response_t *res)
1542{
1543 const char *ct = NULL;
1544 apr_off_t blen;
1545 apr_size_t data_len = 0;
1546 char *data;
1547 md_cert_t *cert;
1549
1551 "chain_read, processing %d response", res->status);
1552 if (APR_SUCCESS != (rv = apr_brigade_length(res->body, 1, &blen))) goto cleanup;
1553 if (blen > 1024*1024) { /* certs usually are <2k each */
1554 rv = APR_EINVAL;
1555 goto cleanup;
1556 }
1557
1558 data_len = (apr_size_t)blen;
1559 ct = apr_table_get(res->headers, "Content-Type");
1560 if (!res->body || !ct) goto cleanup;
1561 ct = md_util_parse_ct(res->req->pool, ct);
1562 if (!strcmp("application/pkix-cert", ct)) {
1563 rv = md_cert_read_http(&cert, p, res);
1564 if (APR_SUCCESS != rv) goto cleanup;
1565 APR_ARRAY_PUSH(chain, md_cert_t *) = cert;
1566 }
1567 else if (!strcmp("application/pem-certificate-chain", ct)
1568 || !strncmp("text/plain", ct, sizeof("text/plain")-1)) {
1569 /* Some servers seem to think 'text/plain' is sufficient, see #232 */
1570 rv = apr_brigade_pflatten(res->body, &data, &data_len, res->req->pool);
1571 if (APR_SUCCESS != rv) goto cleanup;
1572 rv = md_cert_read_chain(chain, res->req->pool, data, data_len);
1573 }
1574 else {
1576 "attempting to parse certificates from unrecognized content-type: %s", ct);
1577 rv = apr_brigade_pflatten(res->body, &data, &data_len, res->req->pool);
1578 if (APR_SUCCESS != rv) goto cleanup;
1579 rv = md_cert_read_chain(chain, res->req->pool, data, data_len);
1580 if (APR_SUCCESS == rv && chain->nelts == 0) {
1582 "certificate chain response did not contain any certificates "
1583 "(suspicious content-type: %s)", ct);
1584 rv = APR_ENOENT;
1585 }
1586 }
1587cleanup:
1589 "parsed certs from content-type=%s, content-length=%ld", ct, (long)data_len);
1590 return rv;
1591}
1592
1594{
1595 if (cert->x509) {
1597 }
1598 return MD_CERT_UNKNOWN;
1599}
1600
1602{
1603 FILE *f;
1604 apr_status_t rv;
1605 X509 *x509;
1606 md_cert_t *cert;
1607 unsigned long err;
1608
1609 rv = md_util_fopen(&f, fname, "r");
1610 if (rv == APR_SUCCESS) {
1612 while (NULL != (x509 = PEM_read_X509(f, NULL, NULL, NULL))) {
1613 cert = md_cert_make(p, x509);
1614 APR_ARRAY_PUSH(certs, md_cert_t *) = cert;
1615 }
1616 fclose(f);
1617
1618 if (0 < (err = ERR_get_error())
1620 /* not the expected one when no more PEM encodings are found */
1621 rv = APR_EINVAL;
1622 goto out;
1623 }
1624
1625 if (certs->nelts == 0) {
1626 /* Did not find any. This is acceptable unless the file has a certain size
1627 * when we no longer accept it as empty chain file. Something seems to be
1628 * wrong then. */
1630 if (APR_SUCCESS == apr_stat(&info, fname, APR_FINFO_SIZE, p) && info.size >= 1024) {
1631 /* "Too big for a moon." */
1632 rv = APR_EINVAL;
1634 "no certificates in non-empty chain %s", fname);
1635 goto out;
1636 }
1637 }
1638 }
1639out:
1640 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p, "read chain file %s, found %d certs",
1641 fname, certs? certs->nelts : 0);
1642 return rv;
1643}
1644
1646{
1647 apr_array_header_t *certs;
1648 apr_status_t rv;
1649
1650 certs = apr_array_make(p, 5, sizeof(md_cert_t *));
1651 rv = md_chain_fappend(certs, p, fname);
1652 *pcerts = (APR_SUCCESS == rv)? certs : NULL;
1653 return rv;
1654}
1655
1657 const char *fname, apr_fileperms_t perms)
1658{
1659 FILE *f;
1660 apr_status_t rv;
1661 const md_cert_t *cert;
1662 unsigned long err = 0;
1663 int i;
1664
1665 (void)p;
1666 rv = md_util_fopen(&f, fname, "w");
1667 if (rv == APR_SUCCESS) {
1670 for (i = 0; i < certs->nelts; ++i) {
1671 cert = APR_ARRAY_IDX(certs, i, const md_cert_t *);
1672 assert(cert->x509);
1673
1674 PEM_write_X509(f, cert->x509);
1675
1676 if (0 < (err = ERR_get_error())) {
1677 break;
1678 }
1679
1680 }
1681 rv = fclose(f);
1682 if (err) {
1683 rv = APR_EINVAL;
1684 }
1685 }
1686 return rv;
1687}
1688
1689/**************************************************************************************************/
1690/* certificate signing requests */
1691
1692static const char *alt_names(apr_array_header_t *domains, apr_pool_t *p)
1693{
1694 const char *alts = "", *sep = "", *domain;
1695 int i;
1696
1697 for (i = 0; i < domains->nelts; ++i) {
1698 domain = APR_ARRAY_IDX(domains, i, const char *);
1699 alts = apr_psprintf(p, "%s%sDNS:%s", alts, sep, domain);
1700 sep = ",";
1701 }
1702 return alts;
1703}
1704
1705static apr_status_t add_ext(X509 *x, int nid, const char *value, apr_pool_t *p)
1706{
1709 apr_status_t rv;
1710
1713 X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1714 if (NULL == (ext = X509V3_EXT_conf_nid(NULL, &ctx, nid, (char*)value))) {
1715 unsigned long err = ERR_get_error();
1716 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "add_ext, create, nid=%d value='%s' "
1717 "(lib=%d, reason=%d)", nid, value, ERR_GET_LIB(err), ERR_GET_REASON(err));
1718 return APR_EGENERAL;
1719 }
1720
1722 rv = X509_add_ext(x, ext, -1)? APR_SUCCESS : APR_EINVAL;
1723 if (APR_SUCCESS != rv) {
1724 unsigned long err = ERR_get_error();
1725 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "add_ext, add, nid=%d value='%s' "
1726 "(lib=%d, reason=%d)", nid, value, ERR_GET_LIB(err), ERR_GET_REASON(err));
1727 }
1729 return rv;
1730}
1731
1733 apr_array_header_t *domains, apr_pool_t *p)
1734{
1735 if (domains->nelts > 0) {
1736 X509_EXTENSION *x;
1737
1739 if (NULL == x) {
1740 return APR_EGENERAL;
1741 }
1743 }
1744 return APR_SUCCESS;
1745}
1746
1747#define MD_OID_MUST_STAPLE_NUM "1.3.6.1.5.5.7.1.24"
1748#define MD_OID_MUST_STAPLE_SNAME "tlsfeature"
1749#define MD_OID_MUST_STAPLE_LNAME "TLS Feature"
1750
1752{
1753 /* In case we do not get the NID for it, we treat this as not set. */
1754 int nid = MD_GET_NID(MUST_STAPLE);
1755 return ((NID_undef != nid)) && X509_get_ext_by_NID(cert->x509, nid, -1) >= 0;
1756}
1757
1759{
1760 X509_EXTENSION *x;
1761 int nid;
1762
1764 if (NID_undef == nid) {
1766 "%s: unable to get NID for v3 must-staple TLS feature", name);
1767 return APR_ENOTIMPL;
1768 }
1769 x = X509V3_EXT_conf_nid(NULL, NULL, nid, (char*)"DER:30:03:02:01:05");
1770 if (NULL == x) {
1772 "%s: unable to create x509 extension for must-staple", name);
1773 return APR_EGENERAL;
1774 }
1776 return APR_SUCCESS;
1777}
1778
1780 apr_array_header_t *domains, int must_staple,
1782{
1783 const char *s, *csr_der_64 = NULL;
1784 const unsigned char *domain;
1785 X509_REQ *csr;
1786 X509_NAME *n = NULL;
1788 apr_status_t rv;
1790 int csr_der_len;
1791
1792 assert(domains->nelts > 0);
1794
1795 if (NULL == (csr = X509_REQ_new())
1797 || NULL == (n = X509_NAME_new())) {
1798 rv = APR_ENOMEM;
1799 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: openssl alloc X509 things", name);
1800 goto out;
1801 }
1802
1803 /* subject name == first domain */
1804 domain = APR_ARRAY_IDX(domains, 0, const unsigned char *);
1805 /* Do not set the domain in the CN if it is longer than 64 octets.
1806 * Instead, let the CA choose a 'proper' name. At the moment (2021-01), LE will
1807 * inspect all SAN names and use one < 64 chars if it can be found. It will fail
1808 * otherwise.
1809 * The reason we do not check this beforehand is that the restrictions on CNs
1810 * are in flux. They used to be authoritative, now browsers no longer do that, but
1811 * no one wants to hand out a cert with "google.com" as CN either. So, we leave
1812 * it for the CA to decide if and how it hands out a cert for this or fails.
1813 * This solves issue where the name is too long, see #227 */
1814 if (strlen((const char*)domain) < 64
1815 && (!X509_NAME_add_entry_by_txt(n, "CN", MBSTRING_ASC, domain, -1, -1, 0)
1817 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: REQ name add entry", name);
1818 rv = APR_EGENERAL; goto out;
1819 }
1820 /* collect extensions, such as alt names and must staple */
1821 if (APR_SUCCESS != (rv = sk_add_alt_names(exts, domains, p))) {
1822 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: collecting alt names", name);
1823 rv = APR_EGENERAL; goto out;
1824 }
1825 if (must_staple && APR_SUCCESS != (rv = add_must_staple(exts, name, p))) {
1826 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: you requested that a certificate "
1827 "is created with the 'must-staple' extension, however the SSL library was "
1828 "unable to initialized that extension. Please file a bug report on which platform "
1829 "and with which library this happens. To continue before this problem is resolved, "
1830 "configure 'MDMustStaple off' for your domains", name);
1831 rv = APR_EGENERAL; goto out;
1832 }
1833 /* add extensions to csr */
1835 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: adding exts", name);
1836 rv = APR_EGENERAL; goto out;
1837 }
1838 /* add our key */
1839 if (!X509_REQ_set_pubkey(csr, pkey->pkey)) {
1840 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set pkey in csr", name);
1841 rv = APR_EGENERAL; goto out;
1842 }
1843 /* sign, der encode and base64url encode */
1844 if (!X509_REQ_sign(csr, pkey->pkey, pkey_get_MD(pkey))) {
1845 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: sign csr", name);
1846 rv = APR_EGENERAL; goto out;
1847 }
1848 if ((csr_der_len = i2d_X509_REQ(csr, NULL)) < 0) {
1849 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: der length", name);
1850 rv = APR_EGENERAL; goto out;
1851 }
1853 s = csr_der.data = apr_pcalloc(p, csr_der.len + 1);
1854 if (i2d_X509_REQ(csr, (unsigned char**)&s) != csr_der_len) {
1855 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: csr der enc", name);
1856 rv = APR_EGENERAL; goto out;
1857 }
1858 csr_der_64 = md_util_base64url_encode(&csr_der, p);
1859 rv = APR_SUCCESS;
1860
1861out:
1862 if (exts) {
1864 }
1865 if (csr) {
1867 }
1868 if (n) {
1870 }
1871 *pcsr_der_64 = (APR_SUCCESS == rv)? csr_der_64 : NULL;
1872 return rv;
1873}
1874
1875static apr_status_t mk_x509(X509 **px, md_pkey_t *pkey, const char *cn,
1877{
1878 X509 *x = NULL;
1879 X509_NAME *n = NULL;
1880 BIGNUM *big_rnd = NULL;
1882 unsigned char rnd[20];
1883 int days;
1884 apr_status_t rv;
1885
1886 if (NULL == (x = X509_new())
1887 || NULL == (n = X509_NAME_new())) {
1888 rv = APR_ENOMEM;
1889 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: openssl alloc X509 things", cn);
1890 goto out;
1891 }
1892
1893 if (APR_SUCCESS != (rv = md_rand_bytes(rnd, sizeof(rnd), p))
1894 || !(big_rnd = BN_bin2bn(rnd, sizeof(rnd), NULL))
1896 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: setup random serial", cn);
1897 rv = APR_EGENERAL; goto out;
1898 }
1900 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: set serial number", cn);
1901 rv = APR_EGENERAL; goto out;
1902 }
1903 if (1 != X509_set_version(x, 2L)) {
1904 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: setting x.509v3", cn);
1905 rv = APR_EGENERAL; goto out;
1906 }
1907 /* set common name and issuer */
1908 if (!X509_NAME_add_entry_by_txt(n, "CN", MBSTRING_ASC, (const unsigned char*)cn, -1, -1, 0)
1909 || !X509_set_subject_name(x, n)
1910 || !X509_set_issuer_name(x, n)) {
1911 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: name add entry", cn);
1912 rv = APR_EGENERAL; goto out;
1913 }
1914 /* cert are unconstrained (but not very trustworthy) */
1915 if (APR_SUCCESS != (rv = add_ext(x, NID_basic_constraints, "critical,CA:FALSE", p))) {
1916 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set basic constraints ext", cn);
1917 goto out;
1918 }
1919 /* add our key */
1920 if (!X509_set_pubkey(x, pkey->pkey)) {
1921 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set pkey in x509", cn);
1922 rv = APR_EGENERAL; goto out;
1923 }
1924 /* validity */
1926 if (!X509_set_notBefore(x, ASN1_TIME_set(NULL, time(NULL)))) {
1927 rv = APR_EGENERAL; goto out;
1928 }
1929 if (!X509_set_notAfter(x, ASN1_TIME_adj(NULL, time(NULL), days, 0))) {
1930 rv = APR_EGENERAL; goto out;
1931 }
1932
1933out:
1934 *px = (APR_SUCCESS == rv)? x : NULL;
1935 if (APR_SUCCESS != rv && x) X509_free(x);
1936 if (big_rnd) BN_free(big_rnd);
1938 if (n) X509_NAME_free(n);
1939 return rv;
1940}
1941
1945{
1946 X509 *x;
1947 md_cert_t *cert = NULL;
1948 apr_status_t rv;
1949
1950 assert(domains);
1951
1952 if (APR_SUCCESS != (rv = mk_x509(&x, pkey, cn, valid_for, p))) goto out;
1953
1954 /* add the domain as alt name */
1955 if (APR_SUCCESS != (rv = add_ext(x, NID_subject_alt_name, alt_names(domains, p), p))) {
1956 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set alt_name ext", cn);
1957 goto out;
1958 }
1959
1960 /* keyUsage, ExtendedKeyUsage */
1961
1962 if (APR_SUCCESS != (rv = add_ext(x, NID_key_usage, "critical,digitalSignature", p))) {
1963 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set keyUsage", cn);
1964 goto out;
1965 }
1966 if (APR_SUCCESS != (rv = add_ext(x, NID_ext_key_usage, "serverAuth", p))) {
1967 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set extKeyUsage", cn);
1968 goto out;
1969 }
1970
1971 /* sign with same key */
1972 if (!X509_sign(x, pkey->pkey, pkey_get_MD(pkey))) {
1973 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: sign x509", cn);
1974 rv = APR_EGENERAL; goto out;
1975 }
1976
1977 cert = md_cert_make(p, x);
1978 rv = APR_SUCCESS;
1979
1980out:
1981 *pcert = (APR_SUCCESS == rv)? cert : NULL;
1982 if (!cert && x) X509_free(x);
1983 return rv;
1984}
1985
1986#define MD_OID_ACME_VALIDATION_NUM "1.3.6.1.5.5.7.1.31"
1987#define MD_OID_ACME_VALIDATION_SNAME "pe-acmeIdentifier"
1988#define MD_OID_ACME_VALIDATION_LNAME "ACME Identifier"
1989
1999
2001 const char *acme_id, md_pkey_t *pkey,
2003{
2004 X509 *x;
2005 md_cert_t *cert = NULL;
2006 const char *alts;
2007 apr_status_t rv;
2008
2009 if (APR_SUCCESS != (rv = mk_x509(&x, pkey, "tls-alpn-01-challenge", valid_for, p))) goto out;
2010
2011 /* add the domain as alt name */
2012 alts = apr_psprintf(p, "DNS:%s", domain);
2013 if (APR_SUCCESS != (rv = add_ext(x, NID_subject_alt_name, alts, p))) {
2014 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set alt_name ext", domain);
2015 goto out;
2016 }
2017
2018 if (APR_SUCCESS != (rv = add_ext(x, get_acme_validation_nid(), acme_id, p))) {
2019 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set pe-acmeIdentifier", domain);
2020 goto out;
2021 }
2022
2023 /* sign with same key */
2024 if (!X509_sign(x, pkey->pkey, pkey_get_MD(pkey))) {
2025 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: sign x509", domain);
2026 rv = APR_EGENERAL; goto out;
2027 }
2028
2029 cert = md_cert_make(p, x);
2030 rv = APR_SUCCESS;
2031
2032out:
2033 if (!cert && x) {
2034 X509_free(x);
2035 }
2036 *pcert = (APR_SUCCESS == rv)? cert : NULL;
2037 return rv;
2038}
2039
2040#define MD_OID_CT_SCTS_NUM "1.3.6.1.4.1.11129.2.4.2"
2041#define MD_OID_CT_SCTS_SNAME "CT-SCTs"
2042#define MD_OID_CT_SCTS_LNAME "CT Certificate SCTs"
2043
2044#ifndef OPENSSL_NO_CT
2045static int get_ct_scts_nid(void)
2046{
2048 if (NID_undef == nid) {
2051 }
2052 return nid;
2053}
2054#endif
2055
2056const char *md_nid_get_sname(int nid)
2057{
2058 return OBJ_nid2sn(nid);
2059}
2060
2061const char *md_nid_get_lname(int nid)
2062{
2063 return OBJ_nid2ln(nid);
2064}
2065
2067{
2068#ifndef OPENSSL_NO_CT
2069 int nid, i, idx, critical;
2071 SCT *sct_handle;
2072 md_sct *sct;
2073 size_t len;
2074 const char *data;
2075
2076 nid = get_ct_scts_nid();
2077 if (NID_undef == nid) return APR_ENOTIMPL;
2078
2079 idx = -1;
2080 while (1) {
2081 sct_list = X509_get_ext_d2i(cert->x509, nid, &critical, &idx);
2082 if (sct_list) {
2083 for (i = 0; i < sk_SCT_num(sct_list); i++) {
2085 if (sct_handle) {
2086 sct = apr_pcalloc(p, sizeof(*sct));
2087 sct->version = SCT_get_version(sct_handle);
2089 len = SCT_get0_log_id(sct_handle, (unsigned char**)&data);
2090 sct->logid = md_data_make_pcopy(p, data, len);
2091 sct->signature_type_nid = SCT_get_signature_nid(sct_handle);
2092 len = SCT_get0_signature(sct_handle, (unsigned char**)&data);
2093 sct->signature = md_data_make_pcopy(p, data, len);
2094
2096 }
2097 }
2098 }
2099 if (idx < 0) break;
2100 }
2101 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p, "ct_sct, found %d SCT extensions", scts->nelts);
2102 return APR_SUCCESS;
2103#else
2104 (void)scts;
2105 (void)p;
2106 (void)cert;
2107 return APR_ENOTIMPL;
2108#endif
2109}
2110
2112{
2115 const char *url = NULL;
2116
2118 if (!ssk) {
2119 rv = APR_ENOENT;
2120 goto cleanup;
2121 }
2123 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, 0, p, "ocsp responder found '%s'", url);
2124
2125cleanup:
2126 if (ssk) X509_email_free(ssk);
2127 *purl = url;
2128 return rv;
2129}
2130
2132{
2133 const md_cert_t *cert;
2134
2135 if (certs->nelts == 0) {
2136 return APR_ENOENT;
2137 }
2138
2139 cert = APR_ARRAY_IDX(certs, 0, const md_cert_t*);
2140
2141 if (1 != X509_check_private_key(cert->x509, pkey->pkey)) {
2142 return APR_EGENERAL;
2143 }
2144
2145 return APR_SUCCESS;
2146}
int n
Definition ap_regex.h:278
const char apr_size_t len
Definition ap_regex.h:187
APR-UTIL Buckets/Bucket Brigades.
APR File I/O Handling.
APR general purpose library routines.
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
request_rec * r
const unsigned char * buf
Definition util_md5.h:50
ap_vhost_iterate_conn_cb void * baton
Definition http_vhost.h:87
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_ENOMEM
Definition apr_errno.h:683
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_ENOENT
Definition apr_errno.h:662
#define APR_EINVAL
Definition apr_errno.h:711
apr_file_t * f
apr_bucket * e
apr_brigade_flush void * ctx
apr_bucket apr_bucket_brigade * a
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
Definition apr_dbd.h:287
apr_datum_t * pkey
Definition apr_dbm.h:158
apr_datum_t apr_datum_t * pvalue
Definition apr_dbm.h:128
const char * url
Definition apr_escape.h:120
const char const apr_size_t data_len
const char * uri
Definition apr_uri.h:159
#define X509_get_notAfter
#define X509_get_notBefore
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const char int apr_pool_t * pool
Definition apr_cstr.h:84
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_int32_t apr_fileperms_t
const char * key
const char apr_fileperms_t perms
void * data
void const char apr_status_t(* cleanup)(void *))
char * buffer
const char * fname
#define APR_FINFO_SIZE
const apr_hash_t * h
Definition apr_hash.h:97
apr_interval_time_t t
apr_interval_time_t apr_int32_t * num
Definition apr_poll.h:273
apr_pool_t * b
Definition apr_pools.h:529
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char * sep
const char * s
Definition apr_strings.h:95
#define APR_ARRAY_PUSH(ary, type)
Definition apr_tables.h:150
#define APR_ARRAY_IDX(ary, i, type)
Definition apr_tables.h:141
apr_int32_t apr_int32_t apr_int32_t err
#define apr_time_from_msec(msec)
Definition apr_time.h:75
apr_int64_t apr_interval_time_t
Definition apr_time.h:55
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_sec(time)
Definition apr_time.h:63
#define apr_time_from_sec(sec)
Definition apr_time.h:78
CORE HTTP Daemon.
HTTP Daemon routines.
#define MD_PKEY_RSA_BITS_MIN
Definition md.h:36
#define MD_PKEY_RSA_BITS_DEF
Definition md.h:37
#define MD_KEY_CURVE
Definition md.h:135
#define MD_KEY_TYPE
Definition md.h:204
#define MD_KEY_BITS
Definition md.h:121
#define MD_GET_NID(x)
Definition md_crypt.c:276
static apr_status_t spec_from_json(void **pvalue, md_json_t *json, apr_pool_t *p, void *baton)
Definition md_crypt.c:432
apr_status_t md_cert_chain_read_http(struct apr_array_header_t *chain, apr_pool_t *p, const struct md_http_response_t *res)
Definition md_crypt.c:1540
#define MD_OID_ACME_VALIDATION_NUM
Definition md_crypt.c:1986
int md_certs_are_equal(const md_cert_t *a, const md_cert_t *b)
Definition md_crypt.c:1196
apr_status_t md_chain_fload(apr_array_header_t **pcerts, apr_pool_t *p, const char *fname)
Definition md_crypt.c:1645
static void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
Definition md_crypt.c:952
apr_status_t md_rand_bytes(unsigned char *buf, apr_size_t len, apr_pool_t *p)
Definition md_crypt.c:162
void md_pkey_free(md_pkey_t *pkey)
Definition md_crypt.c:590
apr_status_t md_chain_fappend(struct apr_array_header_t *certs, apr_pool_t *p, const char *fname)
Definition md_crypt.c:1601
md_json_t * md_pkey_spec_to_json(const md_pkey_spec_t *spec, apr_pool_t *p)
Definition md_crypt.c:348
const char * md_pkey_get_rsa_e64(md_pkey_t *pkey, apr_pool_t *p)
Definition md_crypt.c:979
apr_status_t md_cert_fload(md_cert_t **pcert, apr_pool_t *p, const char *fname)
Definition md_crypt.c:1353
static apr_time_t md_asn1_time_get(const ASN1_TIME *time)
Definition md_crypt.c:204
apr_status_t md_pkey_read_http(md_pkey_t **ppkey, apr_pool_t *pool, const struct md_http_response_t *res)
Definition md_crypt.c:706
apr_status_t md_cert_to_sha256_fingerprint(const char **pfinger, const md_cert_t *cert, apr_pool_t *p)
Definition md_crypt.c:1443
static int pem_passwd(char *buf, int size, int rwflag, void *baton)
Definition md_crypt.c:180
static int get_nid(const char *num, const char *sname, const char *lname)
Definition md_crypt.c:264
static int pkey_spec_eq(md_pkey_spec_t *s1, md_pkey_spec_t *s2)
Definition md_crypt.c:455
apr_status_t md_cert_read_chain(apr_array_header_t *chain, apr_pool_t *p, const char *pem, apr_size_t pem_len)
Definition md_crypt.c:1472
const char * md_cert_get_serial_number(const md_cert_t *cert, apr_pool_t *p)
Definition md_crypt.c:1180
static md_pkey_spec_t PkeySpecDef
Definition md_crypt.c:560
apr_status_t md_cert_get_issuers_uri(const char **puri, const md_cert_t *cert, apr_pool_t *p)
Definition md_crypt.c:1268
md_cert_t * md_cert_wrap(apr_pool_t *p, void *x509)
Definition md_crypt.c:1160
static apr_status_t mk_x509(X509 **px, md_pkey_t *pkey, const char *cn, apr_interval_time_t valid_for, apr_pool_t *p)
Definition md_crypt.c:1875
static apr_status_t cert_to_buffer(md_data_t *buffer, const md_cert_t *cert, apr_pool_t *p)
Definition md_crypt.c:1377
md_pkey_spec_t * md_pkeys_spec_get(const md_pkeys_spec_t *pks, int index)
Definition md_crypt.c:562
md_pkey_spec_t * md_pkey_spec_from_json(struct md_json_t *json, apr_pool_t *p)
Definition md_crypt.c:397
#define MD_OID_CT_SCTS_SNAME
Definition md_crypt.c:2041
apr_status_t md_cert_get_ocsp_responder_url(const char **purl, apr_pool_t *p, const md_cert_t *cert)
Definition md_crypt.c:2111
int md_cert_must_staple(const md_cert_t *cert)
Definition md_crypt.c:1751
apr_status_t md_cert_self_sign(md_cert_t **pcert, const char *cn, apr_array_header_t *domains, md_pkey_t *pkey, apr_interval_time_t valid_for, apr_pool_t *p)
Definition md_crypt.c:1942
#define MD_OID_CT_SCTS_LNAME
Definition md_crypt.c:2042
static int md_cert_read_pem(BIO *bf, apr_pool_t *p, md_cert_t **pcert)
Definition md_crypt.c:1456
apr_status_t md_chain_fsave(apr_array_header_t *certs, apr_pool_t *p, const char *fname, apr_fileperms_t perms)
Definition md_crypt.c:1656
int md_cert_covers_md(md_cert_t *cert, const md_t *md)
Definition md_crypt.c:1241
const char * md_pkey_get_rsa_n64(md_pkey_t *pkey, apr_pool_t *p)
Definition md_crypt.c:999
const char * md_pkey_spec_name(const md_pkey_spec_t *spec)
Definition md_crypt.c:520
static apr_status_t sk_add_alt_names(STACK_OF(X509_EXTENSION) *exts, apr_array_header_t *domains, apr_pool_t *p)
Definition md_crypt.c:1732
apr_time_t md_asn1_generalized_time_get(void *ASN1_GENERALIZEDTIME)
Definition md_crypt.c:256
static int get_ct_scts_nid(void)
Definition md_crypt.c:2045
static int rand_choosenum(int l, int h)
Definition md_crypt.c:88
apr_time_t md_cert_get_not_before(const md_cert_t *cert)
Definition md_crypt.c:1217
md_timeperiod_t md_cert_get_valid(const md_cert_t *cert)
Definition md_crypt.c:1222
const char * md_nid_get_sname(int nid)
Definition md_crypt.c:2056
apr_status_t md_crypt_sign64(const char **psign64, md_pkey_t *pkey, apr_pool_t *p, const char *d, size_t dlen)
Definition md_crypt.c:1019
apr_status_t md_cert_req_create(const char **pcsr_der_64, const char *name, apr_array_header_t *domains, int must_staple, md_pkey_t *pkey, apr_pool_t *p)
Definition md_crypt.c:1779
static apr_status_t gen_rsa(md_pkey_t **ppkey, apr_pool_t *p, unsigned int bits)
Definition md_crypt.c:771
int md_pkeys_spec_count(const md_pkeys_spec_t *pks)
Definition md_crypt.c:555
static md_pkey_t * make_pkey(apr_pool_t *p)
Definition md_crypt.c:573
md_cert_t * md_cert_make(apr_pool_t *p, void *x509)
Definition md_crypt.c:1168
int md_cert_is_valid_now(const md_cert_t *cert)
Definition md_crypt.c:1201
apr_status_t md_crypt_init(apr_pool_t *pool)
Definition md_crypt.c:133
static apr_status_t spec_to_json(void *value, md_json_t *json, apr_pool_t *p, void *baton)
Definition md_crypt.c:376
apr_status_t md_cert_get_alt_names(apr_array_header_t **pnames, const md_cert_t *cert, apr_pool_t *p)
Definition md_crypt.c:1295
int md_pkeys_spec_contains_rsa(md_pkeys_spec_t *pks)
Definition md_crypt.c:305
apr_status_t md_pkey_fsave(md_pkey_t *pkey, apr_pool_t *p, const char *pass_phrase, apr_size_t pass_len, const char *fname, apr_fileperms_t perms)
Definition md_crypt.c:691
apr_status_t md_pkey_gen(md_pkey_t **ppkey, apr_pool_t *p, md_pkey_spec_t *spec)
Definition md_crypt.c:933
apr_status_t md_cert_to_sha256_digest(md_data_t **pdigest, const md_cert_t *cert, apr_pool_t *p)
Definition md_crypt.c:1430
int md_cert_has_expired(const md_cert_t *cert)
Definition md_crypt.c:1207
static apr_status_t gen_ec(md_pkey_t **ppkey, apr_pool_t *p, const char *curve)
Definition md_crypt.c:820
apr_status_t md_cert_make_tls_alpn_01(md_cert_t **pcert, const char *domain, const char *acme_id, md_pkey_t *pkey, apr_interval_time_t valid_for, apr_pool_t *p)
Definition md_crypt.c:2000
apr_status_t md_cert_get_ct_scts(apr_array_header_t *scts, apr_pool_t *p, const md_cert_t *cert)
Definition md_crypt.c:2066
md_pkeys_spec_t * md_pkeys_spec_make(apr_pool_t *p)
Definition md_crypt.c:281
static apr_status_t cert_cleanup(void *data)
Definition md_crypt.c:1150
int md_pkeys_spec_eq(md_pkeys_spec_t *pks1, md_pkeys_spec_t *pks2)
Definition md_crypt.c:482
md_json_t * md_pkeys_spec_to_json(const md_pkeys_spec_t *pks, apr_pool_t *p)
Definition md_crypt.c:385
static const char * alt_names(apr_array_header_t *domains, apr_pool_t *p)
Definition md_crypt.c:1692
static apr_status_t add_ext(X509 *x, int nid, const char *value, apr_pool_t *p)
Definition md_crypt.c:1705
#define MD_OID_ACME_VALIDATION_LNAME
Definition md_crypt.c:1988
static const EVP_MD * pkey_get_MD(md_pkey_t *pkey)
Definition md_crypt.c:755
md_pkeys_spec_t * md_pkeys_spec_clone(apr_pool_t *p, const md_pkeys_spec_t *pks)
Definition md_crypt.c:538
apr_status_t md_crypt_sha256_digest64(const char **pdigest64, apr_pool_t *p, const md_data_t *d)
Definition md_crypt.c:1088
apr_status_t md_crypt_hmac64(const char **pmac64, const md_data_t *hmac_key, apr_pool_t *p, const char *d, size_t dlen)
Definition md_crypt.c:1116
#define MD_OID_CT_SCTS_NUM
Definition md_crypt.c:2040
static int initialized
Definition md_crypt.c:68
void * md_cert_get_X509(const md_cert_t *cert)
Definition md_crypt.c:1175
apr_status_t md_cert_fsave(md_cert_t *cert, apr_pool_t *p, const char *fname, apr_fileperms_t perms)
Definition md_crypt.c:1403
md_cert_state_t md_cert_state_get(const md_cert_t *cert)
Definition md_crypt.c:1593
apr_status_t md_crypt_sha256_digest_hex(const char **pdigesthex, apr_pool_t *p, const md_data_t *data)
Definition md_crypt.c:1103
apr_status_t md_check_cert_and_pkey(struct apr_array_header_t *certs, md_pkey_t *pkey)
Definition md_crypt.c:2131
void md_pkeys_spec_add_default(md_pkeys_spec_t *pks)
Definition md_crypt.c:296
md_pkeys_spec_t * md_pkeys_spec_from_json(struct md_json_t *json, apr_pool_t *p)
Definition md_crypt.c:439
apr_status_t md_pkey_fload(md_pkey_t **ppkey, apr_pool_t *p, const char *key, apr_size_t key_len, const char *fname)
Definition md_crypt.c:600
static md_pkey_spec_t * pkey_spec_clone(apr_pool_t *p, md_pkey_spec_t *spec)
Definition md_crypt.c:501
apr_status_t md_cert_read_http(md_cert_t **pcert, apr_pool_t *p, const md_http_response_t *res)
Definition md_crypt.c:1498
static apr_status_t pkey_to_buffer(md_data_t *buf, md_pkey_t *pkey, apr_pool_t *p, const char *pass, apr_size_t pass_len)
Definition md_crypt.c:634
static const char * bn64(const BIGNUM *b, apr_pool_t *p)
Definition md_crypt.c:965
void md_pkeys_spec_add(md_pkeys_spec_t *pks, md_pkey_spec_t *spec)
Definition md_crypt.c:291
int md_cert_covers_domain(md_cert_t *cert, const char *domain_name)
Definition md_crypt.c:1230
const char * md_nid_get_lname(int nid)
Definition md_crypt.c:2061
void md_pkeys_spec_add_ec(md_pkeys_spec_t *pks, const char *curve)
Definition md_crypt.c:338
static apr_status_t check_EC_curve(int nid, apr_pool_t *p)
Definition md_crypt.c:796
static apr_status_t fwrite_buffer(void *baton, apr_file_t *f, apr_pool_t *p)
Definition md_crypt.c:153
int md_pkeys_spec_is_empty(const md_pkeys_spec_t *pks)
Definition md_crypt.c:533
apr_time_t md_cert_get_not_after(const md_cert_t *cert)
Definition md_crypt.c:1212
void md_pkeys_spec_add_rsa(md_pkeys_spec_t *pks, unsigned int bits)
Definition md_crypt.c:316
apr_status_t md_cert_to_base64url(const char **ps64, const md_cert_t *cert, apr_pool_t *p)
Definition md_crypt.c:1416
static apr_status_t sha256_digest(md_data_t **pdigest, apr_pool_t *p, const md_data_t *buf)
Definition md_crypt.c:1060
void * md_pkey_get_EVP_PKEY(struct md_pkey_t *pkey)
Definition md_crypt.c:595
static void seed_RAND(int pid)
Definition md_crypt.c:101
#define MD_OID_ACME_VALIDATION_SNAME
Definition md_crypt.c:1987
static apr_status_t pkey_cleanup(void *data)
Definition md_crypt.c:580
int md_pkeys_spec_contains_ec(md_pkeys_spec_t *pks, const char *curve)
Definition md_crypt.c:326
static apr_status_t add_must_staple(STACK_OF(X509_EXTENSION) *exts, const char *name, apr_pool_t *p)
Definition md_crypt.c:1758
static int get_acme_validation_nid(void)
Definition md_crypt.c:1990
md_pkey_type_t
Definition md_crypt.h:49
@ MD_PKEY_TYPE_RSA
Definition md_crypt.h:51
@ MD_PKEY_TYPE_EC
Definition md_crypt.h:52
@ MD_PKEY_TYPE_DEFAULT
Definition md_crypt.h:50
md_cert_state_t
Definition md_crypt.h:131
@ MD_CERT_VALID
Definition md_crypt.h:133
@ MD_CERT_EXPIRED
Definition md_crypt.h:134
@ MD_CERT_UNKNOWN
Definition md_crypt.h:132
apr_pool_t * p
Definition md_event.c:32
md_json_t * md_json_create(apr_pool_t *pool)
Definition md_json.c:92
apr_status_t md_json_sets(const char *value, md_json_t *json,...)
Definition md_json.c:430
const char * md_json_gets(const md_json_t *json,...)
Definition md_json.c:406
long md_json_getl(const md_json_t *json,...)
Definition md_json.c:381
apr_status_t md_json_geta(apr_array_header_t *a, md_json_from_cb *cb, void *baton, const md_json_t *json,...)
Definition md_json.c:730
md_json_t * md_json_getj(md_json_t *json,...)
Definition md_json.c:473
apr_status_t md_json_seta(apr_array_header_t *a, md_json_to_cb *cb, void *baton, md_json_t *json,...)
Definition md_json.c:767
int md_json_is(const md_json_type_t jtype, md_json_t *json,...)
Definition md_json.c:294
apr_status_t md_json_setj(const md_json_t *value, md_json_t *json,...)
Definition md_json.c:527
apr_status_t md_json_setl(long value, md_json_t *json,...)
Definition md_json.c:392
@ MD_JSON_TYPE_ARRAY
Definition md_json.h:33
void md_log_perror(const char *file, int line, md_log_level_t level, apr_status_t rv, apr_pool_t *p, const char *fmt,...)
Definition md_log.c:68
#define MD_LOG_MARK
Definition md_log.h:39
@ MD_LOG_TRACE2
Definition md_log.h:30
@ MD_LOG_TRACE1
Definition md_log.h:29
@ MD_LOG_TRACE4
Definition md_log.h:32
@ MD_LOG_ERR
Definition md_log.h:24
@ MD_LOG_WARNING
Definition md_log.h:25
@ MD_LOG_TRACE3
Definition md_log.h:31
@ MD_LOG_DEBUG
Definition md_log.h:28
#define MD_SECS_PER_DAY
Definition md_time.h:23
int md_dns_domains_match(const apr_array_header_t *domains, const char *name)
Definition md_util.c:907
void md_data_pinit(md_data_t *d, apr_size_t len, apr_pool_t *p)
Definition md_util.c:79
apr_status_t md_util_fopen(FILE **pf, const char *fn, const char *mode)
Definition md_util.c:352
const char * md_util_base64url_encode(const md_data_t *data, apr_pool_t *pool)
Definition md_util.c:1207
int md_array_str_index(const apr_array_header_t *array, const char *s, int start, int case_sensitive)
Definition md_util.c:250
md_data_t * md_data_make_pcopy(apr_pool_t *p, const char *data, apr_size_t len)
Definition md_util.c:120
const char * md_util_parse_ct(apr_pool_t *pool, const char *cth)
Definition md_util.c:1547
apr_status_t md_data_to_hex(const char **phex, char separator, apr_pool_t *p, const md_data_t *data)
Definition md_util.c:169
void md_data_null(md_data_t *d)
Definition md_util.c:107
apr_status_t md_util_freplace(const char *fpath, apr_fileperms_t perms, apr_pool_t *p, md_util_file_cb *write_cb, void *baton)
Definition md_util.c:433
md_data_t * md_data_pmake(apr_size_t len, apr_pool_t *p)
Definition md_util.c:86
static apr_file_t * out
Definition mod_info.c:85
#define RAND_MAX
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
STACK_OF(X509_NAME)
char * name
int nid
apr_pool_t * pool
Definition apr_tables.h:64
X509 * x509
Definition md_crypt.c:1146
apr_pool_t * pool
Definition md_crypt.c:1145
apr_array_header_t * alt_names
Definition md_crypt.c:1147
const char * curve
Definition md_crypt.h:60
apr_uint32_t bits
Definition md_crypt.h:56
md_pkey_type_t type
Definition md_crypt.h:64
md_pkey_ec_params_t ec
Definition md_crypt.h:67
md_pkey_rsa_params_t rsa
Definition md_crypt.h:66
union md_pkey_spec_t::@24 params
EVP_PKEY * pkey
Definition md_crypt.c:72
apr_pool_t * pool
Definition md_crypt.c:71
apr_pool_t * p
Definition md_crypt.h:72
struct apr_array_header_t * specs
Definition md_crypt.h:73
Definition md.h:76
struct apr_array_header_t * domains
Definition md.h:78
int pass_len
Definition md_crypt.c:177
const char * pass_phrase
Definition md_crypt.c:176
const char * digest
Definition testmd5.c:30
#define str
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray
INT info