diff --git a/CMakeLists.txt b/CMakeLists.txt index ee880c6350f..2f65549a85c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -493,9 +493,7 @@ if (BUILD_TESTING) string(REGEX REPLACE ".+\\/(.+)\\.c" "\\1" test_case_name ${test_case}) add_executable(${test_case_name} ${test_case}) - target_include_directories(${test_case_name} PRIVATE api) target_include_directories(${test_case_name} PRIVATE ./) - target_include_directories(${test_case_name} PRIVATE tests) target_link_libraries(${test_case_name} PRIVATE testss2n) if (S2N_INTERN_LIBCRYPTO) # if libcrypto was interned, rewrite libcrypto symbols so use of internal functions will link correctly @@ -521,15 +519,11 @@ if (BUILD_TESTING) add_executable(s2nc "bin/s2nc.c" "bin/echo.c" "bin/https.c" "bin/common.c") target_link_libraries(s2nc ${PROJECT_NAME}) - - target_include_directories(s2nc PRIVATE api) target_compile_options(s2nc PRIVATE -std=gnu99) add_executable(s2nd "bin/s2nd.c" "bin/echo.c" "bin/https.c" "bin/common.c") target_link_libraries(s2nd ${PROJECT_NAME}) - - target_include_directories(s2nd PRIVATE api) target_compile_options(s2nd PRIVATE -std=gnu99) if(S2N_LTO) diff --git a/api/s2n.h b/api/s2n.h index 6bce51c0342..15f6dbf9c7e 100644 --- a/api/s2n.h +++ b/api/s2n.h @@ -241,6 +241,27 @@ S2N_API extern int s2n_init(void); */ S2N_API extern int s2n_cleanup(void); +typedef enum { + S2N_FIPS_MODE_DISABLED = 0, + S2N_FIPS_MODE_ENABLED, +} s2n_fips_mode; + +/** + * Determines whether s2n-tls is operating in FIPS mode. + * + * s2n-tls enters FIPS mode on initialization when the linked libcrypto has FIPS mode enabled. Some + * libcryptos, such as AWS-LC-FIPS, have FIPS mode enabled by default. With other libcryptos, such + * as OpenSSL, FIPS mode must be enabled before initialization by calling `FIPS_mode_set()`. + * + * s2n-tls MUST be linked to a FIPS libcrypto and MUST be in FIPS mode in order to comply with FIPS + * requirements. Applications desiring FIPS compliance should use this API to ensure that s2n-tls + * has been properly linked with a FIPS libcrypto and has successfully entered FIPS mode. + * + * @param fips_mode Set to the FIPS mode of s2n-tls. + * @returns S2N_SUCCESS on success. S2N_FAILURE on failure. + */ +S2N_API extern int s2n_get_fips_mode(s2n_fips_mode *fips_mode); + /** * Creates a new s2n_config object. This object can (and should) be associated with many connection * objects. @@ -1882,6 +1903,30 @@ 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); +/** + * Used to indicate the type of key update that is being requested. For further + * information refer to `s2n_connection_request_key_update`. +*/ +typedef enum { + S2N_KEY_UPDATE_NOT_REQUESTED = 0, + S2N_KEY_UPDATE_REQUESTED +} s2n_peer_key_update; + +/** + * Signals the connection to do a key_update at the next possible opportunity. Note that the resulting key update message + * will not be sent until `s2n_send` is called. + * + * @param conn The connection object to trigger the key update on. + * @param peer_request Indicates if a key update should also be requested + * of the peer. When set to `S2N_KEY_UPDATE_NOT_REQUESTED`, then only the sending + * key of `conn` will be updated. If set to `S2N_KEY_UPDATE_REQUESTED`, then + * the sending key of conn will be updated AND the peer will be requested to + * update their sending key. Note that s2n-tls currently only supports + * `peer_request` being set to `S2N_KEY_UPDATE_NOT_REQUESTED` and will return + * S2N_FAILURE if any other value is used. + * @returns S2N_SUCCESS on success. S2N_FAILURE on failure +*/ +S2N_API extern int s2n_connection_request_key_update(struct s2n_connection *conn, s2n_peer_key_update peer_request); /** * Appends the provided application protocol to the preference list * diff --git a/bindings/rust/s2n-tls/src/config.rs b/bindings/rust/s2n-tls/src/config.rs index 3137a9d248d..9c42ad2b532 100644 --- a/bindings/rust/s2n-tls/src/config.rs +++ b/bindings/rust/s2n-tls/src/config.rs @@ -151,7 +151,6 @@ impl Drop for Config { } } -#[derive(Default)] pub struct Builder { config: Config, load_system_certs: bool, @@ -743,6 +742,12 @@ impl Builder { } } +impl Default for Builder { + fn default() -> Self { + Self::new() + } +} + pub(crate) struct Context { refcount: AtomicUsize, pub(crate) client_hello_callback: Option>, diff --git a/bindings/rust/s2n-tls/src/testing/s2n_tls.rs b/bindings/rust/s2n-tls/src/testing/s2n_tls.rs index 1b6f12eae03..8fcf7c86db6 100644 --- a/bindings/rust/s2n-tls/src/testing/s2n_tls.rs +++ b/bindings/rust/s2n-tls/src/testing/s2n_tls.rs @@ -756,32 +756,36 @@ mod tests { // Load the server certificate into the trust store by overriding the OpenSSL default // certificate location. temp_env::with_var("SSL_CERT_FILE", Some(keypair.cert_path()), || { - let mut builder = Builder::new(); - builder - .load_pem(keypair.cert(), keypair.key()) - .unwrap() - .set_security_policy(&security::DEFAULT_TLS13) - .unwrap() - .set_verify_host_callback(InsecureAcceptAllCertificatesHandler {}) - .unwrap(); + // Test the Builder itself, and also the Builder produced by the Config builder() API. + for mut builder in [Builder::new(), Config::builder()] { + builder + .load_pem(keypair.cert(), keypair.key()) + .unwrap() + .set_security_policy(&security::DEFAULT_TLS13) + .unwrap() + .set_verify_host_callback(InsecureAcceptAllCertificatesHandler {}) + .unwrap(); - // Disable loading system certificates - builder.with_system_certs(false).unwrap(); + // Disable loading system certificates + builder.with_system_certs(false).unwrap(); - let config = builder.build().unwrap(); - let mut config_with_system_certs = config.clone(); + let config = builder.build().unwrap(); + let mut config_with_system_certs = config.clone(); - let mut pair = tls_pair(config); + let mut pair = tls_pair(config); - // System certificates should not be loaded into the trust store. The handshake - // should fail since the certificate should not be trusted. - assert!(poll_tls_pair_result(&mut pair).is_err()); + // System certificates should not be loaded into the trust store. The handshake + // should fail since the certificate should not be trusted. + assert!(poll_tls_pair_result(&mut pair).is_err()); - // The handshake should succeed after trusting the certificate. - unsafe { - s2n_tls_sys::s2n_config_load_system_certs(config_with_system_certs.as_mut_ptr()); + // The handshake should succeed after trusting the certificate. + unsafe { + s2n_tls_sys::s2n_config_load_system_certs( + config_with_system_certs.as_mut_ptr(), + ); + } + establish_connection(config_with_system_certs); } - establish_connection(config_with_system_certs); }); } diff --git a/crypto/s2n_fips.c b/crypto/s2n_fips.c index 29229dd607d..ff73433a6ce 100644 --- a/crypto/s2n_fips.c +++ b/crypto/s2n_fips.c @@ -17,11 +17,14 @@ #include +#include "utils/s2n_init.h" +#include "utils/s2n_safety.h" + #if defined(S2N_INTERN_LIBCRYPTO) && defined(OPENSSL_FIPS) #error "Interning with OpenSSL fips-validated libcrypto is not currently supported. See https://github.com/aws/s2n-tls/issues/2741" #endif -static int s2n_fips_mode = 0; +static bool s2n_fips_mode_enabled = false; /* FIPS mode can be checked if OpenSSL was configured and built for FIPS which then defines OPENSSL_FIPS. * @@ -46,17 +49,25 @@ bool s2n_libcrypto_is_fips(void) int s2n_fips_init(void) { - s2n_fips_mode = 0; - - if (s2n_libcrypto_is_fips()) { - s2n_fips_mode = 1; - } - - return 0; + s2n_fips_mode_enabled = s2n_libcrypto_is_fips(); + return S2N_SUCCESS; } /* Return 1 if FIPS mode is enabled, 0 otherwise. FIPS mode must be enabled prior to calling s2n_init(). */ -int s2n_is_in_fips_mode(void) +bool s2n_is_in_fips_mode(void) +{ + return s2n_fips_mode_enabled; +} + +int s2n_get_fips_mode(s2n_fips_mode *fips_mode) { - return s2n_fips_mode; + POSIX_ENSURE_REF(fips_mode); + *fips_mode = S2N_FIPS_MODE_DISABLED; + POSIX_ENSURE(s2n_is_initialized(), S2N_ERR_NOT_INITIALIZED); + + if (s2n_is_in_fips_mode()) { + *fips_mode = S2N_FIPS_MODE_ENABLED; + } + + return S2N_SUCCESS; } diff --git a/crypto/s2n_fips.h b/crypto/s2n_fips.h index f1047d52ae6..a353589199d 100644 --- a/crypto/s2n_fips.h +++ b/crypto/s2n_fips.h @@ -21,7 +21,7 @@ #pragma once int s2n_fips_init(void); -int s2n_is_in_fips_mode(void); +bool s2n_is_in_fips_mode(void); bool s2n_libcrypto_is_fips(void); struct s2n_cipher_suite; diff --git a/crypto/s2n_pkey.c b/crypto/s2n_pkey.c index 190c73e303a..bcc57c42422 100644 --- a/crypto/s2n_pkey.c +++ b/crypto/s2n_pkey.c @@ -115,7 +115,11 @@ int s2n_pkey_match(const struct s2n_pkey *pub_key, const struct s2n_pkey *priv_k int s2n_pkey_free(struct s2n_pkey *key) { - if (key != NULL && key->free != NULL) { + if (key == NULL) { + return S2N_SUCCESS; + } + + if (key->free != NULL) { POSIX_GUARD(key->free(key)); } diff --git a/scripts/s2n_safety_macros.py b/scripts/s2n_safety_macros.py index fbd5a5d977b..9ca973eeca8 100644 --- a/scripts/s2n_safety_macros.py +++ b/scripts/s2n_safety_macros.py @@ -539,7 +539,7 @@ def cmp_check(op): * The size of the data pointed to by both the `destination` and `source` parameters, shall be at least `len` bytes. ''', - impl='__S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), {prefix}ENSURE_REF)', + impl='__S2N_ENSURE_SAFE_MEMMOVE((destination), (source), (len), {prefix}ENSURE_REF)', harness=''' static {ret} {prefix}CHECKED_MEMCPY_harness(uint32_t* dest, uint32_t* source, size_t len) {{ diff --git a/stuffer/s2n_stuffer_network_order.c b/stuffer/s2n_stuffer_network_order.c index 9db807a60cb..88927091eb2 100644 --- a/stuffer/s2n_stuffer_network_order.c +++ b/stuffer/s2n_stuffer_network_order.c @@ -21,10 +21,14 @@ /* Writes length bytes of input to stuffer, in network order, starting from the smallest byte of input. */ int s2n_stuffer_write_network_order(struct s2n_stuffer *stuffer, const uint64_t input, const uint8_t length) { + if (length == 0) { + return S2N_SUCCESS; + } + POSIX_ENSURE_REF(stuffer); POSIX_ENSURE(length <= sizeof(input), S2N_ERR_SAFETY); POSIX_GUARD(s2n_stuffer_skip_write(stuffer, length)); - uint8_t *data = (stuffer->blob.data) ? (stuffer->blob.data + stuffer->write_cursor - length) : NULL; - + POSIX_ENSURE_REF(stuffer->blob.data); + uint8_t *data = stuffer->blob.data + stuffer->write_cursor - length; for (int i = 0; i < length; i++) { S2N_INVARIANT(i <= length); uint8_t shift = (length - i - 1) * CHAR_BIT; diff --git a/tests/cbmc/proofs/s2n_alloc/Makefile b/tests/cbmc/proofs/s2n_alloc/Makefile index 92c2fd07206..7b6c5821968 100644 --- a/tests/cbmc/proofs/s2n_alloc/Makefile +++ b/tests/cbmc/proofs/s2n_alloc/Makefile @@ -40,7 +40,7 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_result.c # We abstract these functions because manual inspection demonstrates they are unreachable. REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl REMOVE_FUNCTION_BODY += s2n_blob_slice -REMOVE_FUNCTION_BODY += s2n_ensure_memcpy_trace +REMOVE_FUNCTION_BODY += s2n_ensure_memmove_trace UNWINDSET += diff --git a/tests/cbmc/proofs/s2n_array_init/Makefile b/tests/cbmc/proofs/s2n_array_init/Makefile index 8f740b51045..48477fd21be 100644 --- a/tests/cbmc/proofs/s2n_array_init/Makefile +++ b/tests/cbmc/proofs/s2n_array_init/Makefile @@ -35,7 +35,7 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_safety.c # We abstract these functions because manual inspection demonstrates they are unreachable. REMOVE_FUNCTION_BODY += s2n_blob_slice -REMOVE_FUNCTION_BODY += s2n_ensure_memcpy_trace +REMOVE_FUNCTION_BODY += s2n_ensure_memmove_trace REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl UNWINDSET += diff --git a/tests/cbmc/proofs/s2n_array_new/Makefile b/tests/cbmc/proofs/s2n_array_new/Makefile index 389c7f0192c..6cd64107a73 100644 --- a/tests/cbmc/proofs/s2n_array_new/Makefile +++ b/tests/cbmc/proofs/s2n_array_new/Makefile @@ -38,7 +38,7 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_safety.c # We abstract these functions because manual inspection demonstrates they are unreachable. REMOVE_FUNCTION_BODY += s2n_blob_slice -REMOVE_FUNCTION_BODY += s2n_ensure_memcpy_trace +REMOVE_FUNCTION_BODY += s2n_ensure_memmove_trace REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl UNWINDSET += diff --git a/tests/cbmc/proofs/s2n_dh_compute_shared_secret_as_client/Makefile b/tests/cbmc/proofs/s2n_dh_compute_shared_secret_as_client/Makefile index ec8ef4fc519..cb7a239897c 100644 --- a/tests/cbmc/proofs/s2n_dh_compute_shared_secret_as_client/Makefile +++ b/tests/cbmc/proofs/s2n_dh_compute_shared_secret_as_client/Makefile @@ -39,7 +39,7 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_mem.c PROJECT_SOURCES += $(SRCDIR)/utils/s2n_result.c PROJECT_SOURCES += $(SRCDIR)/utils/s2n_safety.c -UNWINDSET += s2n_stuffer_write_network_order.4:9 +UNWINDSET += s2n_stuffer_write_network_order.10:9 # We abstract this function because manual inspection demonstrates it is unreachable. REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl diff --git a/tests/cbmc/proofs/s2n_dh_params_to_p_g_Ys/Makefile b/tests/cbmc/proofs/s2n_dh_params_to_p_g_Ys/Makefile index 94ca0745414..33bba982d1f 100644 --- a/tests/cbmc/proofs/s2n_dh_params_to_p_g_Ys/Makefile +++ b/tests/cbmc/proofs/s2n_dh_params_to_p_g_Ys/Makefile @@ -42,6 +42,6 @@ REMOVE_FUNCTION_BODY += s2n_free REMOVE_FUNCTION_BODY += s2n_realloc REMOVE_FUNCTION_BODY += s2n_stuffer_wipe -UNWINDSET += s2n_stuffer_write_network_order.4:9 +UNWINDSET += s2n_stuffer_write_network_order.10:9 include ../Makefile.common diff --git a/tests/cbmc/proofs/s2n_set_new/Makefile b/tests/cbmc/proofs/s2n_set_new/Makefile index 6322ae4ce0e..5cf2f575ea5 100644 --- a/tests/cbmc/proofs/s2n_set_new/Makefile +++ b/tests/cbmc/proofs/s2n_set_new/Makefile @@ -42,7 +42,7 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_set.c # We abstract these functions because manual inspection demonstrates they are unreachable. REMOVE_FUNCTION_BODY += s2n_blob_slice -REMOVE_FUNCTION_BODY += s2n_ensure_memcpy_trace +REMOVE_FUNCTION_BODY += s2n_ensure_memmove_trace REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl UNWINDSET += diff --git a/tests/cbmc/proofs/s2n_stuffer_alloc/Makefile b/tests/cbmc/proofs/s2n_stuffer_alloc/Makefile index 59795b1e168..db954284f82 100644 --- a/tests/cbmc/proofs/s2n_stuffer_alloc/Makefile +++ b/tests/cbmc/proofs/s2n_stuffer_alloc/Makefile @@ -40,7 +40,7 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_safety.c # We abstract these functions because manual inspection demonstrates they are unreachable. REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl REMOVE_FUNCTION_BODY += s2n_blob_slice -REMOVE_FUNCTION_BODY += s2n_ensure_memcpy_trace +REMOVE_FUNCTION_BODY += s2n_ensure_memmove_trace UNWINDSET += diff --git a/tests/cbmc/proofs/s2n_stuffer_growable_alloc/Makefile b/tests/cbmc/proofs/s2n_stuffer_growable_alloc/Makefile index 48ca5bebc0a..4a11bcc8189 100644 --- a/tests/cbmc/proofs/s2n_stuffer_growable_alloc/Makefile +++ b/tests/cbmc/proofs/s2n_stuffer_growable_alloc/Makefile @@ -38,7 +38,7 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_safety.c # We abstract these functions because manual inspection demonstrates they are unreachable. REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl REMOVE_FUNCTION_BODY += s2n_blob_slice -REMOVE_FUNCTION_BODY += s2n_ensure_memcpy_trace +REMOVE_FUNCTION_BODY += s2n_ensure_memmove_trace UNWINDSET += diff --git a/tests/cbmc/proofs/s2n_stuffer_resize_if_empty/Makefile b/tests/cbmc/proofs/s2n_stuffer_resize_if_empty/Makefile index daac401569b..41b69d86b55 100644 --- a/tests/cbmc/proofs/s2n_stuffer_resize_if_empty/Makefile +++ b/tests/cbmc/proofs/s2n_stuffer_resize_if_empty/Makefile @@ -35,7 +35,7 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_result.c # We abstract these functions because manual inspection demonstrates they are unreachable. REMOVE_FUNCTION_BODY += s2n_calculate_stacktrace REMOVE_FUNCTION_BODY += s2n_blob_slice -REMOVE_FUNCTION_BODY += s2n_ensure_memcpy_trace +REMOVE_FUNCTION_BODY += s2n_ensure_memmove_trace REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl UNWINDSET += diff --git a/tests/cbmc/proofs/s2n_stuffer_write_network_order/Makefile b/tests/cbmc/proofs/s2n_stuffer_write_network_order/Makefile index 4c8f38b8e79..ba093b9041a 100644 --- a/tests/cbmc/proofs/s2n_stuffer_write_network_order/Makefile +++ b/tests/cbmc/proofs/s2n_stuffer_write_network_order/Makefile @@ -38,7 +38,7 @@ REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl REMOVE_FUNCTION_BODY += s2n_blob_slice REMOVE_FUNCTION_BODY += s2n_stuffer_wipe -UNWINDSET += s2n_stuffer_write_network_order.4:9 +UNWINDSET += s2n_stuffer_write_network_order.10:9 UNWINDSET += s2n_stuffer_write_network_order_harness.0:9 include ../Makefile.common diff --git a/tests/cbmc/proofs/s2n_stuffer_write_reservation/Makefile b/tests/cbmc/proofs/s2n_stuffer_write_reservation/Makefile index fe8370b37f7..bc921b1d3ee 100644 --- a/tests/cbmc/proofs/s2n_stuffer_write_reservation/Makefile +++ b/tests/cbmc/proofs/s2n_stuffer_write_reservation/Makefile @@ -48,13 +48,6 @@ REMOVE_FUNCTION_BODY += s2n_stuffer_wipe REMOVE_FUNCTION_BODY += s2n_stuffer_wipe_n REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl -UNWINDSET += s2n_stuffer_write_network_order.0:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.1:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.2:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.3:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.4:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.5:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.6:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.7:$(MAX_WRITE_NETWORK_ORDER) +UNWINDSET += s2n_stuffer_write_network_order.10:$(MAX_WRITE_NETWORK_ORDER) include ../Makefile.common diff --git a/tests/cbmc/proofs/s2n_stuffer_write_uint16/Makefile b/tests/cbmc/proofs/s2n_stuffer_write_uint16/Makefile index 73c61bcecad..de513abf4e9 100644 --- a/tests/cbmc/proofs/s2n_stuffer_write_uint16/Makefile +++ b/tests/cbmc/proofs/s2n_stuffer_write_uint16/Makefile @@ -36,6 +36,6 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_result.c REMOVE_FUNCTION_BODY += s2n_blob_slice REMOVE_FUNCTION_BODY += s2n_stuffer_wipe -UNWINDSET += s2n_stuffer_write_network_order.4:$(shell echo $$((1 + $(SIZEOF_UINT16)))) +UNWINDSET += s2n_stuffer_write_network_order.10:$(shell echo $$((1 + $(SIZEOF_UINT16)))) include ../Makefile.common diff --git a/tests/cbmc/proofs/s2n_stuffer_write_uint24/Makefile b/tests/cbmc/proofs/s2n_stuffer_write_uint24/Makefile index acba5cf7b1e..0ee330db573 100644 --- a/tests/cbmc/proofs/s2n_stuffer_write_uint24/Makefile +++ b/tests/cbmc/proofs/s2n_stuffer_write_uint24/Makefile @@ -36,6 +36,6 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_result.c REMOVE_FUNCTION_BODY += s2n_blob_slice REMOVE_FUNCTION_BODY += s2n_stuffer_wipe -UNWINDSET += s2n_stuffer_write_network_order.4:$(shell echo $$((1 + $(SIZEOF_UINT24)))) +UNWINDSET += s2n_stuffer_write_network_order.10:$(shell echo $$((1 + $(SIZEOF_UINT24)))) include ../Makefile.common diff --git a/tests/cbmc/proofs/s2n_stuffer_write_uint32/Makefile b/tests/cbmc/proofs/s2n_stuffer_write_uint32/Makefile index aece6e2f0d0..bec46adf7eb 100644 --- a/tests/cbmc/proofs/s2n_stuffer_write_uint32/Makefile +++ b/tests/cbmc/proofs/s2n_stuffer_write_uint32/Makefile @@ -36,6 +36,6 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_result.c REMOVE_FUNCTION_BODY += s2n_blob_slice REMOVE_FUNCTION_BODY += s2n_stuffer_wipe -UNWINDSET += s2n_stuffer_write_network_order.4:$(shell echo $$((1 + $(SIZEOF_UINT32)))) +UNWINDSET += s2n_stuffer_write_network_order.10:$(shell echo $$((1 + $(SIZEOF_UINT32)))) include ../Makefile.common diff --git a/tests/cbmc/proofs/s2n_stuffer_write_uint64/Makefile b/tests/cbmc/proofs/s2n_stuffer_write_uint64/Makefile index 04f1c6b5aae..8e339851469 100644 --- a/tests/cbmc/proofs/s2n_stuffer_write_uint64/Makefile +++ b/tests/cbmc/proofs/s2n_stuffer_write_uint64/Makefile @@ -36,6 +36,6 @@ PROJECT_SOURCES += $(SRCDIR)/utils/s2n_result.c REMOVE_FUNCTION_BODY += s2n_blob_slice REMOVE_FUNCTION_BODY += s2n_stuffer_wipe -UNWINDSET += s2n_stuffer_write_network_order.4:$(shell echo $$((1 + $(SIZEOF_UINT64)))) +UNWINDSET += s2n_stuffer_write_network_order.10:$(shell echo $$((1 + $(SIZEOF_UINT64)))) include ../Makefile.common diff --git a/tests/cbmc/proofs/s2n_stuffer_write_vector_size/Makefile b/tests/cbmc/proofs/s2n_stuffer_write_vector_size/Makefile index cf3fc56cd15..350684a0681 100644 --- a/tests/cbmc/proofs/s2n_stuffer_write_vector_size/Makefile +++ b/tests/cbmc/proofs/s2n_stuffer_write_vector_size/Makefile @@ -44,13 +44,6 @@ REMOVE_FUNCTION_BODY += s2n_stuffer_resize REMOVE_FUNCTION_BODY += s2n_stuffer_wipe_n REMOVE_FUNCTION_BODY += __CPROVER_file_local_s2n_mem_c_s2n_mem_cleanup_impl -UNWINDSET += s2n_stuffer_write_network_order.0:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.1:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.2:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.3:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.4:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.5:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.6:$(MAX_WRITE_NETWORK_ORDER) -UNWINDSET += s2n_stuffer_write_network_order.7:$(MAX_WRITE_NETWORK_ORDER) +UNWINDSET += s2n_stuffer_write_network_order.10:$(MAX_WRITE_NETWORK_ORDER) include ../Makefile.common diff --git a/tests/cbmc/stubs/s2n_ensure.c b/tests/cbmc/stubs/s2n_ensure.c index 01ff888062f..ae0e5a82c47 100644 --- a/tests/cbmc/stubs/s2n_ensure.c +++ b/tests/cbmc/stubs/s2n_ensure.c @@ -15,7 +15,7 @@ #include "utils/s2n_safety.h" -void* s2n_ensure_memcpy_trace(void *restrict to, const void *restrict from, size_t size) +void* s2n_ensure_memmove_trace(void *to, const void *from, size_t size) { if (to == NULL || from == NULL) { return NULL; diff --git a/tests/cbmc/stubs/s2n_is_in_fips_mode.c b/tests/cbmc/stubs/s2n_is_in_fips_mode.c index 8a76d11bc6d..7ee61b05510 100644 --- a/tests/cbmc/stubs/s2n_is_in_fips_mode.c +++ b/tests/cbmc/stubs/s2n_is_in_fips_mode.c @@ -17,18 +17,18 @@ #include "crypto/s2n_fips.h" -static int flag = 0; -static int s2n_fips_mode = 0; +static bool flag = 0; +static bool s2n_fips_mode_enabled = 0; /** * Return 1 if FIPS mode is set, 0 otherwise, * where FIPS mode is set nondeterministically on first call. */ -int s2n_is_in_fips_mode() +bool s2n_is_in_fips_mode() { if (flag == 0) { - s2n_fips_mode = nondet_bool() ? 1 : 0; - flag = 1; + s2n_fips_mode_enabled = nondet_bool() ? 1 : 0; + flag = 1; } - return s2n_fips_mode; + return s2n_fips_mode_enabled; } diff --git a/tests/features/S2N___RESTRICT__SUPPORTED.c b/tests/features/S2N___RESTRICT__SUPPORTED.c deleted file mode 100644 index b29c32ef9ad..00000000000 --- a/tests/features/S2N___RESTRICT__SUPPORTED.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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. - */ - -void swap(int *__restrict__ left, int *__restrict__ right) { - int temp = *left; - *left = *right; - *right = temp; -} - -int main() { - int a = 1, b = 2; - swap(&a, &b); - return 0; -} - diff --git a/tests/features/S2N___RESTRICT__SUPPORTED.flags b/tests/features/S2N___RESTRICT__SUPPORTED.flags deleted file mode 100644 index 2f41be663b2..00000000000 --- a/tests/features/S2N___RESTRICT__SUPPORTED.flags +++ /dev/null @@ -1 +0,0 @@ --Werror diff --git a/tests/sidetrail/working/stubs/s2n_ensure.h b/tests/sidetrail/working/stubs/s2n_ensure.h index 521e3e56f55..179f5a52b19 100644 --- a/tests/sidetrail/working/stubs/s2n_ensure.h +++ b/tests/sidetrail/working/stubs/s2n_ensure.h @@ -31,7 +31,10 @@ void *s2n_sidetrail_memset(void * ptr, int value, size_t num); #define __S2N_ENSURE_PRECONDITION( result ) S2N_RESULT_OK #define __S2N_ENSURE_POSTCONDITION( result ) S2N_RESULT_OK -#define __S2N_ENSURE_SAFE_MEMCPY( d , s , n , guard ) do { memcpy((d), (s), (n)); } while(0) +/* memmove isn't supported, so use memcpy instead. + * For the purposes of these proofs, there should be no useful difference. + */ +#define __S2N_ENSURE_SAFE_MEMMOVE( d , s , n , guard ) do { memcpy((d), (s), (n)); } while(0) #define __S2N_ENSURE_SAFE_MEMSET( d , c , n , guard ) \ do { \ diff --git a/tests/unit/s2n_build_test.c b/tests/unit/s2n_build_test.c index 75195fe0d2a..e7f40949d15 100644 --- a/tests/unit/s2n_build_test.c +++ b/tests/unit/s2n_build_test.c @@ -84,6 +84,18 @@ int main() END_TEST(); } + /* Ensure that FIPS mode is enabled when linked to AWS-LC-FIPS, and disabled when linked to AWS-LC */ + if (strstr(s2n_libcrypto, "awslc") != NULL) { + s2n_fips_mode fips_mode = S2N_FIPS_MODE_DISABLED; + EXPECT_SUCCESS(s2n_get_fips_mode(&fips_mode)); + + if (strstr(s2n_libcrypto, "fips") != NULL) { + EXPECT_EQUAL(fips_mode, S2N_FIPS_MODE_ENABLED); + } else { + EXPECT_EQUAL(fips_mode, S2N_FIPS_MODE_DISABLED); + } + } + char s2n_libcrypto_copy[MAX_LIBCRYPTO_NAME_LEN] = { 0 }; EXPECT_TRUE(strlen(s2n_libcrypto) < MAX_LIBCRYPTO_NAME_LEN); EXPECT_OK(s2n_test_lowercase_copy(s2n_libcrypto, &s2n_libcrypto_copy[0], s2n_array_len(s2n_libcrypto_copy))); diff --git a/tests/unit/s2n_fips_test.c b/tests/unit/s2n_fips_test.c new file mode 100644 index 00000000000..c4e5bdc134e --- /dev/null +++ b/tests/unit/s2n_fips_test.c @@ -0,0 +1,53 @@ +/* +* 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. +*/ + +#include "crypto/s2n_fips.h" + +#include "api/s2n.h" +#include "s2n_test.h" + +int main() +{ + BEGIN_TEST_NO_INIT(); + + /* s2n_get_fips_mode() fails before init */ + { + s2n_fips_mode fips_mode = S2N_FIPS_MODE_ENABLED; + EXPECT_FAILURE_WITH_ERRNO(s2n_get_fips_mode(&fips_mode), S2N_ERR_NOT_INITIALIZED); + EXPECT_EQUAL(fips_mode, S2N_FIPS_MODE_DISABLED); + } + + EXPECT_SUCCESS(s2n_init()); + + /* Test s2n_get_fips_mode() after init */ + { + /* Safety */ + EXPECT_FAILURE_WITH_ERRNO(s2n_get_fips_mode(NULL), S2N_ERR_NULL); + + /* FIPS mode matches s2n_is_in_fips_mode() */ + { + s2n_fips_mode fips_mode = S2N_FIPS_MODE_DISABLED; + EXPECT_SUCCESS(s2n_get_fips_mode(&fips_mode)); + + if (s2n_is_in_fips_mode()) { + EXPECT_EQUAL(fips_mode, S2N_FIPS_MODE_ENABLED); + } else { + EXPECT_EQUAL(fips_mode, S2N_FIPS_MODE_DISABLED); + } + } + } + + END_TEST(); +} diff --git a/tests/unit/s2n_key_update_test.c b/tests/unit/s2n_key_update_test.c index 23955cdd2a8..be8bf8b1874 100644 --- a/tests/unit/s2n_key_update_test.c +++ b/tests/unit/s2n_key_update_test.c @@ -333,7 +333,7 @@ int main(int argc, char **argv) EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0)); EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&stuffer, &stuffer, client_conn)); - s2n_atomic_flag_set(&client_conn->key_update_pending); + EXPECT_SUCCESS(s2n_connection_request_key_update(client_conn, S2N_KEY_UPDATE_NOT_REQUESTED)); s2n_blocked_status blocked = 0; EXPECT_SUCCESS(s2n_key_update_send(client_conn, &blocked)); @@ -677,5 +677,27 @@ int main(int argc, char **argv) } } + /* s2n_connection_key_update_requested */ + { + /* null safety */ + { + EXPECT_FAILURE_WITH_ERRNO(s2n_connection_request_key_update(NULL, S2N_KEY_UPDATE_NOT_REQUESTED), S2N_ERR_NULL); + }; + + /* usage */ + { + DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), s2n_connection_ptr_free); + EXPECT_FAILURE_WITH_ERRNO(s2n_connection_request_key_update(conn, S2N_KEY_UPDATE_REQUESTED), S2N_ERR_INVALID_ARGUMENT); + }; + + /* happy path */ + { + DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), s2n_connection_ptr_free); + EXPECT_FALSE(s2n_atomic_flag_test(&conn->key_update_pending)); + EXPECT_SUCCESS(s2n_connection_request_key_update(conn, S2N_KEY_UPDATE_NOT_REQUESTED)); + EXPECT_TRUE(s2n_atomic_flag_test(&conn->key_update_pending)); + }; + }; + END_TEST(); } diff --git a/tests/unit/s2n_key_update_threads_test.c b/tests/unit/s2n_key_update_threads_test.c index 0a7ef4dd4c0..d54807c6587 100644 --- a/tests/unit/s2n_key_update_threads_test.c +++ b/tests/unit/s2n_key_update_threads_test.c @@ -35,7 +35,7 @@ _##name##_record_alg.encryption_limit = limit; \ name.record_alg = &_##name##_record_alg; -S2N_RESULT s2n_set_key_update_request_for_testing(keyupdate_request request); +S2N_RESULT s2n_set_key_update_request_for_testing(s2n_peer_key_update request); static void *s2n_send_random_data(void *arg) { diff --git a/tls/s2n_key_update.c b/tls/s2n_key_update.c index d10d7c5b244..90c49c9756e 100644 --- a/tls/s2n_key_update.c +++ b/tls/s2n_key_update.c @@ -24,12 +24,12 @@ #include "utils/s2n_atomic.h" #include "utils/s2n_safety.h" -static keyupdate_request key_update_request_val = S2N_KEY_UPDATE_NOT_REQUESTED; +static s2n_peer_key_update key_update_request_val = S2N_KEY_UPDATE_NOT_REQUESTED; int s2n_key_update_write(struct s2n_blob *out); int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequence_number); -S2N_RESULT s2n_set_key_update_request_for_testing(keyupdate_request request) +S2N_RESULT s2n_set_key_update_request_for_testing(s2n_peer_key_update request) { RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST); key_update_request_val = request; @@ -146,3 +146,12 @@ int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequenc return S2N_SUCCESS; } + +int s2n_connection_request_key_update(struct s2n_connection *conn, s2n_peer_key_update peer_request) +{ + POSIX_ENSURE_REF(conn); + /* s2n-tls does not currently support requesting key updates from peers */ + POSIX_ENSURE(peer_request == S2N_KEY_UPDATE_NOT_REQUESTED, S2N_ERR_INVALID_ARGUMENT); + s2n_atomic_flag_set(&conn->key_update_pending); + return S2N_SUCCESS; +} diff --git a/tls/s2n_key_update.h b/tls/s2n_key_update.h index 2b787f08487..79a103d8261 100644 --- a/tls/s2n_key_update.h +++ b/tls/s2n_key_update.h @@ -25,10 +25,5 @@ typedef enum { RECEIVING } keyupdate_status; -typedef enum { - S2N_KEY_UPDATE_NOT_REQUESTED = 0, - S2N_KEY_UPDATE_REQUESTED -} keyupdate_request; - int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request); int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked); diff --git a/tls/s2n_security_rules.c b/tls/s2n_security_rules.c index ebeefe99430..2d1513d3909 100644 --- a/tls/s2n_security_rules.c +++ b/tls/s2n_security_rules.c @@ -219,7 +219,7 @@ S2N_CLEANUP_RESULT s2n_security_rule_result_free(struct s2n_security_rule_result { if (result) { RESULT_GUARD_POSIX(s2n_stuffer_free(&result->output)); + *result = (struct s2n_security_rule_result){ 0 }; } - *result = (struct s2n_security_rule_result){ 0 }; return S2N_RESULT_OK; } diff --git a/utils/s2n_ensure.c b/utils/s2n_ensure.c index 5824f9b6186..c2350740462 100644 --- a/utils/s2n_ensure.c +++ b/utils/s2n_ensure.c @@ -15,7 +15,7 @@ #include "utils/s2n_safety.h" -void *s2n_ensure_memcpy_trace(void *restrict to, const void *restrict from, size_t size) +void *s2n_ensure_memmove_trace(void *to, const void *from, size_t size) { PTR_ENSURE_REF(to); PTR_ENSURE_REF(from); diff --git a/utils/s2n_ensure.h b/utils/s2n_ensure.h index c072d93e952..890cca162b5 100644 --- a/utils/s2n_ensure.h +++ b/utils/s2n_ensure.h @@ -60,13 +60,13 @@ #define __S2N_ENSURE_POSTCONDITION(result) (s2n_likely(s2n_result_is_ok(result)) ? S2N_RESULT_OK : S2N_RESULT_ERROR) #endif -#define __S2N_ENSURE_SAFE_MEMCPY(d, s, n, guard) \ - do { \ - __typeof(n) __tmp_n = (n); \ - if (s2n_likely(__tmp_n)) { \ - void *r = s2n_ensure_memcpy_trace((d), (s), (__tmp_n)); \ - guard(r); \ - } \ +#define __S2N_ENSURE_SAFE_MEMMOVE(d, s, n, guard) \ + do { \ + __typeof(n) __tmp_n = (n); \ + if (s2n_likely(__tmp_n)) { \ + void *r = s2n_ensure_memmove_trace((d), (s), (__tmp_n)); \ + guard(r); \ + } \ } while (0) #define __S2N_ENSURE_SAFE_MEMSET(d, c, n, guard) \ @@ -90,23 +90,7 @@ #define __S2N_ENSURE_CHECKED_RETURN(v) return v #endif -/** - * `restrict` is a part of the c99 standard and will work with any C compiler. If you're trying to - * compile with a C++ compiler `restrict` is invalid. However some C++ compilers support the behavior - * of `restrict` using the `__restrict__` keyword. Therefore if the compiler supports `__restrict__` - * use it. - * - * This is helpful for the benchmarks in tests/benchmark which use Google's Benchmark library and - * are all written in C++. - * - * https://gcc.gnu.org/onlinedocs/gcc/Restricted-Pointers.html - * - */ -#if defined(S2N___RESTRICT__SUPPORTED) -void *s2n_ensure_memcpy_trace(void *__restrict__ to, const void *__restrict__ from, size_t size); -#else -void *s2n_ensure_memcpy_trace(void *restrict to, const void *restrict from, size_t size); -#endif +void *s2n_ensure_memmove_trace(void *to, const void *from, size_t size); /** * These macros should not be used in validate functions. diff --git a/utils/s2n_map.c b/utils/s2n_map.c index b1ad6721c09..ee8bafd7c32 100644 --- a/utils/s2n_map.c +++ b/utils/s2n_map.c @@ -32,6 +32,7 @@ static S2N_RESULT s2n_map_slot(const struct s2n_map *map, struct s2n_blob *key, uint32_t *slot) { RESULT_ENSURE_REF(map); + RESULT_ENSURE(map->capacity != 0, S2N_ERR_SAFETY); union { uint8_t u8[32]; uint32_t u32[8]; diff --git a/utils/s2n_safety_macros.h b/utils/s2n_safety_macros.h index 33e5133dca4..e3896e8c360 100644 --- a/utils/s2n_safety_macros.h +++ b/utils/s2n_safety_macros.h @@ -161,7 +161,7 @@ * * The size of the data pointed to by both the `destination` and `source` parameters, * shall be at least `len` bytes. */ -#define RESULT_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), RESULT_ENSURE_REF) +#define RESULT_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMMOVE((destination), (source), (len), RESULT_ENSURE_REF) /** * Performs a safer memset @@ -357,7 +357,7 @@ * * The size of the data pointed to by both the `destination` and `source` parameters, * shall be at least `len` bytes. */ -#define POSIX_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), POSIX_ENSURE_REF) +#define POSIX_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMMOVE((destination), (source), (len), POSIX_ENSURE_REF) /** * DEPRECATED: all methods (except those in s2n.h) should return s2n_result. @@ -563,7 +563,7 @@ * * The size of the data pointed to by both the `destination` and `source` parameters, * shall be at least `len` bytes. */ -#define PTR_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), PTR_ENSURE_REF) +#define PTR_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMMOVE((destination), (source), (len), PTR_ENSURE_REF) /** * DEPRECATED: all methods (except those in s2n.h) should return s2n_result.