/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ #pragma once #if ((__GNUC__ >= 4) || defined(__clang__)) && defined(S2N_EXPORTS) # define S2N_API __attribute__((visibility("default"))) #else # define S2N_API #endif /* __GNUC__ >= 4 || defined(__clang__) */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include /* Function return code */ #define S2N_SUCCESS 0 #define S2N_FAILURE -1 /* Callback return code */ #define S2N_CALLBACK_BLOCKED -2 #define S2N_MINIMUM_SUPPORTED_TLS_RECORD_MAJOR_VERSION 2 #define S2N_MAXIMUM_SUPPORTED_TLS_RECORD_MAJOR_VERSION 3 #define S2N_SSLv2 20 #define S2N_SSLv3 30 #define S2N_TLS10 31 #define S2N_TLS11 32 #define S2N_TLS12 33 #define S2N_TLS13 34 #define S2N_UNKNOWN_PROTOCOL_VERSION 0 S2N_API extern __thread int s2n_errno; /** * Returns the address of the thread-local `s2n_errno` variable * * This function can be used instead of trying to resolve `s2n_errno` directly * in runtimes where thread-local variables may not be easily accessible. */ S2N_API extern int *s2n_errno_location(void); typedef enum { S2N_ERR_T_OK=0, S2N_ERR_T_IO, S2N_ERR_T_CLOSED, S2N_ERR_T_BLOCKED, S2N_ERR_T_ALERT, S2N_ERR_T_PROTO, S2N_ERR_T_INTERNAL, S2N_ERR_T_USAGE } s2n_error_type; S2N_API extern int s2n_error_get_type(int error); struct s2n_config; struct s2n_connection; S2N_API extern unsigned long s2n_get_openssl_version(void); S2N_API extern int s2n_init(void); S2N_API extern int s2n_cleanup(void); S2N_API extern struct s2n_config *s2n_config_new(void); S2N_API extern int s2n_config_free(struct s2n_config *config); S2N_API extern int s2n_config_free_dhparams(struct s2n_config *config); S2N_API extern int s2n_config_free_cert_chain_and_key(struct s2n_config *config); typedef int (*s2n_clock_time_nanoseconds) (void *, uint64_t *); typedef int (*s2n_cache_retrieve_callback) (struct s2n_connection *conn, void *, const void *key, uint64_t key_size, void *value, uint64_t *value_size); typedef int (*s2n_cache_store_callback) (struct s2n_connection *conn, void *, uint64_t ttl_in_seconds, const void *key, uint64_t key_size, const void *value, uint64_t value_size); typedef int (*s2n_cache_delete_callback) (struct s2n_connection *conn, void *, const void *key, uint64_t key_size); S2N_API extern int s2n_config_set_wall_clock(struct s2n_config *config, s2n_clock_time_nanoseconds clock_fn, void *ctx); S2N_API extern int s2n_config_set_monotonic_clock(struct s2n_config *config, s2n_clock_time_nanoseconds clock_fn, void *ctx); S2N_API extern const char *s2n_strerror(int error, const char *lang); S2N_API extern const char *s2n_strerror_debug(int error, const char *lang); S2N_API extern const char *s2n_strerror_name(int error); struct s2n_stacktrace; S2N_API extern bool s2n_stack_traces_enabled(void); S2N_API extern int s2n_stack_traces_enabled_set(bool newval); S2N_API extern int s2n_calculate_stacktrace(void); S2N_API extern int s2n_print_stacktrace(FILE *fptr); S2N_API extern int s2n_free_stacktrace(void); S2N_API extern int s2n_get_stacktrace(struct s2n_stacktrace *trace); S2N_API extern int s2n_config_set_cache_store_callback(struct s2n_config *config, s2n_cache_store_callback cache_store_callback, void *data); S2N_API extern int s2n_config_set_cache_retrieve_callback(struct s2n_config *config, s2n_cache_retrieve_callback cache_retrieve_callback, void *data); S2N_API extern int s2n_config_set_cache_delete_callback(struct s2n_config *config, s2n_cache_delete_callback cache_delete_callback, void *data); typedef int (*s2n_mem_init_callback)(void); typedef int (*s2n_mem_cleanup_callback)(void); typedef int (*s2n_mem_malloc_callback)(void **ptr, uint32_t requested, uint32_t *allocated); typedef int (*s2n_mem_free_callback)(void *ptr, uint32_t size); S2N_API extern int s2n_mem_set_callbacks(s2n_mem_init_callback mem_init_callback, s2n_mem_cleanup_callback mem_cleanup_callback, s2n_mem_malloc_callback mem_malloc_callback, s2n_mem_free_callback mem_free_callback); typedef int (*s2n_rand_init_callback)(void); typedef int (*s2n_rand_cleanup_callback)(void); typedef int (*s2n_rand_seed_callback)(void *data, uint32_t size); typedef int (*s2n_rand_mix_callback)(void *data, uint32_t size); S2N_API extern int s2n_rand_set_callbacks(s2n_rand_init_callback rand_init_callback, s2n_rand_cleanup_callback rand_cleanup_callback, s2n_rand_seed_callback rand_seed_callback, s2n_rand_mix_callback rand_mix_callback); typedef enum { S2N_EXTENSION_SERVER_NAME = 0, S2N_EXTENSION_MAX_FRAG_LEN = 1, S2N_EXTENSION_OCSP_STAPLING = 5, S2N_EXTENSION_SUPPORTED_GROUPS = 10, S2N_EXTENSION_EC_POINT_FORMATS = 11, S2N_EXTENSION_SIGNATURE_ALGORITHMS = 13, S2N_EXTENSION_ALPN = 16, S2N_EXTENSION_CERTIFICATE_TRANSPARENCY = 18, S2N_EXTENSION_RENEGOTIATION_INFO = 65281, } s2n_tls_extension_type; typedef enum { S2N_TLS_MAX_FRAG_LEN_512 = 1, S2N_TLS_MAX_FRAG_LEN_1024 = 2, S2N_TLS_MAX_FRAG_LEN_2048 = 3, S2N_TLS_MAX_FRAG_LEN_4096 = 4, } s2n_max_frag_len; struct s2n_cert; struct s2n_cert_chain_and_key; struct s2n_pkey; typedef struct s2n_pkey s2n_cert_public_key; typedef struct s2n_pkey s2n_cert_private_key; S2N_API extern struct s2n_cert_chain_and_key *s2n_cert_chain_and_key_new(void); S2N_API extern int s2n_cert_chain_and_key_load_pem(struct s2n_cert_chain_and_key *chain_and_key, const char *chain_pem, const char *private_key_pem); S2N_API extern int s2n_cert_chain_and_key_load_pem_bytes(struct s2n_cert_chain_and_key *chain_and_key, uint8_t *chain_pem, uint32_t chain_pem_len, uint8_t *private_key_pem, uint32_t private_key_pem_len); S2N_API extern int s2n_cert_chain_and_key_free(struct s2n_cert_chain_and_key *cert_and_key); S2N_API extern int s2n_cert_chain_and_key_set_ctx(struct s2n_cert_chain_and_key *cert_and_key, void *ctx); S2N_API extern void *s2n_cert_chain_and_key_get_ctx(struct s2n_cert_chain_and_key *cert_and_key); S2N_API extern s2n_cert_private_key *s2n_cert_chain_and_key_get_private_key(struct s2n_cert_chain_and_key *cert_and_key); typedef struct s2n_cert_chain_and_key* (*s2n_cert_tiebreak_callback) (struct s2n_cert_chain_and_key *cert1, struct s2n_cert_chain_and_key *cert2, uint8_t *name, uint32_t name_len); S2N_API extern int s2n_config_set_cert_tiebreak_callback(struct s2n_config *config, s2n_cert_tiebreak_callback cert_tiebreak_cb); S2N_API extern int s2n_config_add_cert_chain_and_key(struct s2n_config *config, const char *cert_chain_pem, const char *private_key_pem); S2N_API extern int s2n_config_add_cert_chain_and_key_to_store(struct s2n_config *config, struct s2n_cert_chain_and_key *cert_key_pair); S2N_API extern int s2n_config_set_cert_chain_and_key_defaults(struct s2n_config *config, struct s2n_cert_chain_and_key **cert_key_pairs, uint32_t num_cert_key_pairs); S2N_API extern int s2n_config_set_verification_ca_location(struct s2n_config *config, const char *ca_pem_filename, const char *ca_dir); S2N_API extern int s2n_config_add_pem_to_trust_store(struct s2n_config *config, const char *pem); typedef uint8_t (*s2n_verify_host_fn) (const char *host_name, size_t host_name_len, void *data); /* will be inherited by s2n_connection. If s2n_connection specifies a callback, that callback will be used for that connection. */ S2N_API extern int s2n_config_set_verify_host_callback(struct s2n_config *config, s2n_verify_host_fn, void *data); S2N_API extern int s2n_config_set_check_stapled_ocsp_response(struct s2n_config *config, uint8_t check_ocsp); S2N_API extern int s2n_config_disable_x509_verification(struct s2n_config *config); S2N_API extern int s2n_config_set_max_cert_chain_depth(struct s2n_config *config, uint16_t max_depth); S2N_API extern int s2n_config_add_dhparams(struct s2n_config *config, const char *dhparams_pem); S2N_API extern int s2n_config_set_cipher_preferences(struct s2n_config *config, const char *version); /** * Appends the provided application protocol to the preference list * * The data provided in `protocol` parameter will be copied into an internal buffer * * @param config The configuration object being updated * @param protocol A pointer to a byte array value * @param protocol_len The length of bytes that should be read from `protocol`. Note: this value cannot be 0, otherwise an error will be returned. */ S2N_API extern int s2n_config_append_protocol_preference(struct s2n_config *config, const uint8_t *protocol, uint8_t protocol_len); S2N_API extern int s2n_config_set_protocol_preferences(struct s2n_config *config, const char * const *protocols, int protocol_count); typedef enum { S2N_STATUS_REQUEST_NONE = 0, S2N_STATUS_REQUEST_OCSP = 1 } s2n_status_request_type; S2N_API extern int s2n_config_set_status_request_type(struct s2n_config *config, s2n_status_request_type type); typedef enum { S2N_CT_SUPPORT_NONE = 0, S2N_CT_SUPPORT_REQUEST = 1 } s2n_ct_support_level; S2N_API extern int s2n_config_set_ct_support_level(struct s2n_config *config, s2n_ct_support_level level); typedef enum { S2N_ALERT_FAIL_ON_WARNINGS = 0, S2N_ALERT_IGNORE_WARNINGS = 1 } s2n_alert_behavior; S2N_API extern int s2n_config_set_alert_behavior(struct s2n_config *config, s2n_alert_behavior alert_behavior); S2N_API extern int s2n_config_set_extension_data(struct s2n_config *config, s2n_tls_extension_type type, const uint8_t *data, uint32_t length); S2N_API extern int s2n_config_send_max_fragment_length(struct s2n_config *config, s2n_max_frag_len mfl_code); S2N_API extern int s2n_config_accept_max_fragment_length(struct s2n_config *config); S2N_API extern int s2n_config_set_session_state_lifetime(struct s2n_config *config, uint64_t lifetime_in_secs); S2N_API extern int s2n_config_set_session_tickets_onoff(struct s2n_config *config, uint8_t enabled); S2N_API extern int s2n_config_set_session_cache_onoff(struct s2n_config *config, uint8_t enabled); S2N_API extern int s2n_config_set_ticket_encrypt_decrypt_key_lifetime(struct s2n_config *config, uint64_t lifetime_in_secs); S2N_API extern int s2n_config_set_ticket_decrypt_key_lifetime(struct s2n_config *config, uint64_t lifetime_in_secs); S2N_API extern int s2n_config_add_ticket_crypto_key(struct s2n_config *config, const uint8_t *name, uint32_t name_len, uint8_t *key, uint32_t key_len, uint64_t intro_time_in_seconds_from_epoch); typedef enum { S2N_SERVER, S2N_CLIENT } s2n_mode; S2N_API extern struct s2n_connection *s2n_connection_new(s2n_mode mode); S2N_API extern int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *config); S2N_API extern int s2n_connection_set_ctx(struct s2n_connection *conn, void *ctx); S2N_API extern void *s2n_connection_get_ctx(struct s2n_connection *conn); typedef int s2n_client_hello_fn(struct s2n_connection *conn, void *ctx); typedef enum { S2N_CLIENT_HELLO_CB_BLOCKING, S2N_CLIENT_HELLO_CB_NONBLOCKING } s2n_client_hello_cb_mode; S2N_API extern int s2n_config_set_client_hello_cb(struct s2n_config *config, s2n_client_hello_fn client_hello_callback, void *ctx); S2N_API extern int s2n_config_set_client_hello_cb_mode(struct s2n_config *config, s2n_client_hello_cb_mode cb_mode); S2N_API extern int s2n_client_hello_cb_done(struct s2n_connection *conn); S2N_API extern int s2n_connection_server_name_extension_used(struct s2n_connection *conn); struct s2n_client_hello; S2N_API extern struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn); S2N_API extern ssize_t s2n_client_hello_get_raw_message_length(struct s2n_client_hello *ch); S2N_API extern ssize_t s2n_client_hello_get_raw_message(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length); S2N_API extern ssize_t s2n_client_hello_get_cipher_suites_length(struct s2n_client_hello *ch); S2N_API extern ssize_t s2n_client_hello_get_cipher_suites(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length); S2N_API extern ssize_t s2n_client_hello_get_extensions_length(struct s2n_client_hello *ch); S2N_API extern ssize_t s2n_client_hello_get_extensions(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length); S2N_API extern ssize_t s2n_client_hello_get_extension_length(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type); S2N_API extern ssize_t s2n_client_hello_get_extension_by_id(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type, uint8_t *out, uint32_t max_length); S2N_API extern int s2n_connection_set_fd(struct s2n_connection *conn, int fd); S2N_API extern int s2n_connection_set_read_fd(struct s2n_connection *conn, int readfd); S2N_API extern int s2n_connection_set_write_fd(struct s2n_connection *conn, int writefd); S2N_API extern int s2n_connection_use_corked_io(struct s2n_connection *conn); typedef int s2n_recv_fn(void *io_context, uint8_t *buf, uint32_t len); typedef int s2n_send_fn(void *io_context, const uint8_t *buf, uint32_t len); S2N_API extern int s2n_connection_set_recv_ctx(struct s2n_connection *conn, void *ctx); S2N_API extern int s2n_connection_set_send_ctx(struct s2n_connection *conn, void *ctx); S2N_API extern int s2n_connection_set_recv_cb(struct s2n_connection *conn, s2n_recv_fn recv); S2N_API extern int s2n_connection_set_send_cb(struct s2n_connection *conn, s2n_send_fn send); S2N_API extern int s2n_connection_prefer_throughput(struct s2n_connection *conn); S2N_API extern int s2n_connection_prefer_low_latency(struct s2n_connection *conn); S2N_API extern int s2n_connection_set_dynamic_record_threshold(struct s2n_connection *conn, uint32_t resize_threshold, uint16_t timeout_threshold); /* If you don't want to use the configuration wide callback, you can set this per connection and it will be honored. */ S2N_API extern int s2n_connection_set_verify_host_callback(struct s2n_connection *config, s2n_verify_host_fn host_fn, void *data); typedef enum { S2N_BUILT_IN_BLINDING, S2N_SELF_SERVICE_BLINDING } s2n_blinding; S2N_API extern int s2n_connection_set_blinding(struct s2n_connection *conn, s2n_blinding blinding); S2N_API extern uint64_t s2n_connection_get_delay(struct s2n_connection *conn); S2N_API extern int s2n_connection_set_cipher_preferences(struct s2n_connection *conn, const char *version); /** * Appends the provided application protocol to the preference list * * The data provided in `protocol` parameter will be copied into an internal buffer * * @param conn The connection object being updated * @param protocol A pointer to a slice of bytes * @param protocol_len The length of bytes that should be read from `protocol`. Note: this value cannot be 0, otherwise an error will be returned. */ S2N_API extern int s2n_connection_append_protocol_preference(struct s2n_connection *conn, const uint8_t *protocol, uint8_t protocol_len); S2N_API extern int s2n_connection_set_protocol_preferences(struct s2n_connection *conn, const char * const *protocols, int protocol_count); S2N_API extern int s2n_set_server_name(struct s2n_connection *conn, const char *server_name); S2N_API extern const char *s2n_get_server_name(struct s2n_connection *conn); S2N_API extern const char *s2n_get_application_protocol(struct s2n_connection *conn); S2N_API extern const uint8_t *s2n_connection_get_ocsp_response(struct s2n_connection *conn, uint32_t *length); S2N_API extern const uint8_t *s2n_connection_get_sct_list(struct s2n_connection *conn, uint32_t *length); typedef enum { S2N_NOT_BLOCKED = 0, S2N_BLOCKED_ON_READ, S2N_BLOCKED_ON_WRITE, S2N_BLOCKED_ON_APPLICATION_INPUT, S2N_BLOCKED_ON_EARLY_DATA, } s2n_blocked_status; S2N_API extern int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked); S2N_API extern ssize_t s2n_send(struct s2n_connection *conn, const void *buf, ssize_t size, s2n_blocked_status *blocked); S2N_API extern ssize_t s2n_sendv(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, s2n_blocked_status *blocked); S2N_API extern ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked); S2N_API extern ssize_t s2n_recv(struct s2n_connection *conn, void *buf, ssize_t size, s2n_blocked_status *blocked); S2N_API extern uint32_t s2n_peek(struct s2n_connection *conn); S2N_API extern int s2n_connection_free_handshake(struct s2n_connection *conn); S2N_API extern int s2n_connection_release_buffers(struct s2n_connection *conn); S2N_API extern int s2n_connection_wipe(struct s2n_connection *conn); S2N_API extern int s2n_connection_free(struct s2n_connection *conn); S2N_API extern int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked); typedef enum { S2N_CERT_AUTH_NONE, S2N_CERT_AUTH_REQUIRED, S2N_CERT_AUTH_OPTIONAL } s2n_cert_auth_type; S2N_API extern int s2n_config_get_client_auth_type(struct s2n_config *config, s2n_cert_auth_type *client_auth_type); S2N_API extern int s2n_config_set_client_auth_type(struct s2n_config *config, s2n_cert_auth_type client_auth_type); S2N_API extern int s2n_connection_get_client_auth_type(struct s2n_connection *conn, s2n_cert_auth_type *client_auth_type); S2N_API extern int s2n_connection_set_client_auth_type(struct s2n_connection *conn, s2n_cert_auth_type client_auth_type); S2N_API extern int s2n_connection_get_client_cert_chain(struct s2n_connection *conn, uint8_t **der_cert_chain_out, uint32_t *cert_chain_len); /** * Sets the initial number of session tickets to send after a >=TLS1.3 handshake. The default value is one ticket. * * @param config A pointer to the config object. * @param num The number of session tickets that will be sent. */ S2N_API extern int s2n_config_set_initial_ticket_count(struct s2n_config *config, uint8_t num); /** * Increases the number of session tickets to send after a >=TLS1.3 handshake. * * @param conn A pointer to the connection object. * @param num The number of additional session tickets to send. */ S2N_API extern int s2n_connection_add_new_tickets_to_send(struct s2n_connection *conn, uint8_t num); /** * Sets the keying material lifetime for >=TLS1.3 session tickets so that one session doesn't get re-used ad infinitum. * The default value is one week. * * @param conn A pointer to the connection object. * @param lifetime_in_secs Lifetime of keying material in seconds. */ S2N_API extern int s2n_connection_set_server_keying_material_lifetime(struct s2n_connection *conn, uint32_t lifetime_in_secs); struct s2n_session_ticket; /** * Callback function for receiving a session ticket. * * # Safety * * `ctx` is a void pointer and the caller is responsible for ensuring it is cast to the correct type. * `ticket` is valid only within the scope of this callback. * * @param conn A pointer to the connection object. * @param ctx Context for the session ticket callback function. * @param ticket Pointer to the received session ticket object. */ typedef int (*s2n_session_ticket_fn)(struct s2n_connection *conn, void *ctx, struct s2n_session_ticket *ticket); /** * Sets a session ticket callback to be called when a client receives a new session ticket. * * # Safety * * `callback` MUST cast `ctx` into the same type of pointer that was originally created. * `ctx` MUST be valid for the lifetime of the config, or until a different context is set. * * @param config A pointer to the config object. * @param callback The function that should be called when the callback is triggered. * @param ctx The context to be passed when the callback is called. */ S2N_API extern int s2n_config_set_session_ticket_cb(struct s2n_config *config, s2n_session_ticket_fn callback, void *ctx); /** * Gets the length of the session ticket from a session ticket object. * * @param ticket Pointer to the session ticket object. * @param data_len Pointer to be set to the length of the session ticket on success. */ S2N_API extern int s2n_session_ticket_get_data_len(struct s2n_session_ticket *ticket, size_t *data_len); /** * Gets the session ticket data from a session ticket object. * * # Safety * The entire session ticket will be copied into `data` on success. Therefore, `data` MUST have enough * memory to store the session ticket data. * * @param ticket Pointer to the session ticket object. * @param max_data_len Maximum length of data that can be written to the 'data' pointer. * @param data Pointer to where the session ticket data will be stored. */ S2N_API extern int s2n_session_ticket_get_data(struct s2n_session_ticket *ticket, size_t max_data_len, uint8_t *data); /** * Gets the lifetime in seconds of the session ticket from a session ticket object. * * @param ticket Pointer to the session ticket object. * @param session_lifetime Pointer to a variable where the lifetime of the session ticket will be stored. */ S2N_API extern int s2n_session_ticket_get_lifetime(struct s2n_session_ticket *ticket, uint32_t *session_lifetime); S2N_API extern int s2n_connection_set_session(struct s2n_connection *conn, const uint8_t *session, size_t length); S2N_API extern int s2n_connection_get_session(struct s2n_connection *conn, uint8_t *session, size_t max_length); S2N_API extern int s2n_connection_get_session_ticket_lifetime_hint(struct s2n_connection *conn); S2N_API extern int s2n_connection_get_session_length(struct s2n_connection *conn); S2N_API extern int s2n_connection_get_session_id_length(struct s2n_connection *conn); S2N_API extern int s2n_connection_get_session_id(struct s2n_connection *conn, uint8_t *session_id, size_t max_length); S2N_API extern int s2n_connection_is_session_resumed(struct s2n_connection *conn); S2N_API extern int s2n_connection_is_ocsp_stapled(struct s2n_connection *conn); /* TLS Signature Algorithms - RFC 5246 7.4.1.4.1 */ /* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16 */ typedef enum { S2N_TLS_SIGNATURE_ANONYMOUS = 0, S2N_TLS_SIGNATURE_RSA = 1, S2N_TLS_SIGNATURE_ECDSA = 3, /* Use Private Range for RSA PSS since it's not defined there */ S2N_TLS_SIGNATURE_RSA_PSS_RSAE = 224, S2N_TLS_SIGNATURE_RSA_PSS_PSS } s2n_tls_signature_algorithm; /* TLS Hash Algorithm - https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ /* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18 */ typedef enum { S2N_TLS_HASH_NONE = 0, S2N_TLS_HASH_MD5 = 1, S2N_TLS_HASH_SHA1 = 2, S2N_TLS_HASH_SHA224 = 3, S2N_TLS_HASH_SHA256 = 4, S2N_TLS_HASH_SHA384 = 5, S2N_TLS_HASH_SHA512 = 6, /* Use Private Range for MD5_SHA1 */ S2N_TLS_HASH_MD5_SHA1 = 224 } s2n_tls_hash_algorithm; S2N_API extern int s2n_connection_get_selected_signature_algorithm(struct s2n_connection *conn, s2n_tls_signature_algorithm *chosen_alg); S2N_API extern int s2n_connection_get_selected_digest_algorithm(struct s2n_connection *conn, s2n_tls_hash_algorithm *chosen_alg); S2N_API extern int s2n_connection_get_selected_client_cert_signature_algorithm(struct s2n_connection *conn, s2n_tls_signature_algorithm *chosen_alg); S2N_API extern int s2n_connection_get_selected_client_cert_digest_algorithm(struct s2n_connection *conn, s2n_tls_hash_algorithm *chosen_alg); S2N_API extern struct s2n_cert_chain_and_key *s2n_connection_get_selected_cert(struct s2n_connection *conn); /** * Returns the length of the s2n certificate chain `chain_and_key`. * * @param chain_and_key A pointer to the s2n_cert_chain_and_key object being read. * @param cert_length This return value represents the length of the s2n certificate chain `chain_and_key`. */ S2N_API extern int s2n_cert_chain_get_length(const struct s2n_cert_chain_and_key *chain_and_key, uint32_t *cert_length); /** * Returns the certificate `out_cert` present at the index `cert_idx` of the certificate chain `chain_and_key`. * * Note that the index of the leaf certificate is zero. If the certificate chain `chain_and_key` is NULL or the * certificate index value is not in the acceptable range for the input certificate chain, an error is returned. * * # Safety * * There is no memory allocation required for `out_cert` buffer prior to calling the `s2n_cert_chain_get_cert` API. * The `out_cert` will contain the pointer to the s2n_cert initialized within the input s2n_cert_chain_and_key `chain_and_key`. * The pointer to the output s2n certificate `out_cert` is valid until `chain_and_key` is freed up. * If a caller wishes to persist the `out_cert` beyond the lifetime of `chain_and_key`, the contents would need to be * copied prior to freeing `chain_and_key`. * * @param chain_and_key A pointer to the s2n_cert_chain_and_key object being read. * @param out_cert A pointer to the output s2n_cert `out_cert` present at the index `cert_idx` of the certificate chain `chain_and_key`. * @param cert_idx The certificate index for the requested certificate within the s2n certificate chain. */ S2N_API extern int s2n_cert_chain_get_cert(const struct s2n_cert_chain_and_key *chain_and_key, struct s2n_cert **out_cert, const uint32_t cert_idx); /** * Returns the s2n certificate in DER format along with its length. * * The API gets the s2n certificate `cert` in DER format. The certificate is returned in the `out_cert_der` buffer. * Here, `cert_len` represents the length of the certificate. * * A caller can use certificate parsing tools such as the ones provided by OpenSSL to parse the DER encoded certificate chain returned. * * # Safety * * The memory for the `out_cert_der` buffer is allocated and owned by s2n-tls. * Since the size of the certificate can potentially be very large, a pointer to internal connection data is returned instead of * copying the contents into a caller-provided buffer. * * The pointer to the output buffer `out_cert_der` is valid only while the connection exists. * The `s2n_connection_free` API frees the memory associated with the out_cert_der buffer and after the `s2n_connection_wipe` API is * called the memory pointed by out_cert_der is invalid. * * If a caller wishes to persist the `out_cert_der` beyond the lifetime of the connection, the contents would need to be * copied prior to the connection termination. * * @param cert A pointer to the s2n_cert object being read. * @param out_cert_der A pointer to the output buffer which will hold the s2n certificate `cert` in DER format. * @param cert_length This return value represents the length of the certificate. */ S2N_API extern int s2n_cert_get_der(const struct s2n_cert *cert, const uint8_t **out_cert_der, uint32_t *cert_length); /** * Returns the validated peer certificate chain as a `s2n_cert_chain_and_key` opaque object. * * The `s2n_cert_chain_and_key` parameter must be allocated by the caller using the `s2n_cert_chain_and_key_new` API * prior to this function call and must be empty. To free the memory associated with the `s2n_cert_chain_and_key` object use the * `s2n_cert_chain_and_key_free` API. * * @param conn A pointer to the s2n_connection object being read. * @param s2n_cert_chain_and_key The returned validated peer certificate chain `cert_chain` retrieved from the s2n connection. */ S2N_API extern int s2n_connection_get_peer_cert_chain(const struct s2n_connection *conn, struct s2n_cert_chain_and_key *cert_chain); /** * Returns the length of the DER encoded extension value of the ASN.1 X.509 certificate extension. * * @param cert A pointer to the s2n_cert object being read. * @param oid A null-terminated cstring that contains the OID of the X.509 certificate extension to be read. * @param ext_value_len This return value contains the length of DER encoded extension value of the ASN.1 X.509 certificate extension. */ S2N_API extern int s2n_cert_get_x509_extension_value_length(struct s2n_cert *cert, const uint8_t *oid, uint32_t *ext_value_len); /** * Returns the DER encoding of an ASN.1 X.509 certificate extension value, it's length and a boolean critical. * * @param cert A pointer to the s2n_cert object being read. * @param oid A null-terminated cstring that contains the OID of the X.509 certificate extension to be read. * @param ext_value A pointer to the output buffer which will hold the DER encoding of an ASN.1 X.509 certificate extension value returned. * @param ext_value_len This value is both an input and output parameter and represents the length of the output buffer `ext_value`. * When used as an input parameter, the caller must use this parameter to convey the maximum length of `ext_value`. * When used as an output parameter, `ext_value_len` holds the actual length of the DER encoding of the ASN.1 X.509 certificate extension value returned. * @param critical This return value contains the boolean value for `critical`. */ S2N_API extern int s2n_cert_get_x509_extension_value(struct s2n_cert *cert, const uint8_t *oid, uint8_t *ext_value, uint32_t *ext_value_len, bool *critical); /** * Returns the UTF8 String length of the ASN.1 X.509 certificate extension data. * * @param extension_data A pointer to the DER encoded ASN.1 X.509 certificate extension value being read. * @param extension_len represents the length of the input buffer `extension_data`. * @param utf8_str_len This return value contains the UTF8 String length of the ASN.1 X.509 certificate extension data. */ S2N_API extern int s2n_cert_get_utf8_string_from_extension_data_length(const uint8_t *extension_data, uint32_t extension_len, uint32_t *utf8_str_len); /** * Returns the UTF8 String representation of the DER encoded ASN.1 X.509 certificate extension data. * * @param extension_data A pointer to the DER encoded ASN.1 X.509 certificate extension value being read. * @param extension_len represents the length of the input buffer `extension_data`. * @param out_data A pointer to the output buffer which will hold the UTF8 String representation of the DER encoded ASN.1 X.509 * certificate extension data returned. * @param out_len This value is both an input and output parameter and represents the length of the output buffer `out_data`. * When used as an input parameter, the caller must use this parameter to convey the maximum length of `out_data`. * When used as an output parameter, `out_len` holds the actual length of UTF8 String returned. */ S2N_API extern int s2n_cert_get_utf8_string_from_extension_data(const uint8_t *extension_data, uint32_t extension_len, uint8_t *out_data, uint32_t *out_len); /* Pre-shared key (PSK) Hash Algorithm - RFC 8446 Section-2.2 */ typedef enum { S2N_PSK_HMAC_SHA256, S2N_PSK_HMAC_SHA384, } s2n_psk_hmac; struct s2n_psk; /** * Creates a new s2n external pre-shared key (PSK) object with `S2N_PSK_HMAC_SHA256` as the default * PSK hash algorithm. An external PSK is a key established outside of TLS using a secure mutually agreed upon mechanism. * * Use `s2n_psk_free` to free the memory allocated to the s2n external PSK object created by this API. * * @return struct s2n_psk* Returns a pointer to the newly created external PSK object. */ S2N_API struct s2n_psk* s2n_external_psk_new(); /** * Frees the memory associated with the external PSK object. * * @param psk Pointer to the PSK object to be freed. */ S2N_API int s2n_psk_free(struct s2n_psk **psk); /** * Sets the identity for a given external PSK object. * The identity is a unique identifier for the pre-shared secret. * It is a non-secret value represented by raw bytes. * * # Safety * * The identity is transmitted over the network unencrypted and is a non-secret value. * Do not include confidential information in the identity. * * Note that the identity is copied into s2n-tls memory and the caller is responsible for * freeing the memory associated with the identity input. * * @param psk A pointer to a PSK object to be updated with the identity. * @param identity The identity in raw bytes format to be copied. * @param identity_size The length of the PSK identity being set. */ S2N_API int s2n_psk_set_identity(struct s2n_psk *psk, const uint8_t *identity, uint16_t identity_size); /** * Sets the out-of-band/externally provisioned secret for a given external PSK object. * * # Safety * * Note that the secret is copied into s2n-tls memory and the caller is responsible for * freeing the memory associated with the `secret` input. * * Deriving a shared secret from a password or other low-entropy source * is not secure and is subject to dictionary attacks. * See https://tools.ietf.org/rfc/rfc8446#section-2.2 for more information. * * @param psk A pointer to a PSK object to be updated with the secret. * @param secret The secret in raw bytes format to be copied. * @param secret_size The length of the pre-shared secret being set. */ S2N_API int s2n_psk_set_secret(struct s2n_psk *psk, const uint8_t *secret, uint16_t secret_size); /** * Sets the hash algorithm for a given external PSK object. The supported PSK hash * algorithms are as listed in the enum `s2n_psk_hmac` above. * * @param psk A pointer to the external PSK object to be updated with the PSK hash algorithm. * @param hmac The PSK hash algorithm being set. */ S2N_API int s2n_psk_set_hmac(struct s2n_psk *psk, s2n_psk_hmac hmac); /** * Appends a PSK object to the list of PSKs supported by the s2n connection. * If a PSK with a duplicate identity is found, an error is returned and the PSK is not added to the list. * Note that a copy of `psk` is stored on the connection. The user is still responsible for freeing the * memory associated with `psk`. * * @param conn A pointer to the s2n_connection object that contains the list of PSKs supported. * @param psk A pointer to the `s2n_psk` object to be appended to the list of PSKs on the s2n connection. */ S2N_API int s2n_connection_append_psk(struct s2n_connection *conn, struct s2n_psk *psk); /** * The list of PSK modes supported by s2n-tls for TLS versions >= TLS1.3. * Currently s2n-tls supports two modes - `S2N_PSK_MODE_RESUMPTION`, which represents the PSKs established * using the previous connection via session resumption, and `S2N_PSK_MODE_EXTERNAL`, which represents PSKs * established out-of-band/externally using a secure mutually agreed upon mechanism. */ typedef enum { S2N_PSK_MODE_RESUMPTION, S2N_PSK_MODE_EXTERNAL } s2n_psk_mode; /** * Sets the PSK mode on the s2n config object. * The supported PSK modes are listed in the enum `s2n_psk_mode` above. * * @param config A pointer to the s2n_config object being updated. * @param mode The PSK mode to be set. */ S2N_API int s2n_config_set_psk_mode(struct s2n_config *config, s2n_psk_mode mode); /** * Sets the PSK mode on the s2n connection object. * The supported PSK modes are listed in the enum `s2n_psk_mode` above. * This API overrides the PSK mode set on config for this connection. * * @param conn A pointer to the s2n_connection object being updated. * @param mode The PSK mode to be set. */ S2N_API int s2n_connection_set_psk_mode(struct s2n_connection *conn, s2n_psk_mode mode); /** * Gets the negotiated PSK identity length from the s2n connection object. The negotiated PSK * refers to the chosen PSK by the server to be used for the connection. * * This API can be used to determine if the negotiated PSK exists. If negotiated PSK exists a * call to this API returns a value greater than zero. If the negotiated PSK does not exist, the * value `0` is returned. * * @param conn A pointer to the s2n_connection object that successfully negotiated a PSK connection. * @param identity_length The length of the negotiated PSK identity. */ S2N_API int s2n_connection_get_negotiated_psk_identity_length(struct s2n_connection *conn, uint16_t *identity_length); /** * Gets the negotiated PSK identity from the s2n connection object. * If the negotiated PSK does not exist, the PSK identity will not be obtained and no error will be returned. * Prior to this API call, use `s2n_connection_get_negotiated_psk_identity_length` to determine if a * negotiated PSK exists or not. * * # Safety * * The negotiated PSK identity will be copied into the identity buffer on success. * Therefore, the identity buffer must have enough memory to fit the identity length. * * @param conn A pointer to the s2n_connection object. * @param identity The negotiated PSK identity obtained from the s2n_connection object. * @param max_identity_length The maximum length for the PSK identity. If the negotiated psk_identity length is * greater than this `max_identity_length` value an error will be returned. */ S2N_API int s2n_connection_get_negotiated_psk_identity(struct s2n_connection *conn, uint8_t *identity, uint16_t max_identity_length); struct s2n_offered_psk; /** * Creates a new s2n offered PSK object. * An offered PSK object represents a single PSK sent by the client. * * # Safety * * Use `s2n_offered_psk_free` to free the memory allocated to the s2n offered PSK object created by this API. * * @return struct s2n_offered_psk* Returns a pointer to the newly created offered PSK object. */ S2N_API struct s2n_offered_psk* s2n_offered_psk_new(); /** * Frees the memory associated with the `s2n_offered_psk` object. * * @param psk A pointer to the `s2n_offered_psk` object to be freed. */ S2N_API int s2n_offered_psk_free(struct s2n_offered_psk **psk); /** * Gets the PSK identity and PSK identity length for a given offered PSK object. * * @param psk A pointer to the offered PSK object being read. * @param identity The PSK identity being obtained. * @param size The length of the PSK identity being obtained. */ S2N_API int s2n_offered_psk_get_identity(struct s2n_offered_psk *psk, uint8_t** identity, uint16_t *size); struct s2n_offered_psk_list; /** * Checks whether the offered PSK list has an offered psk object next in line in the list. * An offered PSK list contains all the PSKs offered by the client for the server to select. * * @param psk_list A pointer to the offered PSK list being read. * @return bool A boolean value representing whether an offered psk object is present next in line in the offered PSK list. */ S2N_API bool s2n_offered_psk_list_has_next(struct s2n_offered_psk_list *psk_list); /** * Obtains the next offered PSK object from the list of offered PSKs. Use `s2n_offered_psk_list_has_next` * prior to this API call to ensure we have not reached the end of the list. * * @param psk_list A pointer to the offered PSK list being read. * @param psk A pointer to the next offered PSK object being obtained. */ S2N_API int s2n_offered_psk_list_next(struct s2n_offered_psk_list *psk_list, struct s2n_offered_psk *psk); /** * Returns the offered PSK list to its original read state. * * When `s2n_offered_psk_list_reread` is called, `s2n_offered_psk_list_next` will return the first PSK * in the offered PSK list. * * @param psk_list A pointer to the offered PSK list being reread. */ S2N_API int s2n_offered_psk_list_reread(struct s2n_offered_psk_list *psk_list); /** * Chooses a PSK from the offered PSK list to be used for the connection. * This API matches the PSK identity received from the client against the server's known PSK identities * list, in order to choose the PSK to be used for the connection. If the PSK identity sent from the client * is NULL, no PSK is chosen for the connection. If the client offered PSK identity has no matching PSK identity * with the server, an error will be returned. Use this API along with the `s2n_psk_selection_callback` callback * to select a PSK identity. * * @param psk_list A pointer to the server's known PSK list used to compare for a matching PSK with the client. * @param psk A pointer to the client's PSK object used to compare with the server's known PSK identities. */ S2N_API int s2n_offered_psk_list_choose_psk(struct s2n_offered_psk_list *psk_list, struct s2n_offered_psk *psk); /** * Callback function to select a PSK from a list of offered PSKs. * Use this callback to implement custom PSK selection logic. The s2n-tls default PSK selection logic * chooses the first matching PSK from the list of offered PSKs sent by the client. * * # Safety * * `context` is a void pointer and the caller is responsible for ensuring it is cast to the correct type. * * @param conn A pointer to the s2n_connection object. * @param context A pointer to a context for the caller to pass state to the callback, if needed. * @param psk_list A pointer to the offered PSK list being read. */ typedef int (*s2n_psk_selection_callback)(struct s2n_connection *conn, void *context, struct s2n_offered_psk_list *psk_list); /** * Sets the callback to select the matching PSK. * If this callback is not set s2n-tls uses a default PSK selection logic that selects the first matching * server PSK. * * @param config A pointer to the s2n_config object. * @param cb The function that should be called when the callback is triggered. * @param context A pointer to a context for the caller to pass state to the callback, if needed. */ S2N_API int s2n_config_set_psk_selection_callback(struct s2n_config *config, s2n_psk_selection_callback cb, void *context); S2N_API extern uint64_t s2n_connection_get_wire_bytes_in(struct s2n_connection *conn); S2N_API extern uint64_t s2n_connection_get_wire_bytes_out(struct s2n_connection *conn); S2N_API extern int s2n_connection_get_client_protocol_version(struct s2n_connection *conn); S2N_API extern int s2n_connection_get_server_protocol_version(struct s2n_connection *conn); S2N_API extern int s2n_connection_get_actual_protocol_version(struct s2n_connection *conn); S2N_API extern int s2n_connection_get_client_hello_version(struct s2n_connection *conn); S2N_API extern int s2n_connection_client_cert_used(struct s2n_connection *conn); S2N_API extern const char *s2n_connection_get_cipher(struct s2n_connection *conn); /** * Returns the IANA value for the connection's negotiated cipher suite. * * The value is returned in the form of `first,second`, in order to closely match * the values defined in the [IANA Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#table-tls-parameters-4). * For example if the connection's negotiated cipher suite is `TLS_AES_128_GCM_SHA256`, * which is registered as `0x13,0x01`, then `first = 0x13` and `second = 0x01`. * * This method will only succeed after the cipher suite has been negotiated with the peer. * * @param conn A pointer to the connection being read * @param first A pointer to a single byte, which will be updated with the first byte in the registered IANA value. * @param second A pointer to a single byte, which will be updated with the second byte in the registered IANA value. * @return A POSIX error signal. If an error was returned, the values contained in `first` and `second` should be considered invalid. */ S2N_API extern int s2n_connection_get_cipher_iana_value(struct s2n_connection *conn, uint8_t *first, uint8_t *second); S2N_API extern int s2n_connection_is_valid_for_cipher_preferences(struct s2n_connection *conn, const char *version); S2N_API extern const char *s2n_connection_get_curve(struct s2n_connection *conn); S2N_API extern const char *s2n_connection_get_kem_name(struct s2n_connection *conn); S2N_API extern const char *s2n_connection_get_kem_group_name(struct s2n_connection *conn); S2N_API extern int s2n_connection_get_alert(struct s2n_connection *conn); S2N_API extern const char *s2n_connection_get_handshake_type_name(struct s2n_connection *conn); S2N_API extern const char *s2n_connection_get_last_message_name(struct s2n_connection *conn); struct s2n_async_pkey_op; typedef enum { S2N_ASYNC_PKEY_VALIDATION_FAST, S2N_ASYNC_PKEY_VALIDATION_STRICT } s2n_async_pkey_validation_mode; typedef enum { S2N_ASYNC_DECRYPT, S2N_ASYNC_SIGN } s2n_async_pkey_op_type; typedef int (*s2n_async_pkey_fn)(struct s2n_connection *conn, struct s2n_async_pkey_op *op); S2N_API extern int s2n_config_set_async_pkey_callback(struct s2n_config *config, s2n_async_pkey_fn fn); S2N_API extern int s2n_async_pkey_op_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *key); S2N_API extern int s2n_async_pkey_op_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn); S2N_API extern int s2n_async_pkey_op_free(struct s2n_async_pkey_op *op); S2N_API extern int s2n_config_set_async_pkey_validation_mode(struct s2n_config *config, s2n_async_pkey_validation_mode mode); S2N_API extern int s2n_async_pkey_op_get_op_type(struct s2n_async_pkey_op *op, s2n_async_pkey_op_type *type); S2N_API extern int s2n_async_pkey_op_get_input_size(struct s2n_async_pkey_op *op, uint32_t *data_len); S2N_API extern int s2n_async_pkey_op_get_input(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len); S2N_API extern int s2n_async_pkey_op_set_output(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len); /** * Callback function for handling key log events * * THIS SHOULD BE USED FOR DEBUGGING PURPOSES ONLY! * * Each log line is formatted with the * [NSS Key Log Format](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format) * without a newline. * * # Safety * * * `ctx` MUST be cast into the same type of pointer that was originally created * * `logline` bytes MUST be copied or discarded before this function returns * * @param ctx Context for the callback * @param conn Connection for which the log line is being emitted * @param logline Pointer to the log line data * @param len Length of the log line data */ typedef int (*s2n_key_log_fn)(void *ctx, struct s2n_connection *conn, uint8_t *logline, size_t len); /** * Sets a key logging callback on the provided config * * THIS SHOULD BE USED FOR DEBUGGING PURPOSES ONLY! * * Setting this function enables configurations to emit secrets in the * [NSS Key Log Format](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format) * * # Safety * * * `callback` MUST cast `ctx` into the same type of pointer that was originally created * * `ctx` MUST live for at least as long as it is set on the config * * @param config Config to set the callback * @param callback The function that should be called for each secret log entry * @param ctx The context to be passed when the callback is called */ S2N_API extern int s2n_config_set_key_log_cb(struct s2n_config *config, s2n_key_log_fn callback, void *ctx); /* s2n_config_enable_cert_req_dss_legacy_compat adds a dss cert type in the server certificate request when being called. * It only sends the dss cert type in the cert request but does not succeed the handshake if a dss cert is received. * Please DO NOT call this api unless you know you actually need legacy DSS certificate type compatibility */ S2N_API extern int s2n_config_enable_cert_req_dss_legacy_compat(struct s2n_config *config); /** * Sets the maximum bytes of early data the server will accept. * * The default maximum is 0. If the maximum is 0, the server rejects all early data requests. * The config maximum can be overridden by the connection maximum or the maximum on an external pre-shared key. * * @param config A pointer to the config * @param max_early_data_size The maximum early data that the server will accept * @return A POSIX error signal. If successful, the maximum early data size was updated. */ S2N_API int s2n_config_set_server_max_early_data_size(struct s2n_config *config, uint32_t max_early_data_size); /** * Sets the maximum bytes of early data the server will accept. * * The default maximum is 0. If the maximum is 0, the server rejects all early data requests. * The connection maximum can be overridden by the maximum on an external pre-shared key. * * @param conn A pointer to the connection * @param max_early_data_size The maximum early data the server will accept * @return A POSIX error signal. If successful, the maximum early data size was updated. */ S2N_API int s2n_connection_set_server_max_early_data_size(struct s2n_connection *conn, uint32_t max_early_data_size); /** * Sets the user context associated with early data on a server. * * This context is passed to the `s2n_early_data_cb` callback to help decide whether to accept or reject early data. * * Unlike most contexts, the early data context is a byte buffer instead of a void pointer. * This is because we need to serialize the context into session tickets. * * This API is intended for use with session resumption, and will not affect pre-shared keys. * * @param conn A pointer to the connection * @param context A pointer to the user context data. This data will be copied. * @param context_size The size of the data to read from the `context` pointer. * @return A POSIX error signal. If successful, the context was updated. */ S2N_API int s2n_connection_set_server_early_data_context(struct s2n_connection *conn, const uint8_t *context, uint16_t context_size); /** * Configures a particular pre-shared key to allow early data. * * `max_early_data_size` must be set to the maximum early data accepted by the server. * * In order to use early data, the cipher suite set on the pre-shared key must match the cipher suite * ultimately negotiated by the TLS handshake. Additionally, the cipher suite must have the same * hmac algorithm as the pre-shared key. * * @param psk A pointer to the pre-shared key, created with `s2n_external_psk_new`. * @param max_early_data_size The maximum early data that can be sent or received using this key. * @param cipher_suite_first_byte The first byte in the registered IANA value of the associated cipher suite. * @param cipher_suite_second_byte The second byte in the registered IANA value of the associated cipher suite. * @return A POSIX error signal. If successful, `psk` was updated. */ S2N_API int s2n_psk_configure_early_data(struct s2n_psk *psk, uint32_t max_early_data_size, uint8_t cipher_suite_first_byte, uint8_t cipher_suite_second_byte); /** * Sets the optional `application_protocol` associated with the given pre-shared key. * * In order to use early data, the `application_protocol` set on the pre-shared key must match * the `application_protocol` ultimately negotiated by the TLS handshake. * * @param psk A pointer to the pre-shared key, created with `s2n_external_psk_new`. * @param application_protocol A pointer to the associated application protocol data. This data will be copied. * @param size The size of the data to read from the `application_protocol` pointer. * @return A POSIX error signal. If successful, the application protocol was set. */ S2N_API int s2n_psk_set_application_protocol(struct s2n_psk *psk, const uint8_t *application_protocol, uint8_t size); /** * Sets the optional user early data context associated with the given pre-shared key. * * The early data context is passed to the `s2n_early_data_cb` callback to help decide whether * to accept or reject early data. * * @param psk A pointer to the pre-shared key, created with `s2n_external_psk_new`. * @param context A pointer to the associated user context data. This data will be copied. * @param size The size of the data to read from the `context` pointer. * @return A POSIX error signal. If successful, the context was set. */ S2N_API int s2n_psk_set_early_data_context(struct s2n_psk *psk, const uint8_t *context, uint16_t size); /* The status of early data on a connection. * * S2N_EARLY_DATA_STATUS_OK: Early data is in progress. * S2N_EARLY_DATA_STATUS_NOT_REQUESTED: The client did not request early data, so none was sent or received. * S2N_EARLY_DATA_STATUS_REJECTED: The client requested early data, but the server rejected the request. * Early data may have been sent, but was not received. * S2N_EARLY_DATA_STATUS_END: All early data was successfully sent and received. */ typedef enum { S2N_EARLY_DATA_STATUS_OK, S2N_EARLY_DATA_STATUS_NOT_REQUESTED, S2N_EARLY_DATA_STATUS_REJECTED, S2N_EARLY_DATA_STATUS_END, } s2n_early_data_status_t; /** * Reports the current state of early data for a connection. * * See `s2n_early_data_status_t` for all possible states. * * @param conn A pointer to the connection * @param status A pointer which will be set to the current early data status * @return A POSIX error signal. */ S2N_API int s2n_connection_get_early_data_status(struct s2n_connection *conn, s2n_early_data_status_t *status); /** * Reports the remaining size of the early data allowed by a connection. * * If early data was rejected or not requested, the remaining early data size is 0. * Otherwise, the remaining early data size is the maximum early data allowed by the connection, * minus the early data sent or received so far. * * @param conn A pointer to the connection * @param allowed_early_data_size A pointer which will be set to the remaining early data currently allowed by `conn` * @return A POSIX error signal. */ S2N_API int s2n_connection_get_remaining_early_data_size(struct s2n_connection *conn, uint32_t *allowed_early_data_size); /** * Reports the maximum size of the early data allowed by a connection. * * This is the maximum amount of early data that can ever be sent and received for a connection. * It is not affected by the actual status of the early data, so can be non-zero even if early data * is rejected or not requested. * * @param conn A pointer to the connection * @param max_early_data_size A pointer which will be set to the maximum early data allowed by `conn` * @return A POSIX error signal. */ S2N_API int s2n_connection_get_max_early_data_size(struct s2n_connection *conn, uint32_t *max_early_data_size); /** * Called by the client to begin negotiation and send early data. * * See https://github.com/aws/s2n-tls/blob/main/docs/USAGE-GUIDE.md#using-early-data--0rtt * for usage and examples. DO NOT USE unless you have considered the security issues and * implemented mitigation for anti-replay attacks. * * @param conn A pointer to the connection * @param data A pointer to the early data to be sent * @param data_len The size of the early data to send * @param data_sent A pointer which will be set to the size of the early data sent * @param blocked A pointer which will be set to the blocked status, as in `s2n_negotiate`. * @return A POSIX error signal. The error should be handled as in `s2n_negotiate`. */ S2N_API int s2n_send_early_data(struct s2n_connection *conn, const uint8_t *data, ssize_t data_len, ssize_t *data_sent, s2n_blocked_status *blocked); /** * Called by the server to begin negotiation and accept any early data the client sends. * * See https://github.com/aws/s2n-tls/blob/main/docs/USAGE-GUIDE.md#using-early-data--0rtt * for usage and examples. DO NOT USE unless you have considered the security issues and * implemented mitigation for anti-replay attacks. * * @param conn A pointer to the connection * @param data A pointer to a buffer to store the early data received * @param max_data_len The size of the early data buffer * @param data_received A pointer which will be set to the size of the early data received * @param blocked A pointer which will be set to the blocked status, as in `s2n_negotiate`. * @return A POSIX error signal. The error should be handled as in `s2n_negotiate`. */ S2N_API int s2n_recv_early_data(struct s2n_connection *conn, uint8_t *data, ssize_t max_data_len, ssize_t *data_received, s2n_blocked_status *blocked); struct s2n_offered_early_data; /** * A callback which can be implemented to accept or reject early data. * * This callback is triggered only after the server has determined early data is otherwise acceptable according * to the TLS early data specification. Implementations therefore only need to cover application-specific checks, * not the standard TLS early data validation. * * This callback can be synchronous or asynchronous. For asynchronous behavior, return success without * calling `s2n_offered_early_data_reject` or `s2n_offered_early_data_accept`. `early_data` will * still be a valid reference, and the connection will block until `s2n_offered_early_data_reject` or * `s2n_offered_early_data_accept` is called. * * @param conn A pointer to the connection * @param early_data A pointer which can be used to access information about the proposed early data * and then accept or reject it. * @return A POSIX error signal. If unsuccessful, the connection will be closed with an error. */ typedef int (*s2n_early_data_cb)(struct s2n_connection *conn, struct s2n_offered_early_data *early_data); /** * Set a callback to accept or reject early data. * * @param conn A pointer to the connection * @param cb A pointer to the implementation of the callback. * @return A POSIX error signal. If successful, the callback was set. */ S2N_API int s2n_config_set_early_data_cb(struct s2n_config *config, s2n_early_data_cb cb); /** * Get the length of the early data context set by the user. * * @param early_data A pointer to the early data information * @param context_len The length of the user context * @return A POSIX error signal. */ S2N_API int s2n_offered_early_data_get_context_length(struct s2n_offered_early_data *early_data, uint16_t *context_len); /** * Get the early data context set by the user. * * @param early_data A pointer to the early data information * @param context A byte buffer to copy the user context into * @param max_len The size of `context`. Must be >= to the result of `s2n_offered_early_data_get_context_length`. * @return A POSIX error signal. */ S2N_API int s2n_offered_early_data_get_context(struct s2n_offered_early_data *early_data, uint8_t *context, uint16_t max_len); /** * Reject early data offered by the client. * * @param early_data A pointer to the early data information * @return A POSIX error signal. If success, the client's early data will be rejected. */ S2N_API int s2n_offered_early_data_reject(struct s2n_offered_early_data *early_data); /** * Accept early data offered by the client. * * @param early_data A pointer to the early data information * @return A POSIX error signal. If success, the client's early data will be accepted. */ S2N_API int s2n_offered_early_data_accept(struct s2n_offered_early_data *early_data); #ifdef __cplusplus } #endif