1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 
6 #include <aws/io/channel.h>
7 #include <aws/io/file_utils.h>
8 #include <aws/io/logging.h>
9 #include <aws/io/private/pem_utils.h>
10 #include <aws/io/private/tls_channel_handler_shared.h>
11 #include <aws/io/tls_channel_handler.h>
12 
13 #define AWS_DEFAULT_TLS_TIMEOUT_MS 10000
14 
15 #include <aws/common/string.h>
16 
aws_tls_ctx_options_init_default_client(struct aws_tls_ctx_options * options,struct aws_allocator * allocator)17 void aws_tls_ctx_options_init_default_client(struct aws_tls_ctx_options *options, struct aws_allocator *allocator) {
18     AWS_ZERO_STRUCT(*options);
19     options->allocator = allocator;
20     options->minimum_tls_version = AWS_IO_TLS_VER_SYS_DEFAULTS;
21     options->cipher_pref = AWS_IO_TLS_CIPHER_PREF_SYSTEM_DEFAULT;
22     options->verify_peer = true;
23     options->max_fragment_size = g_aws_channel_max_fragment_size;
24 }
25 
aws_tls_ctx_options_clean_up(struct aws_tls_ctx_options * options)26 void aws_tls_ctx_options_clean_up(struct aws_tls_ctx_options *options) {
27     aws_byte_buf_clean_up(&options->ca_file);
28     aws_string_destroy(options->ca_path);
29     aws_byte_buf_clean_up(&options->certificate);
30     aws_byte_buf_clean_up_secure(&options->private_key);
31 
32 #ifdef __APPLE__
33     aws_byte_buf_clean_up_secure(&options->pkcs12);
34     aws_byte_buf_clean_up_secure(&options->pkcs12_password);
35 
36 #    if !defined(AWS_OS_IOS)
37     aws_string_destroy(options->keychain_path);
38 #    endif
39 #endif
40 
41     aws_string_destroy(options->alpn_list);
42 
43     AWS_ZERO_STRUCT(*options);
44 }
45 
46 #if !defined(AWS_OS_IOS)
47 
aws_tls_ctx_options_init_client_mtls(struct aws_tls_ctx_options * options,struct aws_allocator * allocator,const struct aws_byte_cursor * cert,const struct aws_byte_cursor * pkey)48 int aws_tls_ctx_options_init_client_mtls(
49     struct aws_tls_ctx_options *options,
50     struct aws_allocator *allocator,
51     const struct aws_byte_cursor *cert,
52     const struct aws_byte_cursor *pkey) {
53 
54     AWS_ZERO_STRUCT(*options);
55     options->minimum_tls_version = AWS_IO_TLS_VER_SYS_DEFAULTS;
56     options->cipher_pref = AWS_IO_TLS_CIPHER_PREF_SYSTEM_DEFAULT;
57     options->verify_peer = true;
58     options->allocator = allocator;
59     options->max_fragment_size = g_aws_channel_max_fragment_size;
60 
61     if (aws_byte_buf_init_copy_from_cursor(&options->certificate, allocator, *cert)) {
62         goto error;
63     }
64 
65     if (aws_sanitize_pem(&options->certificate, allocator)) {
66         AWS_LOGF_ERROR(AWS_LS_IO_TLS, "static: Invalid certificate. File must contain PEM encoded data");
67         goto error;
68     }
69 
70     if (aws_byte_buf_init_copy_from_cursor(&options->private_key, allocator, *pkey)) {
71         goto error;
72     }
73 
74     if (aws_sanitize_pem(&options->private_key, allocator)) {
75         AWS_LOGF_ERROR(AWS_LS_IO_TLS, "static: Invalid private key. File must contain PEM encoded data");
76         goto error;
77     }
78 
79     return AWS_OP_SUCCESS;
80 error:
81     aws_tls_ctx_options_clean_up(options);
82     return AWS_OP_ERR;
83 }
84 
aws_tls_ctx_options_init_client_mtls_from_path(struct aws_tls_ctx_options * options,struct aws_allocator * allocator,const char * cert_path,const char * pkey_path)85 int aws_tls_ctx_options_init_client_mtls_from_path(
86     struct aws_tls_ctx_options *options,
87     struct aws_allocator *allocator,
88     const char *cert_path,
89     const char *pkey_path) {
90 
91     AWS_ZERO_STRUCT(*options);
92     options->minimum_tls_version = AWS_IO_TLS_VER_SYS_DEFAULTS;
93     options->cipher_pref = AWS_IO_TLS_CIPHER_PREF_SYSTEM_DEFAULT;
94     options->verify_peer = true;
95     options->allocator = allocator;
96     options->max_fragment_size = g_aws_channel_max_fragment_size;
97 
98     if (aws_byte_buf_init_from_file(&options->certificate, allocator, cert_path)) {
99         goto error;
100     }
101 
102     if (aws_sanitize_pem(&options->certificate, allocator)) {
103         AWS_LOGF_ERROR(AWS_LS_IO_TLS, "static: Invalid certificate. File must contain PEM encoded data");
104         goto error;
105     }
106 
107     if (aws_byte_buf_init_from_file(&options->private_key, allocator, pkey_path)) {
108         goto error;
109     }
110 
111     if (aws_sanitize_pem(&options->private_key, allocator)) {
112         AWS_LOGF_ERROR(AWS_LS_IO_TLS, "static: Invalid private key. File must contain PEM encoded data");
113         goto error;
114     }
115 
116     return AWS_OP_SUCCESS;
117 error:
118     aws_tls_ctx_options_clean_up(options);
119     return AWS_OP_ERR;
120 }
121 
122 #    if defined(__APPLE__)
aws_tls_ctx_options_set_keychain_path(struct aws_tls_ctx_options * options,struct aws_byte_cursor * keychain_path_cursor)123 int aws_tls_ctx_options_set_keychain_path(
124     struct aws_tls_ctx_options *options,
125     struct aws_byte_cursor *keychain_path_cursor) {
126     options->keychain_path = aws_string_new_from_cursor(options->allocator, keychain_path_cursor);
127     if (!options->keychain_path) {
128         return AWS_OP_ERR;
129     }
130 
131     return AWS_OP_SUCCESS;
132 }
133 #    endif /* __APPLE__ */
134 
135 #endif /* !AWS_OS_IOS */
136 
137 #ifdef _WIN32
aws_tls_ctx_options_init_client_mtls_from_system_path(struct aws_tls_ctx_options * options,struct aws_allocator * allocator,const char * cert_reg_path)138 void aws_tls_ctx_options_init_client_mtls_from_system_path(
139     struct aws_tls_ctx_options *options,
140     struct aws_allocator *allocator,
141     const char *cert_reg_path) {
142     AWS_ZERO_STRUCT(*options);
143     options->minimum_tls_version = AWS_IO_TLS_VER_SYS_DEFAULTS;
144     options->verify_peer = true;
145     options->allocator = allocator;
146     options->max_fragment_size = g_aws_channel_max_fragment_size;
147     options->system_certificate_path = cert_reg_path;
148 }
149 
aws_tls_ctx_options_init_default_server_from_system_path(struct aws_tls_ctx_options * options,struct aws_allocator * allocator,const char * cert_reg_path)150 void aws_tls_ctx_options_init_default_server_from_system_path(
151     struct aws_tls_ctx_options *options,
152     struct aws_allocator *allocator,
153     const char *cert_reg_path) {
154     aws_tls_ctx_options_init_client_mtls_from_system_path(options, allocator, cert_reg_path);
155     options->verify_peer = false;
156 }
157 #endif /* _WIN32 */
158 
159 #ifdef __APPLE__
aws_tls_ctx_options_init_client_mtls_pkcs12_from_path(struct aws_tls_ctx_options * options,struct aws_allocator * allocator,const char * pkcs12_path,struct aws_byte_cursor * pkcs_pwd)160 int aws_tls_ctx_options_init_client_mtls_pkcs12_from_path(
161     struct aws_tls_ctx_options *options,
162     struct aws_allocator *allocator,
163     const char *pkcs12_path,
164     struct aws_byte_cursor *pkcs_pwd) {
165     AWS_ZERO_STRUCT(*options);
166     options->minimum_tls_version = AWS_IO_TLS_VER_SYS_DEFAULTS;
167     options->verify_peer = true;
168     options->allocator = allocator;
169     options->max_fragment_size = g_aws_channel_max_fragment_size;
170 
171     if (aws_byte_buf_init_from_file(&options->pkcs12, allocator, pkcs12_path)) {
172         return AWS_OP_ERR;
173     }
174 
175     if (aws_byte_buf_init_copy_from_cursor(&options->pkcs12_password, allocator, *pkcs_pwd)) {
176         aws_byte_buf_clean_up_secure(&options->pkcs12);
177         return AWS_OP_ERR;
178     }
179 
180     return AWS_OP_SUCCESS;
181 }
182 
aws_tls_ctx_options_init_client_mtls_pkcs12(struct aws_tls_ctx_options * options,struct aws_allocator * allocator,struct aws_byte_cursor * pkcs12,struct aws_byte_cursor * pkcs_pwd)183 int aws_tls_ctx_options_init_client_mtls_pkcs12(
184     struct aws_tls_ctx_options *options,
185     struct aws_allocator *allocator,
186     struct aws_byte_cursor *pkcs12,
187     struct aws_byte_cursor *pkcs_pwd) {
188     AWS_ZERO_STRUCT(*options);
189     options->minimum_tls_version = AWS_IO_TLS_VER_SYS_DEFAULTS;
190     options->verify_peer = true;
191     options->allocator = allocator;
192     options->max_fragment_size = g_aws_channel_max_fragment_size;
193 
194     if (aws_byte_buf_init_copy_from_cursor(&options->pkcs12, allocator, *pkcs12)) {
195         return AWS_OP_ERR;
196     }
197 
198     if (aws_byte_buf_init_copy_from_cursor(&options->pkcs12_password, allocator, *pkcs_pwd)) {
199         aws_byte_buf_clean_up_secure(&options->pkcs12);
200         return AWS_OP_ERR;
201     }
202 
203     return AWS_OP_SUCCESS;
204 }
205 
aws_tls_ctx_options_init_server_pkcs12_from_path(struct aws_tls_ctx_options * options,struct aws_allocator * allocator,const char * pkcs12_path,struct aws_byte_cursor * pkcs_password)206 int aws_tls_ctx_options_init_server_pkcs12_from_path(
207     struct aws_tls_ctx_options *options,
208     struct aws_allocator *allocator,
209     const char *pkcs12_path,
210     struct aws_byte_cursor *pkcs_password) {
211     if (aws_tls_ctx_options_init_client_mtls_pkcs12_from_path(options, allocator, pkcs12_path, pkcs_password)) {
212         return AWS_OP_ERR;
213     }
214 
215     options->verify_peer = false;
216     return AWS_OP_SUCCESS;
217 }
218 
aws_tls_ctx_options_init_server_pkcs12(struct aws_tls_ctx_options * options,struct aws_allocator * allocator,struct aws_byte_cursor * pkcs12,struct aws_byte_cursor * pkcs_password)219 int aws_tls_ctx_options_init_server_pkcs12(
220     struct aws_tls_ctx_options *options,
221     struct aws_allocator *allocator,
222     struct aws_byte_cursor *pkcs12,
223     struct aws_byte_cursor *pkcs_password) {
224     if (aws_tls_ctx_options_init_client_mtls_pkcs12(options, allocator, pkcs12, pkcs_password)) {
225         return AWS_OP_ERR;
226     }
227 
228     options->verify_peer = false;
229     return AWS_OP_SUCCESS;
230 }
231 
232 #endif /* __APPLE__ */
233 
234 #if !defined(AWS_OS_IOS)
235 
aws_tls_ctx_options_init_default_server_from_path(struct aws_tls_ctx_options * options,struct aws_allocator * allocator,const char * cert_path,const char * pkey_path)236 int aws_tls_ctx_options_init_default_server_from_path(
237     struct aws_tls_ctx_options *options,
238     struct aws_allocator *allocator,
239     const char *cert_path,
240     const char *pkey_path) {
241     if (aws_tls_ctx_options_init_client_mtls_from_path(options, allocator, cert_path, pkey_path)) {
242         return AWS_OP_ERR;
243     }
244 
245     options->verify_peer = false;
246     return AWS_OP_SUCCESS;
247 }
248 
aws_tls_ctx_options_init_default_server(struct aws_tls_ctx_options * options,struct aws_allocator * allocator,struct aws_byte_cursor * cert,struct aws_byte_cursor * pkey)249 int aws_tls_ctx_options_init_default_server(
250     struct aws_tls_ctx_options *options,
251     struct aws_allocator *allocator,
252     struct aws_byte_cursor *cert,
253     struct aws_byte_cursor *pkey) {
254     if (aws_tls_ctx_options_init_client_mtls(options, allocator, cert, pkey)) {
255         return AWS_OP_ERR;
256     }
257 
258     options->verify_peer = false;
259     return AWS_OP_SUCCESS;
260 }
261 
262 #endif /* AWS_OS_IOS */
263 
aws_tls_ctx_options_set_alpn_list(struct aws_tls_ctx_options * options,const char * alpn_list)264 int aws_tls_ctx_options_set_alpn_list(struct aws_tls_ctx_options *options, const char *alpn_list) {
265     options->alpn_list = aws_string_new_from_c_str(options->allocator, alpn_list);
266     if (!options->alpn_list) {
267         return AWS_OP_ERR;
268     }
269 
270     return AWS_OP_SUCCESS;
271 }
272 
aws_tls_ctx_options_set_verify_peer(struct aws_tls_ctx_options * options,bool verify_peer)273 void aws_tls_ctx_options_set_verify_peer(struct aws_tls_ctx_options *options, bool verify_peer) {
274     options->verify_peer = verify_peer;
275 }
276 
aws_tls_ctx_options_set_minimum_tls_version(struct aws_tls_ctx_options * options,enum aws_tls_versions minimum_tls_version)277 void aws_tls_ctx_options_set_minimum_tls_version(
278     struct aws_tls_ctx_options *options,
279     enum aws_tls_versions minimum_tls_version) {
280     options->minimum_tls_version = minimum_tls_version;
281 }
282 
aws_tls_ctx_options_override_default_trust_store_from_path(struct aws_tls_ctx_options * options,const char * ca_path,const char * ca_file)283 int aws_tls_ctx_options_override_default_trust_store_from_path(
284     struct aws_tls_ctx_options *options,
285     const char *ca_path,
286     const char *ca_file) {
287 
288     /* Note: on success these are not cleaned up, their data is "moved" into the options struct */
289     struct aws_string *ca_path_tmp = NULL;
290     struct aws_byte_buf ca_file_tmp;
291     AWS_ZERO_STRUCT(ca_file_tmp);
292 
293     if (ca_path) {
294         if (options->ca_path) {
295             AWS_LOGF_ERROR(AWS_LS_IO_TLS, "static: cannot override trust store multiple times");
296             aws_raise_error(AWS_ERROR_INVALID_STATE);
297             goto error;
298         }
299 
300         ca_path_tmp = aws_string_new_from_c_str(options->allocator, ca_path);
301         if (!ca_path_tmp) {
302             goto error;
303         }
304     }
305 
306     if (ca_file) {
307         if (aws_tls_options_buf_is_set(&options->ca_file)) {
308             AWS_LOGF_ERROR(AWS_LS_IO_TLS, "static: cannot override trust store multiple times");
309             aws_raise_error(AWS_ERROR_INVALID_STATE);
310             goto error;
311         }
312 
313         if (aws_byte_buf_init_from_file(&ca_file_tmp, options->allocator, ca_file)) {
314             goto error;
315         }
316 
317         if (aws_sanitize_pem(&ca_file_tmp, options->allocator)) {
318             AWS_LOGF_ERROR(AWS_LS_IO_TLS, "static: Invalid CA file. File must contain PEM encoded data");
319             goto error;
320         }
321     }
322 
323     /* Success, set new values. (no need to clean up old values, we checked earlier that they were unallocated) */
324     if (ca_path) {
325         options->ca_path = ca_path_tmp;
326     }
327     if (ca_file) {
328         options->ca_file = ca_file_tmp;
329     }
330     return AWS_OP_SUCCESS;
331 
332 error:
333     aws_string_destroy_secure(ca_path_tmp);
334     aws_byte_buf_clean_up_secure(&ca_file_tmp);
335     return AWS_OP_ERR;
336 }
337 
aws_tls_ctx_options_set_extension_data(struct aws_tls_ctx_options * options,void * extension_data)338 void aws_tls_ctx_options_set_extension_data(struct aws_tls_ctx_options *options, void *extension_data) {
339     options->ctx_options_extension = extension_data;
340 }
341 
aws_tls_ctx_options_override_default_trust_store(struct aws_tls_ctx_options * options,const struct aws_byte_cursor * ca_file)342 int aws_tls_ctx_options_override_default_trust_store(
343     struct aws_tls_ctx_options *options,
344     const struct aws_byte_cursor *ca_file) {
345 
346     if (aws_tls_options_buf_is_set(&options->ca_file)) {
347         AWS_LOGF_ERROR(AWS_LS_IO_TLS, "static: cannot override trust store multiple times");
348         return aws_raise_error(AWS_ERROR_INVALID_STATE);
349     }
350 
351     if (aws_byte_buf_init_copy_from_cursor(&options->ca_file, options->allocator, *ca_file)) {
352         goto error;
353     }
354 
355     if (aws_sanitize_pem(&options->ca_file, options->allocator)) {
356         AWS_LOGF_ERROR(AWS_LS_IO_TLS, "static: Invalid CA file. File must contain PEM encoded data");
357         goto error;
358     }
359 
360     return AWS_OP_SUCCESS;
361 
362 error:
363     aws_byte_buf_clean_up_secure(&options->ca_file);
364     return AWS_OP_ERR;
365 }
366 
aws_tls_connection_options_init_from_ctx(struct aws_tls_connection_options * conn_options,struct aws_tls_ctx * ctx)367 void aws_tls_connection_options_init_from_ctx(
368     struct aws_tls_connection_options *conn_options,
369     struct aws_tls_ctx *ctx) {
370     AWS_ZERO_STRUCT(*conn_options);
371     /* the assumption here, is that if it was set in the context, we WANT it to be NULL here unless it's different.
372      * so only set verify peer at this point. */
373     conn_options->ctx = aws_tls_ctx_acquire(ctx);
374 
375     conn_options->timeout_ms = AWS_DEFAULT_TLS_TIMEOUT_MS;
376 }
377 
aws_tls_connection_options_copy(struct aws_tls_connection_options * to,const struct aws_tls_connection_options * from)378 int aws_tls_connection_options_copy(
379     struct aws_tls_connection_options *to,
380     const struct aws_tls_connection_options *from) {
381     /* copy everything copyable over, then override the rest with deep copies. */
382     *to = *from;
383 
384     to->ctx = aws_tls_ctx_acquire(from->ctx);
385 
386     if (from->alpn_list) {
387         to->alpn_list = aws_string_new_from_string(from->alpn_list->allocator, from->alpn_list);
388 
389         if (!to->alpn_list) {
390             return AWS_OP_ERR;
391         }
392     }
393 
394     if (from->server_name) {
395         to->server_name = aws_string_new_from_string(from->server_name->allocator, from->server_name);
396 
397         if (!to->server_name) {
398             aws_string_destroy(to->server_name);
399             return AWS_OP_ERR;
400         }
401     }
402 
403     return AWS_OP_SUCCESS;
404 }
405 
aws_tls_connection_options_clean_up(struct aws_tls_connection_options * connection_options)406 void aws_tls_connection_options_clean_up(struct aws_tls_connection_options *connection_options) {
407     aws_tls_ctx_release(connection_options->ctx);
408 
409     if (connection_options->alpn_list) {
410         aws_string_destroy(connection_options->alpn_list);
411     }
412 
413     if (connection_options->server_name) {
414         aws_string_destroy(connection_options->server_name);
415     }
416 
417     AWS_ZERO_STRUCT(*connection_options);
418 }
419 
aws_tls_connection_options_set_callbacks(struct aws_tls_connection_options * conn_options,aws_tls_on_negotiation_result_fn * on_negotiation_result,aws_tls_on_data_read_fn * on_data_read,aws_tls_on_error_fn * on_error,void * user_data)420 void aws_tls_connection_options_set_callbacks(
421     struct aws_tls_connection_options *conn_options,
422     aws_tls_on_negotiation_result_fn *on_negotiation_result,
423     aws_tls_on_data_read_fn *on_data_read,
424     aws_tls_on_error_fn *on_error,
425     void *user_data) {
426     conn_options->on_negotiation_result = on_negotiation_result;
427     conn_options->on_data_read = on_data_read;
428     conn_options->on_error = on_error;
429     conn_options->user_data = user_data;
430 }
431 
aws_tls_connection_options_set_server_name(struct aws_tls_connection_options * conn_options,struct aws_allocator * allocator,struct aws_byte_cursor * server_name)432 int aws_tls_connection_options_set_server_name(
433     struct aws_tls_connection_options *conn_options,
434     struct aws_allocator *allocator,
435     struct aws_byte_cursor *server_name) {
436 
437     if (conn_options->server_name != NULL) {
438         aws_string_destroy(conn_options->server_name);
439         conn_options->server_name = NULL;
440     }
441 
442     conn_options->server_name = aws_string_new_from_cursor(allocator, server_name);
443     if (!conn_options->server_name) {
444         return AWS_OP_ERR;
445     }
446 
447     return AWS_OP_SUCCESS;
448 }
449 
aws_tls_connection_options_set_alpn_list(struct aws_tls_connection_options * conn_options,struct aws_allocator * allocator,const char * alpn_list)450 int aws_tls_connection_options_set_alpn_list(
451     struct aws_tls_connection_options *conn_options,
452     struct aws_allocator *allocator,
453     const char *alpn_list) {
454 
455     if (conn_options->alpn_list != NULL) {
456         aws_string_destroy(conn_options->alpn_list);
457         conn_options->alpn_list = NULL;
458     }
459 
460     conn_options->alpn_list = aws_string_new_from_c_str(allocator, alpn_list);
461     if (!conn_options->alpn_list) {
462         return AWS_OP_ERR;
463     }
464 
465     return AWS_OP_SUCCESS;
466 }
467 
468 #ifdef BYO_CRYPTO
469 
aws_tls_server_ctx_new(struct aws_allocator * alloc,const struct aws_tls_ctx_options * options)470 struct aws_tls_ctx *aws_tls_server_ctx_new(struct aws_allocator *alloc, const struct aws_tls_ctx_options *options) {
471     (void)alloc;
472     (void)options;
473     AWS_FATAL_ASSERT(
474         false &&
475         "When using BYO_CRYPTO, user is responsible for creating aws_tls_ctx manually. You cannot call this function.");
476 }
477 
aws_tls_client_ctx_new(struct aws_allocator * alloc,const struct aws_tls_ctx_options * options)478 struct aws_tls_ctx *aws_tls_client_ctx_new(struct aws_allocator *alloc, const struct aws_tls_ctx_options *options) {
479     (void)alloc;
480     (void)options;
481     AWS_FATAL_ASSERT(
482         false &&
483         "When using BYO_CRYPTO, user is responsible for creating aws_tls_ctx manually. You cannot call this function.");
484 }
485 
486 static aws_tls_handler_new_fn *s_client_handler_new = NULL;
487 static aws_tls_client_handler_start_negotiation_fn *s_start_negotiation_fn = NULL;
488 static void *s_client_user_data = NULL;
489 
490 static aws_tls_handler_new_fn *s_server_handler_new = NULL;
491 static void *s_server_user_data = NULL;
492 
aws_tls_client_handler_new(struct aws_allocator * allocator,struct aws_tls_connection_options * options,struct aws_channel_slot * slot)493 struct aws_channel_handler *aws_tls_client_handler_new(
494     struct aws_allocator *allocator,
495     struct aws_tls_connection_options *options,
496     struct aws_channel_slot *slot) {
497     AWS_FATAL_ASSERT(
498         s_client_handler_new &&
499         "For BYO_CRYPTO, you must call aws_tls_client_handler_new_set_callback() with a non-null value.");
500     return s_client_handler_new(allocator, options, slot, s_client_user_data);
501 }
502 
aws_tls_server_handler_new(struct aws_allocator * allocator,struct aws_tls_connection_options * options,struct aws_channel_slot * slot)503 struct aws_channel_handler *aws_tls_server_handler_new(
504     struct aws_allocator *allocator,
505     struct aws_tls_connection_options *options,
506     struct aws_channel_slot *slot) {
507     AWS_FATAL_ASSERT(
508         s_client_handler_new &&
509         "For BYO_CRYPTO, you must call aws_tls_server_handler_new_set_callback() with a non-null value.")
510     return s_server_handler_new(allocator, options, slot, s_server_user_data);
511 }
512 
aws_tls_byo_crypto_set_client_setup_options(const struct aws_tls_byo_crypto_setup_options * options)513 void aws_tls_byo_crypto_set_client_setup_options(const struct aws_tls_byo_crypto_setup_options *options) {
514     AWS_FATAL_ASSERT(options);
515     AWS_FATAL_ASSERT(options->new_handler_fn);
516     AWS_FATAL_ASSERT(options->start_negotiation_fn);
517 
518     s_client_handler_new = options->new_handler_fn;
519     s_start_negotiation_fn = options->start_negotiation_fn;
520     s_client_user_data = options->user_data;
521 }
522 
aws_tls_byo_crypto_set_server_setup_options(const struct aws_tls_byo_crypto_setup_options * options)523 void aws_tls_byo_crypto_set_server_setup_options(const struct aws_tls_byo_crypto_setup_options *options) {
524     AWS_FATAL_ASSERT(options);
525     AWS_FATAL_ASSERT(options->new_handler_fn);
526 
527     s_server_handler_new = options->new_handler_fn;
528     s_server_user_data = options->user_data;
529 }
530 
aws_tls_client_handler_start_negotiation(struct aws_channel_handler * handler)531 int aws_tls_client_handler_start_negotiation(struct aws_channel_handler *handler) {
532     AWS_FATAL_ASSERT(
533         s_start_negotiation_fn &&
534         "For BYO_CRYPTO, you must call aws_tls_client_handler_set_start_negotiation_callback() with a non-null value.")
535     return s_start_negotiation_fn(handler, s_client_user_data);
536 }
537 
aws_tls_init_static_state(struct aws_allocator * alloc)538 void aws_tls_init_static_state(struct aws_allocator *alloc) {
539     (void)alloc;
540 }
541 
aws_tls_clean_up_static_state(void)542 void aws_tls_clean_up_static_state(void) {}
543 
544 #endif /* BYO_CRYPTO */
545 
aws_channel_setup_client_tls(struct aws_channel_slot * right_of_slot,struct aws_tls_connection_options * tls_options)546 int aws_channel_setup_client_tls(
547     struct aws_channel_slot *right_of_slot,
548     struct aws_tls_connection_options *tls_options) {
549 
550     AWS_FATAL_ASSERT(right_of_slot != NULL);
551     struct aws_channel *channel = right_of_slot->channel;
552     struct aws_allocator *allocator = right_of_slot->alloc;
553 
554     struct aws_channel_slot *tls_slot = aws_channel_slot_new(channel);
555 
556     /* as far as cleanup goes, since this stuff is being added to a channel, the caller will free this memory
557        when they clean up the channel. */
558     if (!tls_slot) {
559         return AWS_OP_ERR;
560     }
561 
562     struct aws_channel_handler *tls_handler = aws_tls_client_handler_new(allocator, tls_options, tls_slot);
563     if (!tls_handler) {
564         aws_mem_release(allocator, tls_slot);
565         return AWS_OP_ERR;
566     }
567 
568     /*
569      * From here on out, channel shutdown will handle slot/handler cleanup
570      */
571     aws_channel_slot_insert_right(right_of_slot, tls_slot);
572     AWS_LOGF_TRACE(
573         AWS_LS_IO_CHANNEL,
574         "id=%p: Setting up client TLS with handler %p on slot %p",
575         (void *)channel,
576         (void *)tls_handler,
577         (void *)tls_slot);
578 
579     if (aws_channel_slot_set_handler(tls_slot, tls_handler) != AWS_OP_SUCCESS) {
580         return AWS_OP_ERR;
581     }
582 
583     if (aws_tls_client_handler_start_negotiation(tls_handler) != AWS_OP_SUCCESS) {
584         return AWS_OP_ERR;
585     }
586 
587     return AWS_OP_SUCCESS;
588 }
589 
aws_tls_ctx_acquire(struct aws_tls_ctx * ctx)590 struct aws_tls_ctx *aws_tls_ctx_acquire(struct aws_tls_ctx *ctx) {
591     if (ctx != NULL) {
592         aws_ref_count_acquire(&ctx->ref_count);
593     }
594 
595     return ctx;
596 }
597 
aws_tls_ctx_release(struct aws_tls_ctx * ctx)598 void aws_tls_ctx_release(struct aws_tls_ctx *ctx) {
599     if (ctx != NULL) {
600         aws_ref_count_release(&ctx->ref_count);
601     }
602 }
603