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>
48#if APR_HAVE_SYS_TYPES_H
60#if !defined(OPENSSL_NO_CT) \
61 && OPENSSL_VERSION_NUMBER >= 0x10100000L \
62 && (!defined(LIBRESSL_VERSION_NUMBER) \
63 || LIBRESSL_VERSION_NUMBER >= 0x3050000fL)
65#include <openssl/ct.h>
75#ifdef MD_HAVE_ARC4RANDOM
185 if (
ctx->pass_len > 0) {
206#if OPENSSL_VERSION_NUMBER < 0x10002000L || (defined(LIBRESSL_VERSION_NUMBER) && \
207 LIBRESSL_VERSION_NUMBER < 0x3060000fL)
212 const char*
str = (
const char*) time->data;
218 t.tm_year = (
str[
i++] -
'0') * 10;
219 t.tm_year += (
str[
i++] -
'0');
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');
230 t.tm_mon = (
str[
i++] -
'0') * 10;
231 t.tm_mon += (
str[
i++] -
'0') - 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');
276#define MD_GET_NID(x) get_nid(MD_OID_##x##_NUM, MD_OID_##x##_SNAME, MD_OID_##x##_LNAME)
352 switch (spec->
type) {
460 if (
s1 &&
s2 &&
s1->type ==
s2->type) {
465 if (
s1->params.rsa.bits ==
s2->params.rsa.bits) {
470 if (
s1->params.ec.curve ==
s2->params.ec.curve) {
473 else if (!
s1->params.ec.curve || !
s2->params.ec.curve) {
476 return !
strcmp(
s1->params.ec.curve,
s2->params.ec.curve);
490 for(
i = 0;
i <
pks1->specs->nelts; ++
i) {
507 switch (spec->
type) {
522 if (!spec)
return "rsa";
523 switch (spec->
type) {
626 "error loading pkey %s: %s (pass phrase was %snull)",
fname,
653 if (
pass && pass_len > 0) {
655 ctx.pass_len = (
int)pass_len;
702 fname, pass_len > 0?
"with" :
"without", (
int)pass_len);
741 "error loading pkey from http response: %s",
806 "error looking up OpenSSL builtin EC curves");
809 for (
i = 0;
i <
nc; ++
i) {
839#ifdef NID_X9_62_prime256v1
845#ifdef NID_X9_62_prime192v1
851#if defined(NID_X25519) && (!defined(LIBRESSL_VERSION_NUMBER) || \
852 LIBRESSL_VERSION_NUMBER >= 0x3070000fL)
870#if defined(NID_X25519) && (!defined(LIBRESSL_VERSION_NUMBER) || \
871 LIBRESSL_VERSION_NUMBER >= 0x3070000fL)
878 "error generate EC key for group: %s", curve);
885#if defined(NID_X448) && !defined(LIBRESSL_VERSION_NUMBER)
892 "error generate EC key for group: %s", curve);
900#if OPENSSL_VERSION_NUMBER < 0x30000000L
909 "error generate EC key for group: %s", curve);
919 "error generate EC key for group: %s", curve);
948#if OPENSSL_VERSION_NUMBER < 0x10100000L \
949 || (defined(LIBRESSL_VERSION_NUMBER) \
950 && LIBRESSL_VERSION_NUMBER < 0x2070000f)
981#if OPENSSL_VERSION_NUMBER < 0x30000000L
1001#if OPENSSL_VERSION_NUMBER < 0x30000000L
1020 const char *
d,
size_t dlen)
1127 (
const unsigned char*)
d, (
size_t)
dlen,
1246 if (!
cert->alt_names) {
1249 if (
cert->alt_names) {
1251 cert->alt_names->nelts);
1256 "md domain %s not covered by cert",
name);
1306 const unsigned char *ip;
1312 switch (
cval->type) {
1321#if OPENSSL_VERSION_NUMBER < 0x10100000L
1328 ip[0], ip[1], ip[2], ip[3]);
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]);
1510 if (!
res->body || !
ct ||
strcmp(
"application/pkix-cert",
ct)) {
1520 const unsigned char *
bf = (
const unsigned char*)der;
1531 "parsing cert from content-type=%s, content-length=%ld",
ct, (
long)
data_len);
1551 "chain_read, processing %d response",
res->status);
1553 if (blen > 1024*1024) {
1562 if (!
strcmp(
"application/pkix-cert",
ct)) {
1567 else if (!
strcmp(
"application/pem-certificate-chain",
ct)
1568 || !
strncmp(
"text/plain",
ct,
sizeof(
"text/plain")-1)) {
1576 "attempting to parse certificates from unrecognized content-type: %s",
ct);
1582 "certificate chain response did not contain any certificates "
1583 "(suspicious content-type: %s)",
ct);
1589 "parsed certs from content-type=%s, content-length=%ld",
ct, (
long)
data_len);
1625 if (certs->
nelts == 0) {
1634 "no certificates in non-empty chain %s",
fname);
1662 unsigned long err = 0;
1670 for (
i = 0;
i < certs->
nelts; ++
i) {
1694 const char *
alts =
"", *
sep =
"", *domain;
1697 for (
i = 0;
i < domains->
nelts; ++
i) {
1735 if (domains->
nelts > 0) {
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"
1766 "%s: unable to get NID for v3 must-staple TLS feature",
name);
1772 "%s: unable to create x509 extension for must-staple",
name);
1783 const char *
s, *csr_der_64 =
NULL;
1784 const unsigned char *domain;
1814 if (strlen((
const char*)domain) < 64
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);
1882 unsigned char rnd[20];
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"
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"
2044#ifndef OPENSSL_NO_CT
2068#ifndef OPENSSL_NO_CT
2135 if (certs->
nelts == 0) {
const char apr_size_t len
APR-UTIL Buckets/Bucket Brigades.
APR general purpose library routines.
apr_size_t const unsigned char unsigned int unsigned int d
const unsigned char * buf
ap_vhost_iterate_conn_cb void * baton
apr_brigade_flush void * ctx
apr_bucket apr_bucket_brigade * a
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
apr_datum_t apr_datum_t * pvalue
const char const apr_size_t data_len
#define X509_get_notAfter
#define X509_get_notBefore
const char int apr_pool_t * pool
apr_int32_t apr_fileperms_t
const char apr_fileperms_t perms
void const char apr_status_t(* cleanup)(void *))
apr_interval_time_t apr_int32_t * num
#define apr_pcalloc(p, size)
#define APR_ARRAY_PUSH(ary, type)
#define APR_ARRAY_IDX(ary, i, type)
apr_int32_t apr_int32_t apr_int32_t err
#define apr_time_from_msec(msec)
apr_int64_t apr_interval_time_t
#define apr_time_sec(time)
#define apr_time_from_sec(sec)
#define MD_PKEY_RSA_BITS_MIN
#define MD_PKEY_RSA_BITS_DEF
static apr_status_t spec_from_json(void **pvalue, md_json_t *json, apr_pool_t *p, void *baton)
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)
#define MD_OID_ACME_VALIDATION_NUM
int md_certs_are_equal(const md_cert_t *a, const md_cert_t *b)
apr_status_t md_chain_fload(apr_array_header_t **pcerts, apr_pool_t *p, const char *fname)
static void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
apr_status_t md_rand_bytes(unsigned char *buf, apr_size_t len, apr_pool_t *p)
void md_pkey_free(md_pkey_t *pkey)
apr_status_t md_chain_fappend(struct apr_array_header_t *certs, apr_pool_t *p, const char *fname)
md_json_t * md_pkey_spec_to_json(const md_pkey_spec_t *spec, apr_pool_t *p)
const char * md_pkey_get_rsa_e64(md_pkey_t *pkey, apr_pool_t *p)
apr_status_t md_cert_fload(md_cert_t **pcert, apr_pool_t *p, const char *fname)
static apr_time_t md_asn1_time_get(const ASN1_TIME *time)
apr_status_t md_pkey_read_http(md_pkey_t **ppkey, apr_pool_t *pool, const struct md_http_response_t *res)
apr_status_t md_cert_to_sha256_fingerprint(const char **pfinger, const md_cert_t *cert, apr_pool_t *p)
static int pem_passwd(char *buf, int size, int rwflag, void *baton)
static int get_nid(const char *num, const char *sname, const char *lname)
static int pkey_spec_eq(md_pkey_spec_t *s1, md_pkey_spec_t *s2)
apr_status_t md_cert_read_chain(apr_array_header_t *chain, apr_pool_t *p, const char *pem, apr_size_t pem_len)
const char * md_cert_get_serial_number(const md_cert_t *cert, apr_pool_t *p)
static md_pkey_spec_t PkeySpecDef
apr_status_t md_cert_get_issuers_uri(const char **puri, const md_cert_t *cert, apr_pool_t *p)
md_cert_t * md_cert_wrap(apr_pool_t *p, void *x509)
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)
static apr_status_t cert_to_buffer(md_data_t *buffer, const md_cert_t *cert, apr_pool_t *p)
md_pkey_spec_t * md_pkeys_spec_get(const md_pkeys_spec_t *pks, int index)
md_pkey_spec_t * md_pkey_spec_from_json(struct md_json_t *json, apr_pool_t *p)
#define MD_OID_CT_SCTS_SNAME
apr_status_t md_cert_get_ocsp_responder_url(const char **purl, apr_pool_t *p, const md_cert_t *cert)
int md_cert_must_staple(const md_cert_t *cert)
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)
#define MD_OID_CT_SCTS_LNAME
static int md_cert_read_pem(BIO *bf, apr_pool_t *p, md_cert_t **pcert)
apr_status_t md_chain_fsave(apr_array_header_t *certs, apr_pool_t *p, const char *fname, apr_fileperms_t perms)
int md_cert_covers_md(md_cert_t *cert, const md_t *md)
const char * md_pkey_get_rsa_n64(md_pkey_t *pkey, apr_pool_t *p)
const char * md_pkey_spec_name(const md_pkey_spec_t *spec)
static apr_status_t sk_add_alt_names(STACK_OF(X509_EXTENSION) *exts, apr_array_header_t *domains, apr_pool_t *p)
apr_time_t md_asn1_generalized_time_get(void *ASN1_GENERALIZEDTIME)
static int get_ct_scts_nid(void)
static int rand_choosenum(int l, int h)
apr_time_t md_cert_get_not_before(const md_cert_t *cert)
md_timeperiod_t md_cert_get_valid(const md_cert_t *cert)
const char * md_nid_get_sname(int nid)
apr_status_t md_crypt_sign64(const char **psign64, md_pkey_t *pkey, apr_pool_t *p, const char *d, size_t dlen)
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)
static apr_status_t gen_rsa(md_pkey_t **ppkey, apr_pool_t *p, unsigned int bits)
int md_pkeys_spec_count(const md_pkeys_spec_t *pks)
static md_pkey_t * make_pkey(apr_pool_t *p)
md_cert_t * md_cert_make(apr_pool_t *p, void *x509)
int md_cert_is_valid_now(const md_cert_t *cert)
apr_status_t md_crypt_init(apr_pool_t *pool)
static apr_status_t spec_to_json(void *value, md_json_t *json, apr_pool_t *p, void *baton)
apr_status_t md_cert_get_alt_names(apr_array_header_t **pnames, const md_cert_t *cert, apr_pool_t *p)
int md_pkeys_spec_contains_rsa(md_pkeys_spec_t *pks)
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)
apr_status_t md_pkey_gen(md_pkey_t **ppkey, apr_pool_t *p, md_pkey_spec_t *spec)
apr_status_t md_cert_to_sha256_digest(md_data_t **pdigest, const md_cert_t *cert, apr_pool_t *p)
int md_cert_has_expired(const md_cert_t *cert)
static apr_status_t gen_ec(md_pkey_t **ppkey, apr_pool_t *p, const char *curve)
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)
apr_status_t md_cert_get_ct_scts(apr_array_header_t *scts, apr_pool_t *p, const md_cert_t *cert)
md_pkeys_spec_t * md_pkeys_spec_make(apr_pool_t *p)
static apr_status_t cert_cleanup(void *data)
int md_pkeys_spec_eq(md_pkeys_spec_t *pks1, md_pkeys_spec_t *pks2)
md_json_t * md_pkeys_spec_to_json(const md_pkeys_spec_t *pks, apr_pool_t *p)
static const char * alt_names(apr_array_header_t *domains, apr_pool_t *p)
static apr_status_t add_ext(X509 *x, int nid, const char *value, apr_pool_t *p)
#define MD_OID_ACME_VALIDATION_LNAME
static const EVP_MD * pkey_get_MD(md_pkey_t *pkey)
md_pkeys_spec_t * md_pkeys_spec_clone(apr_pool_t *p, const md_pkeys_spec_t *pks)
apr_status_t md_crypt_sha256_digest64(const char **pdigest64, apr_pool_t *p, const md_data_t *d)
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)
#define MD_OID_CT_SCTS_NUM
void * md_cert_get_X509(const md_cert_t *cert)
apr_status_t md_cert_fsave(md_cert_t *cert, apr_pool_t *p, const char *fname, apr_fileperms_t perms)
md_cert_state_t md_cert_state_get(const md_cert_t *cert)
apr_status_t md_crypt_sha256_digest_hex(const char **pdigesthex, apr_pool_t *p, const md_data_t *data)
apr_status_t md_check_cert_and_pkey(struct apr_array_header_t *certs, md_pkey_t *pkey)
void md_pkeys_spec_add_default(md_pkeys_spec_t *pks)
md_pkeys_spec_t * md_pkeys_spec_from_json(struct md_json_t *json, apr_pool_t *p)
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)
static md_pkey_spec_t * pkey_spec_clone(apr_pool_t *p, md_pkey_spec_t *spec)
apr_status_t md_cert_read_http(md_cert_t **pcert, apr_pool_t *p, const md_http_response_t *res)
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)
static const char * bn64(const BIGNUM *b, apr_pool_t *p)
void md_pkeys_spec_add(md_pkeys_spec_t *pks, md_pkey_spec_t *spec)
int md_cert_covers_domain(md_cert_t *cert, const char *domain_name)
const char * md_nid_get_lname(int nid)
void md_pkeys_spec_add_ec(md_pkeys_spec_t *pks, const char *curve)
static apr_status_t check_EC_curve(int nid, apr_pool_t *p)
static apr_status_t fwrite_buffer(void *baton, apr_file_t *f, apr_pool_t *p)
int md_pkeys_spec_is_empty(const md_pkeys_spec_t *pks)
apr_time_t md_cert_get_not_after(const md_cert_t *cert)
void md_pkeys_spec_add_rsa(md_pkeys_spec_t *pks, unsigned int bits)
apr_status_t md_cert_to_base64url(const char **ps64, const md_cert_t *cert, apr_pool_t *p)
static apr_status_t sha256_digest(md_data_t **pdigest, apr_pool_t *p, const md_data_t *buf)
void * md_pkey_get_EVP_PKEY(struct md_pkey_t *pkey)
static void seed_RAND(int pid)
#define MD_OID_ACME_VALIDATION_SNAME
static apr_status_t pkey_cleanup(void *data)
int md_pkeys_spec_contains_ec(md_pkeys_spec_t *pks, const char *curve)
static apr_status_t add_must_staple(STACK_OF(X509_EXTENSION) *exts, const char *name, apr_pool_t *p)
static int get_acme_validation_nid(void)
md_json_t * md_json_create(apr_pool_t *pool)
apr_status_t md_json_sets(const char *value, md_json_t *json,...)
const char * md_json_gets(const md_json_t *json,...)
long md_json_getl(const md_json_t *json,...)
apr_status_t md_json_geta(apr_array_header_t *a, md_json_from_cb *cb, void *baton, const md_json_t *json,...)
md_json_t * md_json_getj(md_json_t *json,...)
apr_status_t md_json_seta(apr_array_header_t *a, md_json_to_cb *cb, void *baton, md_json_t *json,...)
int md_json_is(const md_json_type_t jtype, md_json_t *json,...)
apr_status_t md_json_setj(const md_json_t *value, md_json_t *json,...)
apr_status_t md_json_setl(long value, md_json_t *json,...)
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,...)
int md_dns_domains_match(const apr_array_header_t *domains, const char *name)
void md_data_pinit(md_data_t *d, apr_size_t len, apr_pool_t *p)
apr_status_t md_util_fopen(FILE **pf, const char *fn, const char *mode)
const char * md_util_base64url_encode(const md_data_t *data, apr_pool_t *pool)
int md_array_str_index(const apr_array_header_t *array, const char *s, int start, int case_sensitive)
md_data_t * md_data_make_pcopy(apr_pool_t *p, const char *data, apr_size_t len)
const char * md_util_parse_ct(apr_pool_t *pool, const char *cth)
apr_status_t md_data_to_hex(const char **phex, char separator, apr_pool_t *p, const md_data_t *data)
void md_data_null(md_data_t *d)
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)
md_data_t * md_data_pmake(apr_size_t len, apr_pool_t *p)
apr_array_header_t * alt_names
union md_pkey_spec_t::@24 params
struct apr_array_header_t * specs
struct apr_array_header_t * domains
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray