37#include <mbedtls/ssl.h>
38#include <mbedtls/ssl_cache.h>
39#include <mbedtls/ssl_ticket.h>
40#include <mbedtls/net_sockets.h>
41#include <mbedtls/entropy.h>
42#include <mbedtls/ctr_drbg.h>
43#include <mbedtls/error.h>
44#include <mbedtls/md.h>
45#include <mbedtls/cipher.h>
46#include <mbedtls/x509_crt.h>
47#include <mbedtls/pk.h>
48#include <mbedtls/platform.h>
49#include <mbedtls/ssl_ciphersuites.h>
64static void cwist_mtls_set_err(
int ret) {
65 cwist_mtls_last_err = (
unsigned long)(
unsigned int)(-
ret);
69 unsigned long e = cwist_mtls_last_err;
70 cwist_mtls_last_err = 0;
75 if (!buf || len == 0)
return;
84 cwist_mtls_last_err = 0;
92static pid_t cwist_mtls_rng_pid;
93static int cwist_mtls_rng_ready;
96static int cwist_mtls_rng_init_locked(
void) {
98 if (cwist_mtls_rng_ready && cwist_mtls_rng_pid ==
pid)
return 0;
100 if (cwist_mtls_rng_ready) {
105 cwist_mtls_set_err(
ret);
108 cwist_mtls_rng_pid =
pid;
117 cwist_mtls_set_err(
ret);
122 cwist_mtls_rng_ready = 1;
123 cwist_mtls_rng_pid =
pid;
128 if (!buf ||
num < 0)
return 0;
130 int ok = cwist_mtls_rng_init_locked() == 0 &&
137static int cwist_mtls_rng_cb(
void *
p_rng,
unsigned char *buf,
size_t len) {
150 const volatile unsigned char *
pa = (
const volatile unsigned char *)
a;
151 const volatile unsigned char *
pb = (
const volatile unsigned char *)b;
152 unsigned char diff = 0;
159struct cwist_mtls_evp_md {
166 return &cwist_mtls_md_sha256;
170 const unsigned char *
msg,
size_t msg_len,
unsigned char *out,
171 unsigned int *out_len) {
172 if (!md || !out)
return NULL;
177 cwist_mtls_set_err(
ret);
184struct cwist_mtls_hmac_ctx {
191 if (ctx)
memset(ctx, 0,
sizeof(*ctx));
205 if (!ctx || !md)
return 0;
220 if (!ctx || !ctx->started)
return 0;
225 if (!ctx || !ctx->started || !out)
return 0;
234struct cwist_mtls_cipher {
241 return &cwist_mtls_cipher_aes_256_cbc;
244struct cwist_mtls_cipher_ctx {
250 if (ctx)
memset(ctx, 0,
sizeof(*ctx));
262 const unsigned char *key,
const unsigned char *
iv,
264 if (!ctx || !type || !key || !
iv)
return 0;
281 const unsigned char *key,
const unsigned char *
iv) {
287 const unsigned char *key,
const unsigned char *
iv) {
293 const unsigned char *
in,
int inl) {
295 if (!ctx || !
outl ||
inl < 0)
return 0;
303 if (!ctx || !
outl)
return 0;
310 const unsigned char *
in,
int inl) {
322 const unsigned char *client,
unsigned int client_len) {
328 unsigned int clen = client[
j++];
331 *out = (
unsigned char *)(
server +
i);
344struct cwist_mtls_method {
348static const struct cwist_mtls_method cwist_mtls_server_method = {1};
349static const struct cwist_mtls_method cwist_mtls_client_method = {0};
352 return &cwist_mtls_server_method;
356 return &cwist_mtls_client_method;
359#define CWIST_MTLS_EX_DATA_MAX 8
361struct cwist_mtls_ctx {
371 unsigned long options;
377 const char *alpn_list[3];
378 char alpn_names[2][16];
392static _Atomic
int cwist_mtls_ex_data_next;
395 if (!method)
return NULL;
397 if (ctx)
memset(ctx, 0,
sizeof(*ctx));
398 if (!ctx)
return NULL;
400 ctx->is_server = method->is_server;
422 if (ctx->is_server) {
425#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
442static void cwist_mtls_ctx_destroy(
SSL_CTX *ctx) {
458 cwist_mtls_ctx_destroy(ctx);
477 ctx->options |= options;
488 return (
long)ctx->options;
499static int cwist_mtls_cipher_id(
const char *name,
size_t len,
int *
is_tls13) {
505 static const struct entry
table[] = {
516 for (
size_t i = 0;
i <
sizeof(
table) /
sizeof(
table[0]);
i++) {
527static int cwist_mtls_apply_ciphersuites(
SSL_CTX *ctx) {
529 for (
size_t i = 0;
i < ctx->cs13_count &&
n < 30;
i++) ctx->cs_applied[
n++] = ctx->cs13[
i];
530 for (
size_t i = 0;
i < ctx->cs12_count &&
n < 30;
i++) ctx->cs_applied[
n++] = ctx->cs12[
i];
531 if (
n == 0)
return 0;
532 ctx->cs_applied[
n] = 0;
538 if (!ctx || !
list)
return 0;
540 const char *
p =
list;
545 int id = cwist_mtls_cipher_id(
p, len, &
is_tls13);
547 if (
is_tls13 && ctx->cs13_count < 8) {
548 ctx->cs13[ctx->cs13_count++] = id;
550 }
else if (!
is_tls13 && ctx->cs12_count < 16) {
551 ctx->cs12[ctx->cs12_count++] = id;
561 return want_tls13 ? 1 : cwist_mtls_apply_ciphersuites(ctx);
565 return cwist_mtls_set_cipher_list(ctx,
list, 0);
569 return cwist_mtls_set_cipher_list(ctx,
list, 1) ? cwist_mtls_apply_ciphersuites(ctx) : 0;
573static int cwist_mtls_maybe_conf_own_cert(
SSL_CTX *ctx) {
574 if (!ctx->cert_loaded || !ctx->key_loaded)
return 1;
577 cwist_mtls_set_err(
ret);
584 if (!ctx || !path)
return 0;
589 cwist_mtls_set_err(
ret);
592 ctx->cert_loaded = 1;
593 return cwist_mtls_maybe_conf_own_cert(ctx);
602 cwist_mtls_set_err(
ret);
606 return cwist_mtls_maybe_conf_own_cert(ctx);
615 if (!ctx || ctx->min_version == 0)
return 0;
620 if (!ctx || !ctx->cert_loaded || !ctx->key_loaded)
return 0;
632 ctx->sess_cache_max = (
long)size;
634 return ctx->sess_cache_max;
654 int (*cb)(
SSL *ssl,
const unsigned char **out,
655 unsigned char *
outlen,
const unsigned char *
in,
656 unsigned int inlen,
void *arg),
658 if (!ctx || !cb)
return;
667 static const unsigned char offer[] =
"\x02h2\x08http/1.1";
670 const unsigned char *
sel =
NULL;
687 ctx->alpn_list[
n] =
NULL;
698 ctx->alpn_list[0] =
NULL;
707 unsigned int len =
protos[
i++];
708 if (
i + len >
protos_len || len == 0 || len >=
sizeof(ctx->alpn_names[0]) ||
n >= 2) {
712 ctx->alpn_names[
n][len] =
'\0';
713 ctx->alpn_list[
n] = ctx->alpn_names[
n];
717 ctx->alpn_list[
n] =
NULL;
727struct cwist_mtls_ticket_key {
728 unsigned char name[16];
729 unsigned char aes_key[32];
730 unsigned char hmac_key[32];
738 if (!ctx || !ctx->is_server)
return;
749 const struct cwist_mtls_ticket_key *key =
NULL;
751 if (ctx->ex_data[
i]) {
752 key = (
const struct cwist_mtls_ticket_key *)ctx->ex_data[
i];
766 cwist_mtls_set_err(
ret);
784 cwist_mtls_set_err(
ret);
789 memcpy(
t->MBEDTLS_PRIVATE(
keys)[0].MBEDTLS_PRIVATE(name), key->name,
792 t->MBEDTLS_PRIVATE(active) = 0;
816 ctx->ex_data[
idx] = data;
822 return ctx->ex_data[
idx];
836 if (!
file || !*
file)
file =
"/etc/ssl/certs/ca-certificates.crt";
838 const char *
dir =
getenv(
"SSL_CERT_DIR");
839 if (!
dir || !*
dir)
dir =
"/etc/ssl/certs";
858struct cwist_mtls_ssl {
865 const char *alpn_list[3];
866 char alpn_names[2][16];
874 if (!ctx)
return NULL;
876 if (s)
memset(s, 0,
sizeof(*s));
915static int cwist_mtls_map_result(
SSL *ssl,
int ret,
int ok_value) {
925 cwist_mtls_set_err(
ret);
931static int cwist_mtls_handshake(
SSL *ssl) {
937 return cwist_mtls_handshake(ssl);
942 return cwist_mtls_handshake(ssl);
946 if (!ssl || !buf ||
num <= 0)
return -1;
969 cwist_mtls_set_err(
ret);
975 if (!ssl || !buf ||
num < 0)
return -1;
989 cwist_mtls_set_err(
ret);
1009 return ssl->last_err;
1013 return ssl ? ssl->ctx :
NULL;
1032 if (!ssl)
return NULL;
1041 return "ECDHE-ECDSA-AES128-GCM-SHA256";
1044 return "ECDHE-ECDSA-AES256-GCM-SHA384";
1047 return "ECDHE-ECDSA-CHACHA20-POLY1305";
1049 return "ECDHE-RSA-CHACHA20-POLY1305";
1055 unsigned int *len) {
1057 *data = (
const unsigned char *)
p;
1062 if (!ssl || !name)
return 0;
1076 unsigned int len =
protos[
i++];
1077 if (
i + len >
protos_len || len == 0 || len >=
sizeof(ssl->alpn_names[0]) ||
n >= 2) {
1081 ssl->alpn_names[
n][len] =
'\0';
1082 ssl->alpn_list[
n] = ssl->alpn_names[
n];
1086 ssl->alpn_list[
n] =
NULL;
Memory allocation wrappers backed by libttak.
void cwist_free(void *ptr)
Free memory obtained via cwist_alloc/cwist_strdup/etc.
void * cwist_malloc(size_t size)
Allocate zeroed memory via the CWIST owner context.
const SSL_METHOD * cwist_mtls_TLS_client_method(void)
int cwist_mtls_SSL_read(SSL *ssl, void *buf, int num)
void cwist_mtls_SSL_free(SSL *ssl)
int cwist_mtls_EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl)
int cwist_mtls_SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *path, int type)
int cwist_mtls_EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, void *engine, const unsigned char *key, const unsigned char *iv)
void cwist_mtls_SSL_CTX_set_tlsext_ticket_key_cb(SSL_CTX *ctx, int(*cb)(SSL *ssl, unsigned char *key_name, unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc))
int cwist_mtls_SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *path)
void cwist_mtls_SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, unsigned int *len)
int cwist_mtls_SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsigned char *server, unsigned int server_len, const unsigned char *client, unsigned int client_len)
int cwist_mtls_SSL_CTX_check_private_key(const SSL_CTX *ctx)
void cwist_mtls_HMAC_CTX_free(HMAC_CTX *ctx)
int cwist_mtls_SSL_CTX_get_min_proto_version(const SSL_CTX *ctx)
int cwist_mtls_SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *list)
void cwist_mtls_SSL_CTX_set_verify(SSL_CTX *ctx, int mode, void *callback)
#define CWIST_MTLS_EX_DATA_MAX
int cwist_mtls_SSL_set_fd(SSL *ssl, int fd)
int cwist_mtls_SSL_CTX_set_ex_data(SSL_CTX *ctx, int idx, void *data)
void cwist_mtls_OPENSSL_cleanse(void *ptr, size_t len)
int cwist_mtls_SSL_write(SSL *ssl, const void *buf, int num)
long cwist_mtls_SSL_CTX_set_mode(SSL_CTX *ctx, long mode)
HMAC_CTX * cwist_mtls_HMAC_CTX_new(void)
int cwist_mtls_SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *list)
int cwist_mtls_SSL_set_tlsext_host_name(SSL *ssl, const char *name)
const SSL_METHOD * cwist_mtls_TLS_server_method(void)
int cwist_mtls_SSL_CTX_set1_groups_list(SSL_CTX *ctx, const char *groups)
void cwist_mtls_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
SSL_CTX * cwist_mtls_SSL_get_SSL_CTX(const SSL *ssl)
const char * cwist_mtls_SSL_get_cipher_name(const SSL *ssl)
unsigned char * cwist_mtls_HMAC(const EVP_MD *md, const void *key, int key_len, const unsigned char *msg, size_t msg_len, unsigned char *out, unsigned int *out_len)
void * cwist_mtls_SSL_CTX_get_ex_data(const SSL_CTX *ctx, int idx)
int cwist_mtls_SSL_CTX_set_min_proto_version(SSL_CTX *ctx, uint16_t version)
int cwist_mtls_EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
int cwist_mtls_SSL_version(const SSL *ssl)
int cwist_mtls_SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
EVP_CIPHER_CTX * cwist_mtls_EVP_CIPHER_CTX_new(void)
unsigned long cwist_mtls_ERR_get_error(void)
int cwist_mtls_SSL_CTX_get_ex_new_index(long argl, void *argp, void *new_func, void *dup_func, void *free_func)
SSL_CTX * cwist_mtls_SSL_CTX_new(const SSL_METHOD *method)
int cwist_mtls_SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *path, int type)
int cwist_mtls_SSL_get_error(const SSL *ssl, int ret)
int cwist_mtls_RAND_bytes(unsigned char *buf, int num)
long cwist_mtls_SSL_CTX_set_session_cache_mode(SSL_CTX *ctx, long mode)
int cwist_mtls_EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
void cwist_mtls_ERR_clear_error(void)
int cwist_mtls_EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, void *engine, const unsigned char *key, const unsigned char *iv)
const EVP_MD * cwist_mtls_EVP_sha256(void)
void cwist_mtls_SSL_CTX_free(SSL_CTX *ctx)
int cwist_mtls_HMAC_Final(HMAC_CTX *ctx, unsigned char *out, unsigned int *out_len)
int cwist_mtls_SSL_shutdown(SSL *ssl)
SSL * cwist_mtls_SSL_new(SSL_CTX *ctx)
long cwist_mtls_SSL_CTX_sess_set_cache_size(SSL_CTX *ctx, unsigned long size)
int cwist_mtls_SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, unsigned int protos_len)
long cwist_mtls_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long options)
int cwist_mtls_SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, unsigned int sid_ctx_len)
int cwist_mtls_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, void *engine)
int cwist_mtls_SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, unsigned int protos_len)
const EVP_CIPHER * cwist_mtls_EVP_aes_256_cbc(void)
int cwist_mtls_SSL_connect(SSL *ssl)
int cwist_mtls_SSL_session_reused(const SSL *ssl)
int cwist_mtls_SSL_pending(const SSL *ssl)
void cwist_mtls_ERR_error_string_n(unsigned long e, char *buf, size_t len)
int cwist_mtls_EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl)
int cwist_mtls_SSL_accept(SSL *ssl)
int cwist_mtls_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len)
long cwist_mtls_SSL_CTX_set_timeout(SSL_CTX *ctx, long seconds)
int cwist_mtls_CRYPTO_memcmp(const void *a, const void *b, size_t len)
void cwist_mtls_SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, int(*cb)(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg), void *arg)
mbedTLS TLS backend: OPENSSL_cleanse / CRYPTO_memcmp.
mbedTLS TLS backend: error queue subset.
mbedTLS TLS backend: EVP subset (HMAC digest tags, AES-256-CBC).
struct cwist_mtls_cipher EVP_CIPHER
struct cwist_mtls_cipher_ctx EVP_CIPHER_CTX
struct cwist_mtls_evp_md EVP_MD
mbedTLS TLS backend: HMAC subset (HMAC-SHA256, one-shot + streaming).
struct cwist_mtls_hmac_ctx HMAC_CTX
mbedTLS TLS backend: RAND_bytes over mbedTLS CTR-DRBG.
mbedTLS TLS backend: OpenSSL-shaped seam over the CWIST TLS subset.
struct cwist_mtls_ssl SSL
#define SSL_MODE_AUTO_RETRY
#define SSL_TLSEXT_ERR_OK
#define OPENSSL_NPN_NEGOTIATED
#define SSL_ERROR_WANT_READ
#define SSL_OP_NO_TLSv1_2
struct cwist_mtls_method SSL_METHOD
#define SSL_SESS_CACHE_SERVER
#define SSL_ERROR_ZERO_RETURN
struct cwist_mtls_ctx SSL_CTX
#define SSL_ERROR_WANT_WRITE