#ifndef AWS_IO_TLS_CHANNEL_HANDLER_H #define AWS_IO_TLS_CHANNEL_HANDLER_H /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ #include #include #include struct aws_channel_slot; struct aws_channel_handler; struct aws_pkcs11_session; struct aws_string; enum aws_tls_versions { AWS_IO_SSLv3, AWS_IO_TLSv1, AWS_IO_TLSv1_1, AWS_IO_TLSv1_2, AWS_IO_TLSv1_3, AWS_IO_TLS_VER_SYS_DEFAULTS = 128, }; enum aws_tls_cipher_pref { AWS_IO_TLS_CIPHER_PREF_SYSTEM_DEFAULT = 0, /* Deprecated */ AWS_IO_TLS_CIPHER_PREF_KMS_PQ_TLSv1_0_2019_06 = 1, /* Deprecated */ AWS_IO_TLS_CIPHER_PREF_KMS_PQ_SIKE_TLSv1_0_2019_11 = 2, /* Deprecated */ AWS_IO_TLS_CIPHER_PREF_KMS_PQ_TLSv1_0_2020_02 = 3, /* Deprecated */ AWS_IO_TLS_CIPHER_PREF_KMS_PQ_SIKE_TLSv1_0_2020_02 = 4, /* Deprecated */ AWS_IO_TLS_CIPHER_PREF_KMS_PQ_TLSv1_0_2020_07 = 5, /* * This TLS cipher preference list contains post-quantum key exchange algorithms that have been submitted to NIST * for potential future standardization. Support for this preference list, or PQ algorithms present in it, may be * removed at any time in the future. PQ algorithms in this preference list will be used in hybrid mode, and always * combined with a classical ECDHE key exchange. */ AWS_IO_TLS_CIPHER_PREF_PQ_TLSv1_0_2021_05 = 6, AWS_IO_TLS_CIPHER_PREF_END_RANGE = 0xFFFF }; /** * The hash algorithm of a TLS private key operation. Any custom private key operation handlers are expected to perform * operations on the input TLS data using the correct hash algorithm or fail the operation. */ enum aws_tls_hash_algorithm { AWS_TLS_HASH_UNKNOWN, AWS_TLS_HASH_SHA1, AWS_TLS_HASH_SHA224, AWS_TLS_HASH_SHA256, AWS_TLS_HASH_SHA384, AWS_TLS_HASH_SHA512, }; /** * The signature of a TLS private key operation. Any custom private key operation handlers are expected to perform * operations on the input TLS data using the correct signature algorithm or fail the operation. */ enum aws_tls_signature_algorithm { AWS_TLS_SIGNATURE_UNKNOWN, AWS_TLS_SIGNATURE_RSA, AWS_TLS_SIGNATURE_ECDSA, }; /** * The TLS private key operation that needs to be performed by a custom private key operation handler when making * a connection using mutual TLS. */ enum aws_tls_key_operation_type { AWS_TLS_KEY_OPERATION_UNKNOWN, AWS_TLS_KEY_OPERATION_SIGN, AWS_TLS_KEY_OPERATION_DECRYPT, }; struct aws_tls_ctx { struct aws_allocator *alloc; void *impl; struct aws_ref_count ref_count; }; /** * Invoked upon completion of the TLS handshake. If successful error_code will be AWS_OP_SUCCESS, otherwise * the negotiation failed and immediately after this function is invoked, the channel will be shutting down. */ typedef void(aws_tls_on_negotiation_result_fn)( struct aws_channel_handler *handler, struct aws_channel_slot *slot, int error_code, void *user_data); /** * Only used if the TLS handler is the last handler in the channel. This allows you to read any data that * was read and decrypted by the handler. If you have application protocol channel handlers, this function * is not necessary and certainly not recommended. */ typedef void(aws_tls_on_data_read_fn)( struct aws_channel_handler *handler, struct aws_channel_slot *slot, struct aws_byte_buf *buffer, void *user_data); /** * Invoked when an error occurs in the TLS state machine AFTER the handshake has completed. This function should only * be used in conjunction with the rules of aws_tls_on_data_read_fn. */ typedef void(aws_tls_on_error_fn)( struct aws_channel_handler *handler, struct aws_channel_slot *slot, int err, const char *message, void *user_data); struct aws_tls_connection_options { /** semi-colon delimited list of protocols. Example: * h2;http/1.1 */ struct aws_string *alpn_list; /** * Serves two purposes. If SNI is supported (hint... it is), * this sets the SNI extension. * * For X.509 validation this also sets the name that will be used * for verifying the subj alt name and common name of the peer's certificate. */ struct aws_string *server_name; 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; struct aws_tls_ctx *ctx; bool advertise_alpn_message; uint32_t timeout_ms; }; /** * A struct containing all of the data needed for a private key operation when * making a mutual TLS connection. This struct contains the data that needs * to be operated on, like performing a sign operation or a decrypt operation. */ struct aws_tls_key_operation; struct aws_tls_ctx_options { struct aws_allocator *allocator; /** * minimum tls version to use. If you just want us to use the * system defaults, you can set: AWS_IO_TLS_VER_SYS_DEFAULTS. This * has the added benefit of automatically picking up new TLS versions * as your OS or distribution adds support. */ enum aws_tls_versions minimum_tls_version; /** * The Cipher Preference List to use */ enum aws_tls_cipher_pref cipher_pref; /** * A PEM armored PKCS#7 collection of CAs you want to trust as a string. * Only use this if it's a CA not currently installed on your system. */ struct aws_byte_buf ca_file; /** * Only used on Unix systems using an openssl style trust API. * this is typically something like /etc/pki/tls/certs/" */ struct aws_string *ca_path; /** * Sets ctx wide alpn string. This is most useful for servers. * This is a semi-colon delimited list. example: * h2;http/1.1 */ struct aws_string *alpn_list; /** * A PEM armored PKCS#7 certificate as a string. * It is supported on every operating system. */ struct aws_byte_buf certificate; #ifdef _WIN32 /** The path to a system * installed certficate/private key pair. Example: * CurrentUser\\MY\\ */ const char *system_certificate_path; #endif /** * A PEM armored PKCS#7 private key as a string. * * On windows, this field should be NULL only if you are * using a system installed certficate. */ struct aws_byte_buf private_key; #ifdef __APPLE__ /** * Apple Only! * * On Apple OS you can also use a pkcs#12 for your certificate * and private key. This is the contents the certificate. */ struct aws_byte_buf pkcs12; /** * Password for the pkcs12 data in pkcs12. */ struct aws_byte_buf pkcs12_password; # if !defined(AWS_OS_IOS) /** * On Apple OS you can also use a custom keychain instead of * the default keychain of the account. */ struct aws_string *keychain_path; # endif #endif /** max tls fragment size. Default is the value of g_aws_channel_max_fragment_size. */ size_t max_fragment_size; /** * default is true for clients and false for servers. * You should not change this default for clients unless * you're testing and don't want to fool around with CA trust stores. * Before you release to production, you'll want to turn this back on * and add your custom CA to the aws_tls_ctx_options. * * If you set this in server mode, it enforces client authentication. */ bool verify_peer; /** * For use when adding BYO_CRYPTO implementations. You can set extra data in here for use with your TLS * implementation. */ void *ctx_options_extension; /** * Set if using custom private key operations. * See aws_custom_key_op_handler for more details * * Note: Custom key operations (and PKCS#11 integration) hasn't been tested with TLS 1.3, so don't use * cipher preferences that allow TLS 1.3. If this is set, we will always use non TLS 1.3 preferences. */ struct aws_custom_key_op_handler *custom_key_op_handler; }; struct aws_tls_negotiated_protocol_message { struct aws_byte_buf protocol; }; static const int AWS_TLS_NEGOTIATED_PROTOCOL_MESSAGE = 0x01; typedef struct aws_channel_handler *( *aws_tls_on_protocol_negotiated)(struct aws_channel_slot *new_slot, struct aws_byte_buf *protocol, void *user_data); /** * An enum for the current state of tls negotiation within a tls channel handler */ enum aws_tls_negotiation_status { AWS_TLS_NEGOTIATION_STATUS_NONE, AWS_TLS_NEGOTIATION_STATUS_ONGOING, AWS_TLS_NEGOTIATION_STATUS_SUCCESS, AWS_TLS_NEGOTIATION_STATUS_FAILURE }; #ifdef BYO_CRYPTO /** * Callback for creating a TLS handler. If you're using this you're using BYO_CRYPTO. This function should return * a fully implemented aws_channel_handler instance for TLS. Note: the aws_tls_options passed to your * aws_tls_handler_new_fn contains multiple callbacks. Namely: aws_tls_on_negotiation_result_fn. You are responsible for * invoking this function when TLs session negotiation has completed. */ typedef struct aws_channel_handler *(aws_tls_handler_new_fn)( struct aws_allocator *allocator, struct aws_tls_connection_options *options, struct aws_channel_slot *slot, void *user_data); /** * Invoked when it's time to start TLS negotiation. Note: the aws_tls_options passed to your aws_tls_handler_new_fn * contains multiple callbacks. Namely: aws_tls_on_negotiation_result_fn. You are responsible for invoking this function * when TLS session negotiation has completed. */ typedef int(aws_tls_client_handler_start_negotiation_fn)(struct aws_channel_handler *handler, void *user_data); struct aws_tls_byo_crypto_setup_options { aws_tls_handler_new_fn *new_handler_fn; /* ignored for server implementations, required for clients. */ aws_tls_client_handler_start_negotiation_fn *start_negotiation_fn; void *user_data; }; #endif /* BYO_CRYPTO */ AWS_EXTERN_C_BEGIN /******************************** tls options init stuff ***********************/ /** * Initializes options with default client options */ AWS_IO_API void aws_tls_ctx_options_init_default_client( struct aws_tls_ctx_options *options, struct aws_allocator *allocator); /** * Cleans up resources allocated by init_* functions */ AWS_IO_API void aws_tls_ctx_options_clean_up(struct aws_tls_ctx_options *options); /** * Initializes options for use with mutual tls in client mode. * cert_path and pkey_path are paths to files on disk. cert_path * and pkey_path are treated as PKCS#7 PEM armored. They are loaded * from disk and stored in buffers internally. * * NOTE: This is unsupported on iOS. */ AWS_IO_API int 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); /** * Initializes options for use with mutual tls in client mode. * cert and pkey are copied. cert and pkey are treated as PKCS#7 PEM * armored. * * NOTE: This is unsupported on iOS. */ AWS_IO_API int 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); /** * vtable for aws_custom_key_op_handler. */ struct aws_custom_key_op_handler_vtable { /** * Called when the a TLS handshake has an operation it needs the custom key operation handler to perform. * NOTE: You must call aws_tls_key_operation_complete() or aws_tls_key_operation_complete_with_error() * otherwise the TLS handshake will stall the TLS connection indefinitely and leak memory. */ void (*on_key_operation)(struct aws_custom_key_op_handler *key_op_handler, struct aws_tls_key_operation *operation); }; /** * The custom key operation that is used when performing a mutual TLS handshake. This can * be extended to provide custom private key operations, like PKCS11 or similar. */ struct aws_custom_key_op_handler { /** * A void* intended to be populated with a reference to whatever class is extending this class. For example, * if you have extended aws_custom_key_op_handler with a custom struct, you would put a pointer to this struct * to *impl so you can retrieve it back in the vtable functions. */ void *impl; /** * A vtable containing all of the functions the aws_custom_key_op_handler implements. Is intended to be extended. * NOTE: Use "aws_custom_key_op_handler_" to access vtable functions. */ const struct aws_custom_key_op_handler_vtable *vtable; /** * A reference count for handling memory usage. * Use aws_custom_key_op_handler_acquire and aws_custom_key_op_handler_release to increase/decrease count. */ struct aws_ref_count ref_count; }; /** * Increases the reference count for the passed-in aws_custom_key_op_handler and returns it. */ AWS_IO_API struct aws_custom_key_op_handler *aws_custom_key_op_handler_acquire( struct aws_custom_key_op_handler *key_op_handler); /** * Decreases the reference count for the passed-in aws_custom_key_op_handler and returns NULL. */ AWS_IO_API struct aws_custom_key_op_handler *aws_custom_key_op_handler_release( struct aws_custom_key_op_handler *key_op_handler); /** * Calls the on_key_operation vtable function. See aws_custom_key_op_handler_vtable for function details. */ AWS_IO_API void aws_custom_key_op_handler_perform_operation( struct aws_custom_key_op_handler *key_op_handler, struct aws_tls_key_operation *operation); /** * Initializes options for use with mutual TLS in client mode, * where private key operations are handled by custom code. * * Note: cert_file_contents will be copied into a new buffer after this * function is called, so you do not need to keep that data alive * after calling this function. * * @param options aws_tls_ctx_options to be initialized. * @param allocator Allocator to use. * @param custom Options for custom key operations. * @param cert_file_contents The contents of a certificate file. */ AWS_IO_API int aws_tls_ctx_options_init_client_mtls_with_custom_key_operations( struct aws_tls_ctx_options *options, struct aws_allocator *allocator, struct aws_custom_key_op_handler *custom, const struct aws_byte_cursor *cert_file_contents); /** * This struct exists as a graceful way to pass many arguments when * calling init-with-pkcs11 functions on aws_tls_ctx_options (this also makes * it easy to introduce optional arguments in the future). * Instances of this struct should only exist briefly on the stack. * * Instructions for binding this to high-level languages: * - Python: The members of this struct should be the keyword args to the init-with-pkcs11 functions. * - JavaScript: This should be an options map passed to init-with-pkcs11 functions. * - Java: This should be an options class passed to init-with-pkcs11 functions. * - C++: Same as Java * * Notes on integer types: * PKCS#11 uses `unsigned long` for IDs, handles, etc but we expose them as `uint64_t` in public APIs. * We do this because sizeof(long) is inconsistent across platform/arch/language * (ex: always 64bit in Java, always 32bit in C on Windows, matches CPU in C on Linux and Apple). * By using uint64_t in our public API, we can keep the careful bounds-checking all in one * place, instead of expecting each high-level language binding to get it just right. */ struct aws_tls_ctx_pkcs11_options { /** * The PKCS#11 library to use. * This field is required. */ struct aws_pkcs11_lib *pkcs11_lib; /** * User PIN, for logging into the PKCS#11 token (UTF-8). * Zero out to log into a token with a "protected authentication path". */ struct aws_byte_cursor user_pin; /** * ID of slot containing PKCS#11 token. * If set to NULL, the token will be chosen based on other criteria * (such as token label). */ const uint64_t *slot_id; /** * Label of PKCS#11 token to use. * If zeroed out, the token will be chosen based on other criteria * (such as slot ID). */ struct aws_byte_cursor token_label; /** * Label of private key object on PKCS#11 token (UTF-8). * If zeroed out, the private key will be chosen based on other criteria * (such as being the only available private key on the token). */ struct aws_byte_cursor private_key_object_label; /** * Certificate's file path on disk (UTF-8). * The certificate must be PEM formatted and UTF-8 encoded. * Zero out if passing in certificate by some other means (such as file contents). */ struct aws_byte_cursor cert_file_path; /** * Certificate's file contents (UTF-8). * The certificate must be PEM formatted and UTF-8 encoded. * Zero out if passing in certificate by some other means (such as file path). */ struct aws_byte_cursor cert_file_contents; }; /** * Initializes options for use with mutual TLS in client mode, * where a PKCS#11 library provides access to the private key. * * NOTE: This only works on Unix devices. * * @param options aws_tls_ctx_options to be initialized. * @param allocator Allocator to use. * @param pkcs11_options Options for using PKCS#11 (contents are copied) */ AWS_IO_API int aws_tls_ctx_options_init_client_mtls_with_pkcs11( struct aws_tls_ctx_options *options, struct aws_allocator *allocator, const struct aws_tls_ctx_pkcs11_options *pkcs11_options); /** * @Deprecated * * Sets a custom keychain path for storing the cert and pkey with mutual tls in client mode. * * NOTE: This only works on MacOS. */ AWS_IO_API int aws_tls_ctx_options_set_keychain_path( struct aws_tls_ctx_options *options, struct aws_byte_cursor *keychain_path_cursor); /** * Initializes options for use with in server mode. * cert_path and pkey_path are paths to files on disk. cert_path * and pkey_path are treated as PKCS#7 PEM armored. They are loaded * from disk and stored in buffers internally. */ AWS_IO_API int 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); /** * Initializes options for use with in server mode. * cert and pkey are copied. cert and pkey are treated as PKCS#7 PEM * armored. */ AWS_IO_API int 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); /** * Initializes options for use with mutual tls in client mode. * cert_reg_path is the path to a system * installed certficate/private key pair. Example: * CurrentUser\\MY\\ * * NOTE: This only works on Windows. */ AWS_IO_API int 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); /** * Initializes options for use with server mode. * cert_reg_path is the path to a system * installed certficate/private key pair. Example: * CurrentUser\\MY\\ * * NOTE: This only works on Windows. */ AWS_IO_API int 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); /** * Initializes options for use with mutual tls in client mode. * pkcs12_path is a path to a file on disk containing a pkcs#12 file. The file is loaded * into an internal buffer. pkcs_pwd is the corresponding password for the pkcs#12 file; it is copied. * * NOTE: This only works on Apple devices. */ AWS_IO_API int aws_tls_ctx_options_init_client_mtls_pkcs12_from_path( struct aws_tls_ctx_options *options, struct aws_allocator *allocator, const char *pkcs12_path, const struct aws_byte_cursor *pkcs_pwd); /** * Initializes options for use with mutual tls in client mode. * pkcs12 is a buffer containing a pkcs#12 certificate and private key; it is copied. * pkcs_pwd is the corresponding password for the pkcs#12 buffer; it is copied. * * NOTE: This only works on Apple devices. */ AWS_IO_API int 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); /** * Initializes options for use in server mode. * pkcs12_path is a path to a file on disk containing a pkcs#12 file. The file is loaded * into an internal buffer. pkcs_pwd is the corresponding password for the pkcs#12 file; it is copied. * * NOTE: This only works on Apple devices. */ AWS_IO_API int 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); /** * Initializes options for use in server mode. * pkcs12 is a buffer containing a pkcs#12 certificate and private key; it is copied. * pkcs_pwd is the corresponding password for the pkcs#12 buffer; it is copied. * * NOTE: This only works on Apple devices. */ AWS_IO_API int 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); /** * Sets alpn list in the form . A maximum of 4 protocols are supported. * alpn_list is copied. */ AWS_IO_API int aws_tls_ctx_options_set_alpn_list(struct aws_tls_ctx_options *options, const char *alpn_list); /** * Enables or disables x.509 validation. Disable this only for testing. To enable mutual TLS in server mode, * set verify_peer to true. */ AWS_IO_API void aws_tls_ctx_options_set_verify_peer(struct aws_tls_ctx_options *options, bool verify_peer); /** * Sets the minimum TLS version to allow. */ AWS_IO_API void aws_tls_ctx_options_set_minimum_tls_version( struct aws_tls_ctx_options *options, enum aws_tls_versions minimum_tls_version); /** * Override the default trust store. ca_file is a buffer containing a PEM armored chain of trusted CA certificates. * ca_file is copied. */ AWS_IO_API int aws_tls_ctx_options_override_default_trust_store( struct aws_tls_ctx_options *options, const struct aws_byte_cursor *ca_file); /** * Override the default trust store. ca_path is a path to a directory on disk containing trusted certificates. This is * only supported on Unix systems (otherwise this parameter is ignored). ca_file is a path to a file on disk containing * trusted certificates. ca_file is loaded from disk and stored in an internal buffer. */ AWS_IO_API int aws_tls_ctx_options_override_default_trust_store_from_path( struct aws_tls_ctx_options *options, const char *ca_path, const char *ca_file); /** * When implementing BYO_CRYPTO, if you need extra data to pass to your tls implementation, set it here. The lifetime of * extension_data must outlive the options object and be cleaned up after options is cleaned up. */ AWS_IO_API void aws_tls_ctx_options_set_extension_data(struct aws_tls_ctx_options *options, void *extension_data); /** * Initializes default connection options from an instance ot aws_tls_ctx. */ AWS_IO_API void aws_tls_connection_options_init_from_ctx( struct aws_tls_connection_options *conn_options, struct aws_tls_ctx *ctx); /** * Cleans up resources in aws_tls_connection_options. This can be called immediately after initializing * a tls handler, or if using the bootstrap api, immediately after asking for a channel. */ AWS_IO_API void aws_tls_connection_options_clean_up(struct aws_tls_connection_options *connection_options); /** * Copies 'from' to 'to' */ AWS_IO_API int aws_tls_connection_options_copy( struct aws_tls_connection_options *to, const struct aws_tls_connection_options *from); /** * Sets callbacks for use with a tls connection. */ AWS_IO_API void 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); /** * Sets server name to use for the SNI extension (supported everywhere), as well as x.509 validation. If you don't * set this, your x.509 validation will likely fail. */ AWS_IO_API int aws_tls_connection_options_set_server_name( struct aws_tls_connection_options *conn_options, struct aws_allocator *allocator, const struct aws_byte_cursor *server_name); /** * Sets alpn list in the form . A maximum of 4 protocols are supported. * alpn_list is copied. This value is already inherited from aws_tls_ctx, but the aws_tls_ctx is expensive, * and should be used across as many connections as possible. If you want to set this per connection, set it here. */ AWS_IO_API int aws_tls_connection_options_set_alpn_list( struct aws_tls_connection_options *conn_options, struct aws_allocator *allocator, const char *alpn_list); /********************************* TLS context and state management *********************************/ /** * Returns true if alpn is available in the underlying tls implementation. * This function should always be called before setting an alpn list. */ AWS_IO_API bool aws_tls_is_alpn_available(void); /** * Returns true if this Cipher Preference is available in the underlying TLS implementation. * This function should always be called before setting a Cipher Preference */ AWS_IO_API bool aws_tls_is_cipher_pref_supported(enum aws_tls_cipher_pref cipher_pref); /** * Creates a new tls channel handler in client mode. Options will be copied. * You must call aws_tls_client_handler_start_negotiation and wait on the * aws_tls_on_negotiation_result_fn callback before the handler can begin processing * application data. */ AWS_IO_API struct aws_channel_handler *aws_tls_client_handler_new( struct aws_allocator *allocator, struct aws_tls_connection_options *options, struct aws_channel_slot *slot); /** * Creates a new tls channel handler in server mode. Options will be copied. * You must wait on the aws_tls_on_negotiation_result_fn callback before the handler can begin processing * application data. */ AWS_IO_API struct aws_channel_handler *aws_tls_server_handler_new( struct aws_allocator *allocator, struct aws_tls_connection_options *options, struct aws_channel_slot *slot); #ifdef BYO_CRYPTO /** * If using BYO_CRYPTO, you need to call this function prior to creating any client channels in the application. */ AWS_IO_API void aws_tls_byo_crypto_set_client_setup_options(const struct aws_tls_byo_crypto_setup_options *options); /** * If using BYO_CRYPTO, you need to call this function prior to creating any server channels in the application. */ AWS_IO_API void aws_tls_byo_crypto_set_server_setup_options(const struct aws_tls_byo_crypto_setup_options *options); #endif /* BYO_CRYPTO */ /** * Creates a channel handler, for client or server mode, that handles alpn. This isn't necessarily required * since you can always call aws_tls_handler_protocol in the aws_tls_on_negotiation_result_fn callback, but * this makes channel bootstrap easier to handle. */ AWS_IO_API struct aws_channel_handler *aws_tls_alpn_handler_new( struct aws_allocator *allocator, aws_tls_on_protocol_negotiated on_protocol_negotiated, void *user_data); /** * Kicks off the negotiation process. This function must be called when in client mode to initiate the * TLS handshake. Once the handshake has completed the aws_tls_on_negotiation_result_fn will be invoked. */ AWS_IO_API int aws_tls_client_handler_start_negotiation(struct aws_channel_handler *handler); #ifndef BYO_CRYPTO /** * Creates a new server ctx. This ctx can be used for the lifetime of the application assuming you want the same * options for every incoming connection. Options will be copied. */ AWS_IO_API struct aws_tls_ctx *aws_tls_server_ctx_new( struct aws_allocator *alloc, const struct aws_tls_ctx_options *options); /** * Creates a new client ctx. This ctx can be used for the lifetime of the application assuming you want the same * options for every outgoing connection. Options will be copied. */ AWS_IO_API struct aws_tls_ctx *aws_tls_client_ctx_new( struct aws_allocator *alloc, const struct aws_tls_ctx_options *options); #endif /* BYO_CRYPTO */ /** * Increments the reference count on the tls context, allowing the caller to take a reference to it. * * Returns the same tls context passed in. */ AWS_IO_API struct aws_tls_ctx *aws_tls_ctx_acquire(struct aws_tls_ctx *ctx); /** * Decrements a tls context's ref count. When the ref count drops to zero, the object will be destroyed. */ AWS_IO_API void aws_tls_ctx_release(struct aws_tls_ctx *ctx); /** * Not necessary if you are installing more handlers into the channel, but if you just want to have TLS for arbitrary * data and use the channel handler directly, this function allows you to write data to the channel and have it * encrypted. */ AWS_IO_API int aws_tls_handler_write( struct aws_channel_handler *handler, struct aws_channel_slot *slot, struct aws_byte_buf *buf, aws_channel_on_message_write_completed_fn *on_write_completed, void *completion_user_data); /** * Returns a byte buffer by copy of the negotiated protocols. If there is no agreed upon protocol, len will be 0 and * buffer will be NULL. */ AWS_IO_API struct aws_byte_buf aws_tls_handler_protocol(struct aws_channel_handler *handler); /** * Client mode only. This is the server name that was used for SNI and host name validation. */ AWS_IO_API struct aws_byte_buf aws_tls_handler_server_name(struct aws_channel_handler *handler); /**************************** TLS KEY OPERATION *******************************/ /* Note: Currently this assumes the user knows what key is being used for key/cert pairs but s2n supports multiple cert/key pairs. This functionality is not used in the CRT currently, but in the future, we may need to implement this */ /** * Complete a successful TLS private key operation by providing its output. * The output is copied into the TLS connection. * The operation is freed by this call. * * You MUST call this or aws_tls_key_operation_complete_with_error(). * Failure to do so will stall the TLS connection indefinitely and leak memory. */ AWS_IO_API void aws_tls_key_operation_complete(struct aws_tls_key_operation *operation, struct aws_byte_cursor output); /** * Complete an failed TLS private key operation. * The TLS connection will fail. * The operation is freed by this call. * * You MUST call this or aws_tls_key_operation_complete(). * Failure to do so will stall the TLS connection indefinitely and leak memory. */ AWS_IO_API void aws_tls_key_operation_complete_with_error(struct aws_tls_key_operation *operation, int error_code); /** * Returns the input data that needs to be operated on by the custom key operation. */ AWS_IO_API struct aws_byte_cursor aws_tls_key_operation_get_input(const struct aws_tls_key_operation *operation); /** * Returns the type of operation that needs to be performed by the custom key operation. * If the implementation cannot perform the operation, * use aws_tls_key_operation_complete_with_error() to preventing stalling the TLS connection. */ AWS_IO_API enum aws_tls_key_operation_type aws_tls_key_operation_get_type(const struct aws_tls_key_operation *operation); /** * Returns the algorithm the operation is expected to be operated with. * If the implementation does not support the signature algorithm, * use aws_tls_key_operation_complete_with_error() to preventing stalling the TLS connection. */ AWS_IO_API enum aws_tls_signature_algorithm aws_tls_key_operation_get_signature_algorithm( const struct aws_tls_key_operation *operation); /** * Returns the algorithm the operation digest is signed with. * If the implementation does not support the digest algorithm, * use aws_tls_key_operation_complete_with_error() to preventing stalling the TLS connection. */ AWS_IO_API enum aws_tls_hash_algorithm aws_tls_key_operation_get_digest_algorithm(const struct aws_tls_key_operation *operation); /********************************* Misc TLS related *********************************/ /* * Injects a tls handler/slot into a channel and begins tls negotiation. * If desired, ALPN must be handled separately * * right_of_slot must be an existing slot in a channel */ AWS_IO_API int aws_channel_setup_client_tls( struct aws_channel_slot *right_of_slot, struct aws_tls_connection_options *tls_options); /** * Given enum, return string like: AWS_TLS_HASH_SHA256 -> "SHA256" */ AWS_IO_API const char *aws_tls_hash_algorithm_str(enum aws_tls_hash_algorithm hash); /** * Given enum, return string like: AWS_TLS_SIGNATURE_RSA -> "RSA" */ AWS_IO_API const char *aws_tls_signature_algorithm_str(enum aws_tls_signature_algorithm signature); /** * Given enum, return string like: AWS_TLS_SIGNATURE_RSA -> "RSA" */ AWS_IO_API const char *aws_tls_key_operation_type_str(enum aws_tls_key_operation_type operation_type); AWS_EXTERN_C_END #endif /* AWS_IO_TLS_CHANNEL_HANDLER_H */