Last active
April 12, 2024 23:11
-
-
Save dwolrdcojp/a5b2d69a0eb360993c505422b31009dd to your computer and use it in GitHub Desktop.
Fix fio build context for certifcates
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** Called when the library specific data for the context should be built */ | |
static void fio_tls_build_context(fio_tls_s *tls) { | |
fio_tls_destroy_context(tls); | |
/* TODO: Library specific implementation */ | |
/* create new context */ | |
tls->ctx = SSL_CTX_new(TLS_method()); | |
SSL_CTX_set_mode(tls->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); | |
/* see: https://caniuse.com/#search=tls */ | |
SSL_CTX_set_min_proto_version(tls->ctx, TLS1_2_VERSION); | |
SSL_CTX_set_options(tls->ctx, SSL_OP_NO_COMPRESSION); | |
/* attach certificates */ | |
FIO_ARY_FOR(&tls->sni, pos) { | |
fio_str_info_s keys[4] = { | |
fio_str_info(&pos->private_key), fio_str_info(&pos->public_key), | |
fio_str_info(&pos->password), | |
/* empty password slot for public key */ | |
}; | |
if (keys[0].len && keys[1].len) { | |
if (1) { | |
/* Extract private key from private key file */ | |
BIO *bio = BIO_new_mem_buf(keys[0].data, keys[0].len); | |
if (bio) { | |
EVP_PKEY *k = PEM_read_bio_PrivateKey( | |
bio, NULL, fio_tls_pem_passwd_cb, keys + 2); | |
if (k) { | |
FIO_LOG_DEBUG("TLS read private key from PEM file."); | |
SSL_CTX_use_PrivateKey(tls->ctx, k); | |
} | |
BIO_free(bio); | |
} | |
} | |
/* Certificate Files loaded */ | |
for (int ki = 0; ki < 2; ++ki) { | |
/* Extract as much data as possible from each file */ | |
BIO *bio = BIO_new_mem_buf(keys[ki].data, keys[ki].len); | |
FIO_ASSERT(bio, "OpenSSL error allocating BIO."); | |
STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio( | |
bio, NULL, fio_tls_pem_passwd_cb, keys + ki + 2); | |
if (inf) { | |
for (int i = 0; i < sk_X509_INFO_num(inf); ++i) { | |
/* for each element in PEM */ | |
X509_INFO *tmp = sk_X509_INFO_value(inf, i); | |
if (tmp->x509) { | |
FIO_LOG_DEBUG("TLS adding certificate from PEM file."); | |
if (i == 0) { | |
SSL_CTX_use_certificate(tls->ctx, tmp->x509); | |
} else { | |
SSL_CTX_add1_chain_cert(tls->ctx, tmp->x509); | |
} | |
} | |
if (tmp->x_pkey) { | |
FIO_LOG_DEBUG("TLS adding private key from PEM file."); | |
SSL_CTX_use_PrivateKey(tls->ctx, tmp->x_pkey->dec_pkey); | |
} | |
} | |
sk_X509_INFO_pop_free(inf, X509_INFO_free); | |
} else { | |
/* TODO: attempt DER format? */ | |
// X509 *c; | |
// EVP_PKEY *k; | |
// const uint8_t *pdata = (uint8_t *)&keys[ki].data; | |
// d2i_X509(&c, &pdata, keys[ki].len); | |
// pdata = (uint8_t *)&keys[ki].data; | |
// d2i_AutoPrivateKey(&k, &pdata, keys[ki].len); | |
} | |
BIO_free(bio); | |
} | |
} else if (keys[0].len) { | |
/* Self Signed Certificates, only if server name is provided. */ | |
SSL_CTX_use_certificate(tls->ctx, | |
fio_tls_create_self_signed(keys[0].data)); | |
SSL_CTX_use_PrivateKey(tls->ctx, fio_tls_pkey); | |
} | |
} | |
/* setup ALPN support */ | |
if (1) { | |
size_t alpn_pos = 0; | |
/* looping twice is better than malloc fragmentation. */ | |
FIO_SET_FOR_LOOP(&tls->alpn, pos) { | |
fio_str_info_s s = fio_str_info(&pos->obj.name); | |
if (!s.len) | |
continue; | |
alpn_pos += s.len + 1; | |
} | |
tls->alpn_str = malloc((alpn_pos | 15) + 1); /* round up to 16 + padding */ | |
alpn_pos = 0; | |
FIO_SET_FOR_LOOP(&tls->alpn, pos) { | |
fio_str_info_s s = fio_str_info(&pos->obj.name); | |
if (!s.len) | |
continue; | |
tls->alpn_str[alpn_pos++] = (uint8_t)s.len; | |
memcpy(tls->alpn_str + alpn_pos, s.data, s.len); | |
alpn_pos += s.len; | |
} | |
tls->alpn_len = alpn_pos; | |
SSL_CTX_set_alpn_select_cb(tls->ctx, fio_tls_alpn_selector_cb, tls); | |
SSL_CTX_set_alpn_protos(tls->ctx, tls->alpn_str, tls->alpn_len); | |
} | |
/* Peer Verification / Trust */ | |
if (trust_ary_count(&tls->trust)) { | |
/* TODO: enable peer verification */ | |
X509_STORE *store = X509_STORE_new(); | |
SSL_CTX_set_cert_store(tls->ctx, store); | |
SSL_CTX_set_verify(tls->ctx, SSL_VERIFY_PEER, NULL); | |
/* TODO: Add each ceriticate in the PEM to the trust "store" */ | |
FIO_ARY_FOR(&tls->trust, pos) { | |
fio_str_info_s pem = fio_str_info(&pos->pem); | |
BIO *bio = BIO_new_mem_buf(pem.data, pem.len); | |
FIO_ASSERT(bio, "OpenSSL error allocating BIO."); | |
STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); | |
if (inf) { | |
for (int i = 0; i < sk_X509_INFO_num(inf); ++i) { | |
/* for each element in PEM */ | |
X509_INFO *tmp = sk_X509_INFO_value(inf, i); | |
if (tmp->x509) { | |
FIO_LOG_DEBUG("TLS trusting certificate from PEM file."); | |
X509_STORE_add_cert(store, tmp->x509); | |
} | |
if (tmp->crl) { | |
X509_STORE_add_crl(store, tmp->crl); | |
} | |
} | |
sk_X509_INFO_pop_free(inf, X509_INFO_free); | |
} | |
BIO_free(bio); | |
} | |
} | |
FIO_LOG_DEBUG("(re)built TLS context for OpenSSL %p", (void *)tls); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment