Skip to content

Commit

Permalink
Merge branch 'main' into nix_head
Browse files Browse the repository at this point in the history
  • Loading branch information
dougch authored Jun 7, 2024
2 parents 39ffe76 + 114ccab commit ce36cf2
Show file tree
Hide file tree
Showing 34 changed files with 1,202 additions and 91 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ if (BUILD_TESTING)
add_test(NAME ${test_target}
COMMAND
pytest
-x -n=${N} --maxfail=1 --reruns=0 --cache-clear -rpfsq
-x -n=${N} --reruns=2 --durations=10 --cache-clear -rpfsq
-o log_cli=true --log-cli-level=DEBUG --provider-version=$ENV{S2N_LIBCRYPTO}
--provider-criterion=off --fips-mode=0 --no-pq=0 ${test_file_path}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/integrationv2
Expand Down
43 changes: 42 additions & 1 deletion api/s2n.h
Original file line number Diff line number Diff line change
Expand Up @@ -1973,6 +1973,32 @@ S2N_API extern int s2n_connection_set_blinding(struct s2n_connection *conn, s2n_
*/
S2N_API extern uint64_t s2n_connection_get_delay(struct s2n_connection *conn);

/**
* Configures the maximum blinding delay enforced after errors.
*
* Blinding protects your application from timing side channel attacks like Lucky13. While s2n-tls
* implements other, more specific mitigations for known timing side channels, blinding is important
* as a defense against currently unknown or unreported timing attacks.
*
* Setting a maximum delay lower than the recommended default (30s) will make timing attacks against
* your application easier. The lower you set the delay, the fewer requests and less total time an
* attacker will require to execute an attack. If you must lower the delay for reasons such as client
* timeouts, then you should choose the highest value practically possible to limit your risk.
*
* If you lower the blinding delay, you should also consider implementing monitoring and filtering
* to detect and reject suspicious traffic that could be gathering timing information from a potential
* side channel. Timing attacks usually involve repeatedly triggering TLS errors.
*
* @warning Do NOT set a lower blinding delay unless you understand the risks and have other
* mitigations for timing side channels in place.
*
* @param config The config object being updated.
* @param seconds The maximum number of seconds that s2n-tls will delay for in the event of a
* sensitive error.
* @returns S2N_SUCCESS on success. S2N_FAILURE on failure.
*/
S2N_API extern int s2n_config_set_max_blinding_delay(struct s2n_config *config, uint32_t seconds);

/**
* Sets the cipher preference override for the s2n_connection. Calling this function is not necessary
* unless you want to set the cipher preferences on the connection to something different than what is in the s2n_config.
Expand Down Expand Up @@ -2291,7 +2317,22 @@ S2N_API extern int s2n_shutdown_send(struct s2n_connection *conn, s2n_blocked_st
/**
* Used to declare what type of client certificate authentication to use.
*
* Currently the default for s2n-tls is for neither the server side or the client side to use Client (aka Mutual) authentication.
* A s2n_connection will enforce client certificate authentication (mTLS) differently based on
* the `s2n_cert_auth_type` and `s2n_mode` (client/server) of the connection, as described below.
*
* Server behavior:
* - None (default): Will not request client authentication.
* - Optional: Request the client's certificate and validate it. If no certificate is received then
* no validation is performed.
* - Required: Request the client's certificate and validate it. Abort the handshake if a client
* certificate is not received.
*
* Client behavior:
* - None: Abort the handshake if the server requests client authentication.
* - Optional (default): Sends the client certificate if the server requests client
* authentication. No certificate is sent if the application hasn't provided a certificate.
* - Required: Send the client certificate. Abort the handshake if the server doesn't request
* client authentication or if the application hasn't provided a certificate.
*/
typedef enum {
S2N_CERT_AUTH_NONE,
Expand Down
2 changes: 1 addition & 1 deletion bindings/rust/s2n-tls-sys/templates/Cargo.template
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "s2n-tls-sys"
description = "A C99 implementation of the TLS/SSL protocols"
version = "0.2.6"
version = "0.2.7"
authors = ["AWS s2n"]
edition = "2021"
rust-version = "1.63.0"
Expand Down
4 changes: 2 additions & 2 deletions bindings/rust/s2n-tls-tokio/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "s2n-tls-tokio"
description = "An implementation of TLS streams for Tokio built on top of s2n-tls"
version = "0.2.6"
version = "0.2.7"
authors = ["AWS s2n"]
edition = "2021"
rust-version = "1.63.0"
Expand All @@ -15,7 +15,7 @@ default = []
errno = { version = "0.3" }
libc = { version = "0.2" }
pin-project-lite = { version = "0.2" }
s2n-tls = { version = "=0.2.6", path = "../s2n-tls" }
s2n-tls = { version = "=0.2.7", path = "../s2n-tls" }
tokio = { version = "1", features = ["net", "time"] }

[dev-dependencies]
Expand Down
4 changes: 2 additions & 2 deletions bindings/rust/s2n-tls/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "s2n-tls"
description = "A C99 implementation of the TLS/SSL protocols"
version = "0.2.6"
version = "0.2.7"
authors = ["AWS s2n"]
edition = "2021"
rust-version = "1.63.0"
Expand All @@ -21,7 +21,7 @@ testing = ["bytes"]
bytes = { version = "1", optional = true }
errno = { version = "0.3" }
libc = "0.2"
s2n-tls-sys = { version = "=0.2.6", path = "../s2n-tls-sys", features = ["internal"] }
s2n-tls-sys = { version = "=0.2.7", path = "../s2n-tls-sys", features = ["internal"] }
pin-project-lite = "0.2"
hex = "0.4"

Expand Down
6 changes: 6 additions & 0 deletions bindings/rust/s2n-tls/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,12 @@ impl Builder {
Ok(self)
}

/// Sets a configurable blinding delay instead of the default
pub fn set_max_blinding_delay(&mut self, seconds: u32) -> Result<&mut Self, Error> {
unsafe { s2n_config_set_max_blinding_delay(self.as_mut_ptr(), seconds).into_result() }?;
Ok(self)
}

pub fn build(mut self) -> Result<Config, Error> {
if self.load_system_certs {
unsafe {
Expand Down
20 changes: 18 additions & 2 deletions crypto/s2n_evp_signing.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "crypto/s2n_pkey.h"
#include "crypto/s2n_rsa_pss.h"
#include "error/s2n_errno.h"
#include "tls/s2n_signature_algorithms.h"
#include "utils/s2n_safety.h"

DEFINE_POINTER_CLEANUP_FUNC(EVP_PKEY_CTX *, EVP_PKEY_CTX_free);
Expand All @@ -41,11 +42,11 @@ static S2N_RESULT s2n_evp_md_ctx_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pct

static S2N_RESULT s2n_evp_pkey_set_rsa_pss_saltlen(EVP_PKEY_CTX *pctx)
{
#if RSA_PSS_SIGNING_SUPPORTED
#if defined(S2N_LIBCRYPTO_SUPPORTS_RSA_PSS_SIGNING)
RESULT_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST), S2N_ERR_PKEY_CTX_INIT);
return S2N_RESULT_OK;
#else
RESULT_BAIL(S2N_ERR_UNIMPLEMENTED);
RESULT_BAIL(S2N_ERR_RSA_PSS_NOT_SUPPORTED);
#endif
}

Expand Down Expand Up @@ -97,6 +98,20 @@ static S2N_RESULT s2n_evp_signing_validate_hash_alg(s2n_signature_algorithm sig_
return S2N_RESULT_OK;
}

static S2N_RESULT s2n_evp_signing_validate_sig_alg(const struct s2n_pkey *key, s2n_signature_algorithm sig_alg)
{
RESULT_ENSURE_REF(key);

/* Ensure that the signature algorithm type matches the key type. */
s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN;
RESULT_GUARD(s2n_pkey_get_type(key->pkey, &pkey_type));
s2n_pkey_type sig_alg_type = S2N_PKEY_TYPE_UNKNOWN;
RESULT_GUARD(s2n_signature_algorithm_get_pkey_type(sig_alg, &sig_alg_type));
RESULT_ENSURE(pkey_type == sig_alg_type, S2N_ERR_INVALID_SIGNATURE_ALGORITHM);

return S2N_RESULT_OK;
}

int s2n_evp_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig_alg,
struct s2n_hash_state *hash_state, struct s2n_blob *signature)
{
Expand Down Expand Up @@ -136,6 +151,7 @@ int s2n_evp_verify(const struct s2n_pkey *pub, s2n_signature_algorithm sig_alg,
POSIX_ENSURE_REF(signature);
POSIX_ENSURE(s2n_evp_signing_supported(), S2N_ERR_HASH_NOT_READY);
POSIX_GUARD_RESULT(s2n_evp_signing_validate_hash_alg(sig_alg, hash_state->alg));
POSIX_GUARD_RESULT(s2n_evp_signing_validate_sig_alg(pub, sig_alg));

DEFER_CLEANUP(EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pub->pkey, NULL), EVP_PKEY_CTX_free_pointer);
POSIX_ENSURE_REF(pctx);
Expand Down
38 changes: 29 additions & 9 deletions crypto/s2n_pkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,30 @@ S2N_RESULT s2n_asn1der_to_public_key_and_type(struct s2n_pkey *pub_key,
return S2N_RESULT_OK;
}

S2N_RESULT s2n_pkey_get_type(EVP_PKEY *evp_pkey, s2n_pkey_type *pkey_type)
{
RESULT_ENSURE_REF(evp_pkey);
RESULT_ENSURE_REF(pkey_type);
*pkey_type = S2N_PKEY_TYPE_UNKNOWN;

int type = EVP_PKEY_base_id(evp_pkey);
switch (type) {
case EVP_PKEY_RSA:
*pkey_type = S2N_PKEY_TYPE_RSA;
break;
case EVP_PKEY_RSA_PSS:
*pkey_type = S2N_PKEY_TYPE_RSA_PSS;
break;
case EVP_PKEY_EC:
*pkey_type = S2N_PKEY_TYPE_ECDSA;
break;
default:
RESULT_BAIL(S2N_ERR_DECODE_CERTIFICATE);
}

return S2N_RESULT_OK;
}

S2N_RESULT s2n_pkey_from_x509(X509 *cert, struct s2n_pkey *pub_key_out,
s2n_pkey_type *pkey_type_out)
{
Expand All @@ -204,23 +228,19 @@ S2N_RESULT s2n_pkey_from_x509(X509 *cert, struct s2n_pkey *pub_key_out,
DEFER_CLEANUP(EVP_PKEY *evp_public_key = X509_get_pubkey(cert), EVP_PKEY_free_pointer);
RESULT_ENSURE(evp_public_key != NULL, S2N_ERR_DECODE_CERTIFICATE);

/* Check for success in decoding certificate according to type */
int type = EVP_PKEY_base_id(evp_public_key);
switch (type) {
case EVP_PKEY_RSA:
RESULT_GUARD(s2n_pkey_get_type(evp_public_key, pkey_type_out));
switch (*pkey_type_out) {
case S2N_PKEY_TYPE_RSA:
RESULT_GUARD(s2n_rsa_pkey_init(pub_key_out));
RESULT_GUARD(s2n_evp_pkey_to_rsa_public_key(&pub_key_out->key.rsa_key, evp_public_key));
*pkey_type_out = S2N_PKEY_TYPE_RSA;
break;
case EVP_PKEY_RSA_PSS:
case S2N_PKEY_TYPE_RSA_PSS:
RESULT_GUARD(s2n_rsa_pss_pkey_init(pub_key_out));
RESULT_GUARD(s2n_evp_pkey_to_rsa_pss_public_key(&pub_key_out->key.rsa_key, evp_public_key));
*pkey_type_out = S2N_PKEY_TYPE_RSA_PSS;
break;
case EVP_PKEY_EC:
case S2N_PKEY_TYPE_ECDSA:
RESULT_GUARD(s2n_ecdsa_pkey_init(pub_key_out));
RESULT_GUARD(s2n_evp_pkey_to_ecdsa_public_key(&pub_key_out->key.ecdsa_key, evp_public_key));
*pkey_type_out = S2N_PKEY_TYPE_ECDSA;
break;
default:
RESULT_BAIL(S2N_ERR_DECODE_CERTIFICATE);
Expand Down
1 change: 1 addition & 0 deletions crypto/s2n_pkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,6 @@ int s2n_pkey_free(struct s2n_pkey *pkey);

S2N_RESULT s2n_asn1der_to_private_key(struct s2n_pkey *priv_key, struct s2n_blob *asn1der, int type_hint);
S2N_RESULT s2n_asn1der_to_public_key_and_type(struct s2n_pkey *pub_key, s2n_pkey_type *pkey_type, struct s2n_blob *asn1der);
S2N_RESULT s2n_pkey_get_type(EVP_PKEY *evp_pkey, s2n_pkey_type *pkey_type);
S2N_RESULT s2n_pkey_from_x509(X509 *cert, struct s2n_pkey *pub_key_out,
s2n_pkey_type *pkey_type_out);
2 changes: 1 addition & 1 deletion crypto/s2n_rsa_pss.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
*
* This feature requires this Openssl commit for Openssl 1.1.x versions: openssl/openssl@4088b92
*/
#if RSA_PSS_SIGNING_SUPPORTED && OPENSSL_VERSION_NUMBER > 0x1010104fL
#if defined(S2N_LIBCRYPTO_SUPPORTS_RSA_PSS_SIGNING) && OPENSSL_VERSION_NUMBER > 0x1010104fL
#define RSA_PSS_CERTS_SUPPORTED 1
#else
#define RSA_PSS_CERTS_SUPPORTED 0
Expand Down
8 changes: 6 additions & 2 deletions crypto/s2n_rsa_signing.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,14 @@ int s2n_rsa_pkcs1v15_verify(const struct s2n_pkey *pub, struct s2n_hash_state *d
/* this function returns whether RSA PSS signing is supported */
int s2n_is_rsa_pss_signing_supported()
{
return RSA_PSS_SIGNING_SUPPORTED;
#if defined(S2N_LIBCRYPTO_SUPPORTS_RSA_PSS_SIGNING)
return 1;
#else
return 0;
#endif
}

#if RSA_PSS_SIGNING_SUPPORTED
#if defined(S2N_LIBCRYPTO_SUPPORTS_RSA_PSS_SIGNING)

static int s2n_evp_pkey_ctx_set_rsa_signature_digest(EVP_PKEY_CTX *ctx, const EVP_MD *digest_alg)
{
Expand Down
7 changes: 0 additions & 7 deletions crypto/s2n_rsa_signing.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@
#include "crypto/s2n_rsa.h"
#include "utils/s2n_blob.h"

/* Check for libcrypto 1.1 for RSA PSS Signing and EV_Key usage */
#if (S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 1) || defined(OPENSSL_IS_AWSLC)) && !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
#define RSA_PSS_SIGNING_SUPPORTED 1
#else
#define RSA_PSS_SIGNING_SUPPORTED 0
#endif

int s2n_rsa_pkcs1v15_sign(const struct s2n_pkey *priv, struct s2n_hash_state *digest, struct s2n_blob *signature);
int s2n_rsa_pkcs1v15_verify(const struct s2n_pkey *pub, struct s2n_hash_state *digest, struct s2n_blob *signature);

Expand Down
23 changes: 23 additions & 0 deletions tests/features/S2N_LIBCRYPTO_SUPPORTS_EVP_AEAD_TLS.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 <openssl/aead.h>

int main()
{
EVP_aead_aes_256_gcm_tls13();
EVP_aead_aes_128_gcm_tls13();
return 0;
}
Empty file.
23 changes: 23 additions & 0 deletions tests/features/S2N_LIBCRYPTO_SUPPORTS_RSA_PSS_SIGNING.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 <openssl/evp.h>
#include <openssl/rsa.h>

int main()
{
EVP_PKEY_CTX_set_rsa_pss_saltlen(NULL, RSA_PSS_SALTLEN_DIGEST);
return 0;
}
Empty file.
2 changes: 2 additions & 0 deletions tests/integrationv2/test_happy_path.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import platform
import pytest

from configuration import available_ports, ALL_TEST_CIPHERS, ALL_TEST_CURVES, ALL_TEST_CERTS, PROTOCOLS
Expand Down Expand Up @@ -66,6 +67,7 @@ def test_s2n_server_happy_path(managed_process, cipher, provider, curve, protoco
cipher.name)) in server_results.stdout


@pytest.mark.flaky(reruns=5, reruns_delay=2, condition=platform.machine().startswith("aarch"))
@pytest.mark.uncollect_if(func=invalid_test_parameters)
@pytest.mark.parametrize("cipher", ALL_TEST_CIPHERS, ids=get_parameter_name)
@pytest.mark.parametrize("provider", [S2N, OpenSSL, GnuTLS, SSLv3Provider])
Expand Down
2 changes: 2 additions & 0 deletions tests/integrationv2/test_record_padding.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import platform
import pytest
import re

Expand Down Expand Up @@ -123,6 +124,7 @@ def test_s2n_server_handles_padded_records(managed_process, cipher, provider, cu
cipher.name)) in server_results.stdout


@pytest.mark.flaky(reruns=5, reruns_delay=2, condition=platform.machine().startswith("aarch"))
@pytest.mark.uncollect_if(func=invalid_test_parameters)
@pytest.mark.parametrize("cipher", TLS13_CIPHERS, ids=get_parameter_name)
@pytest.mark.parametrize("provider", [OpenSSL])
Expand Down
7 changes: 5 additions & 2 deletions tests/integrationv2/test_renegotiate.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import platform
import pytest
import random

Expand Down Expand Up @@ -188,13 +189,13 @@ def basic_reneg_test(managed_process, cipher, curve, certificate, protocol, prov

server = managed_process(provider, server_options,
send_marker=Msg.send_markers(messages, Provider.ServerMode),
timeout=5
timeout=8
)

s2n_client = managed_process(S2N, client_options,
send_marker=Msg.send_markers(messages, Provider.ClientMode),
close_marker=Msg.close_marker(messages),
timeout=5
timeout=8
)

return (s2n_client, server)
Expand Down Expand Up @@ -292,6 +293,7 @@ def test_s2n_client_renegotiate_with_openssl(managed_process, cipher, curve, cer
"""


@pytest.mark.flaky(reruns=3, reruns_delay=1, condition=platform.machine().startswith("aarch"))
@pytest.mark.uncollect_if(func=invalid_test_parameters)
@pytest.mark.parametrize("cipher", ALL_TEST_CIPHERS, ids=get_parameter_name)
@pytest.mark.parametrize("curve", ALL_TEST_CURVES, ids=get_parameter_name)
Expand Down Expand Up @@ -341,6 +343,7 @@ def test_s2n_client_renegotiate_with_client_auth_with_openssl(managed_process, c
"""


@pytest.mark.flaky(reruns=3, reruns_delay=1, condition=platform.machine().startswith("aarch"))
@pytest.mark.uncollect_if(func=invalid_test_parameters)
@pytest.mark.parametrize("cipher", ALL_TEST_CIPHERS, ids=get_parameter_name)
@pytest.mark.parametrize("curve", ALL_TEST_CURVES, ids=get_parameter_name)
Expand Down
Loading

0 comments on commit ce36cf2

Please sign in to comment.