ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
tls.c File Reference

Go to the source code of this file.

Functions

asciichat_error_t quic_tls_server_create (const char *alpn, const char *certificate_file, const char *private_key_file, quic_tls_t **out)
asciichat_error_t quic_tls_client_create (const char *alpn, const char *ca_file, quic_tls_t **out)
asciichat_error_t quic_tls_client_configure (quic_tls_t *tls, SSL *ssl, const char *server_name)
asciichat_error_t quic_tls_session_create (quic_tls_t *tls, const char *server_name, ngtcp2_crypto_conn_ref *connection, SSL **out)
asciichat_error_t quic_tls_verify_ready (quic_tls_t *tls, SSL *ssl)
void quic_tls_session_destroy (SSL **ssl)
void quic_tls_destroy (quic_tls_t **tls)

Function Documentation

◆ quic_tls_client_configure()

asciichat_error_t quic_tls_client_configure ( quic_tls_t * tls,
SSL * ssl,
const char * server_name )

Configure certificate identity verification, SNI and ALPN on a client SSL.

Definition at line 112 of file tls.c.

112 {
113 if (!tls || tls->server || !ssl || SSL_get_SSL_CTX(ssl) != tls->ssl_ctx || !server_name || !*server_name)
114 return SET_ERRNO(ERROR_INVALID_PARAM, "QUIC client requires the expected server identity");
115 ERR_clear_error();
116 X509_VERIFY_PARAM *verify = SSL_get0_param(ssl);
117 X509_VERIFY_PARAM_set_hostflags(verify, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
118 if (SSL_set_alpn_protos(ssl, tls->alpn, tls->alpn_length) != 0 ||
119 (is_valid_ip(server_name)
120 ? X509_VERIFY_PARAM_set1_ip_asc(verify, server_name) != 1
121 : (SSL_set_tlsext_host_name(ssl, server_name) != 1 || SSL_set1_host(ssl, server_name) != 1)))
122 return tls_error("Cannot configure QUIC server identity");
123 return ASCIICHAT_OK;
124}
#define SET_ERRNO(code,...)
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
int is_valid_ip(const char *ip)
Check if string is a valid IP address (IPv4 or IPv6).
Definition ip.c:453
SSL_CTX * ssl_ctx
Definition tls.h:12
unsigned char alpn[256]
Definition tls.h:13
bool server
Definition tls.h:15
unsigned int alpn_length
Definition tls.h:14

References quic_tls_t::alpn, quic_tls_t::alpn_length, ASCIICHAT_OK, ERROR_INVALID_PARAM, is_valid_ip(), quic_tls_t::server, SET_ERRNO, and quic_tls_t::ssl_ctx.

Referenced by quic_tls_session_create().

◆ quic_tls_client_create()

asciichat_error_t quic_tls_client_create ( const char * alpn,
const char * ca_file,
quic_tls_t ** out )

Create a TLS 1.3 client context. NULL ca_file selects the system trust store.

Definition at line 90 of file tls.c.

90 {
91 if (!out)
92 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC client trust configuration");
93 *out = NULL;
94 if (ca_file && !*ca_file)
95 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC client trust configuration");
96 quic_tls_t *tls = NULL;
97 asciichat_error_t result = create_context(false, alpn, &tls);
98 if (result != ASCIICHAT_OK)
99 return result;
100 ERR_clear_error();
101 int loaded = ca_file ? SSL_CTX_load_verify_locations(tls->ssl_ctx, ca_file, NULL)
102 : SSL_CTX_set_default_verify_paths(tls->ssl_ctx);
103 if (loaded != 1) {
104 result = tls_error("Cannot load QUIC client trust roots");
105 quic_tls_destroy(&tls);
106 return result;
107 }
108 *out = tls;
109 return ASCIICHAT_OK;
110}
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
static bool size_t gotel_query_t * out
Definition queries.h:8
void quic_tls_destroy(quic_tls_t **tls)
Definition tls.c:202

References ASCIICHAT_OK, ERROR_INVALID_PARAM, out, quic_tls_destroy(), SET_ERRNO, and quic_tls_t::ssl_ctx.

Referenced by quic_endpoint_open().

◆ quic_tls_destroy()

void quic_tls_destroy ( quic_tls_t ** tls)

Definition at line 202 of file tls.c.

202 {
203 if (tls && *tls) {
204 SSL_CTX_free((*tls)->ssl_ctx);
205 SAFE_FREE(*tls);
206 }
207}
#define SAFE_FREE(ptr)
Definition common.h:377

References SAFE_FREE.

Referenced by quic_endpoint_destroy(), quic_endpoint_open(), quic_tls_client_create(), and quic_tls_server_create().

◆ quic_tls_server_create()

asciichat_error_t quic_tls_server_create ( const char * alpn,
const char * certificate_file,
const char * private_key_file,
quic_tls_t ** out )

Create a TLS 1.3 server context. Certificate and key are copied by OpenSSL.

Definition at line 67 of file tls.c.

68 {
69 if (!out)
70 return SET_ERRNO(ERROR_INVALID_PARAM, "QUIC server requires a certificate and private key");
71 *out = NULL;
72 if (!certificate_file || !*certificate_file || !private_key_file || !*private_key_file)
73 return SET_ERRNO(ERROR_INVALID_PARAM, "QUIC server requires a certificate and private key");
74 quic_tls_t *tls = NULL;
75 asciichat_error_t result = create_context(true, alpn, &tls);
76 if (result != ASCIICHAT_OK)
77 return result;
78 ERR_clear_error();
79 if (SSL_CTX_use_certificate_chain_file(tls->ssl_ctx, certificate_file) != 1 ||
80 SSL_CTX_use_PrivateKey_file(tls->ssl_ctx, private_key_file, SSL_FILETYPE_PEM) != 1 ||
81 SSL_CTX_check_private_key(tls->ssl_ctx) != 1) {
82 result = tls_error("Cannot load QUIC server certificate or private key");
83 quic_tls_destroy(&tls);
84 return result;
85 }
86 *out = tls;
87 return ASCIICHAT_OK;
88}

References ASCIICHAT_OK, ERROR_INVALID_PARAM, out, quic_tls_destroy(), SET_ERRNO, and quic_tls_t::ssl_ctx.

Referenced by quic_endpoint_open().

◆ quic_tls_session_create()

asciichat_error_t quic_tls_session_create ( quic_tls_t * tls,
const char * server_name,
ngtcp2_crypto_conn_ref * connection,
SSL ** out )

The connection reference is borrowed and must remain valid while SSL uses it. The caller owns the SSL and must clear its app data before freeing it if the ngtcp2 connection or reference can have been destroyed first.

Definition at line 126 of file tls.c.

127 {
128 if (!out)
129 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC TLS session arguments");
130 *out = NULL;
131 if (!tls || !tls->ssl_ctx || !connection || !connection->get_conn || (tls->server && server_name))
132 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC TLS session arguments");
133 ERR_clear_error();
134 SSL *ssl = SSL_new(tls->ssl_ctx);
135 if (!ssl)
136 return tls_error("Cannot create QUIC TLS session");
137 if (SSL_set_app_data(ssl, connection) != 1) {
138 asciichat_error_t result = tls_error("Cannot attach QUIC connection to TLS session");
139 SSL_free(ssl);
140 return result;
141 }
143 if (tls->server) {
144 SSL_set_accept_state(ssl);
145 if (ngtcp2_crypto_ossl_configure_server_session(ssl) != 0)
146 result = tls_error("Cannot configure server QUIC TLS callbacks");
147 } else {
148 SSL_set_connect_state(ssl);
149 result = quic_tls_client_configure(tls, ssl, server_name);
150 if (result == ASCIICHAT_OK && ngtcp2_crypto_ossl_configure_client_session(ssl) != 0)
151 result = tls_error("Cannot configure client QUIC TLS callbacks");
152 }
153 if (result != ASCIICHAT_OK) {
155 return result;
156 }
157 *out = ssl;
158 return ASCIICHAT_OK;
159}
void quic_tls_session_destroy(SSL **ssl)
Definition tls.c:194
asciichat_error_t quic_tls_client_configure(quic_tls_t *tls, SSL *ssl, const char *server_name)
Definition tls.c:112

References ASCIICHAT_OK, ERROR_INVALID_PARAM, out, quic_tls_client_configure(), quic_tls_session_destroy(), quic_tls_t::server, SET_ERRNO, and quic_tls_t::ssl_ctx.

◆ quic_tls_session_destroy()

void quic_tls_session_destroy ( SSL ** ssl)

Definition at line 194 of file tls.c.

194 {
195 if (ssl && *ssl) {
196 SSL_set_app_data(*ssl, NULL);
197 SSL_free(*ssl);
198 *ssl = NULL;
199 }
200}

Referenced by quic_connection_destroy(), and quic_tls_session_create().

◆ quic_tls_verify_ready()

asciichat_error_t quic_tls_verify_ready ( quic_tls_t * tls,
SSL * ssl )

Call after the TLS handshake and before exposing the connection as ready. Requires the configured ALPN; a client also requires a verified peer cert.

Definition at line 161 of file tls.c.

161 {
162 if (!tls || !ssl || SSL_get_SSL_CTX(ssl) != tls->ssl_ctx || !SSL_is_init_finished(ssl))
163 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC TLS handshake is not complete");
164 const unsigned char *selected = NULL;
165 unsigned int length = 0;
166 SSL_get0_alpn_selected(ssl, &selected, &length);
167 bool negotiated = false;
168 for (size_t offset = 0; offset < tls->alpn_length;) {
169 size_t protocol_length = tls->alpn[offset++];
170 if (protocol_length > tls->alpn_length - offset)
171 break;
172 if (selected && protocol_length == (size_t)length && !memcmp(selected, tls->alpn + offset, protocol_length))
173 negotiated = true;
174 offset += protocol_length;
175 }
176 if (!negotiated)
177 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "QUIC TLS ALPN was not negotiated");
178 if (!tls->server) {
179 X509_VERIFY_PARAM *verify = SSL_get0_param(ssl);
180 const char *host = X509_VERIFY_PARAM_get0_host(verify, 0);
181 char *ip = X509_VERIFY_PARAM_get1_ip_asc(verify);
182 X509 *peer = SSL_get0_peer_certificate(ssl);
183 bool identity_matches =
184 peer && (host || ip) &&
185 (!host || X509_check_host(peer, host, 0, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS, NULL) == 1) &&
186 (!ip || X509_check_ip_asc(peer, ip, 0) == 1);
187 OPENSSL_free(ip);
188 if (!identity_matches || !(SSL_get_verify_mode(ssl) & SSL_VERIFY_PEER) || SSL_get_verify_result(ssl) != X509_V_OK)
189 return SET_ERRNO(ERROR_CRYPTO, "QUIC TLS peer certificate or identity was not verified");
190 }
191 return ASCIICHAT_OK;
192}
@ ERROR_INVALID_STATE
@ ERROR_NETWORK_PROTOCOL
Definition error_codes.h:76
@ ERROR_CRYPTO
Definition error_codes.h:93

References quic_tls_t::alpn, quic_tls_t::alpn_length, ASCIICHAT_OK, ERROR_CRYPTO, ERROR_INVALID_STATE, ERROR_NETWORK_PROTOCOL, quic_tls_t::server, SET_ERRNO, and quic_tls_t::ssl_ctx.