Skip to content

Instantly share code, notes, and snippets.

@dwolrdcojp
Last active April 12, 2024 23:11
Show Gist options
  • Save dwolrdcojp/a5b2d69a0eb360993c505422b31009dd to your computer and use it in GitHub Desktop.
Save dwolrdcojp/a5b2d69a0eb360993c505422b31009dd to your computer and use it in GitHub Desktop.
Fix fio build context for certifcates
/** 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