Skip to content

Commit

Permalink
ktls interface
Browse files Browse the repository at this point in the history
  • Loading branch information
toidiu committed Dec 16, 2022
1 parent c96a479 commit 9ee130d
Show file tree
Hide file tree
Showing 7 changed files with 352 additions and 2 deletions.
197 changes: 197 additions & 0 deletions tests/unit/s2n_ktls_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/*
* 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 "tls/s2n_ktls.h"

#include <stdlib.h>

#include "api/s2n.h"
#include "crypto/s2n_fips.h"
#include "s2n_test.h"
#include "testlib/s2n_testlib.h"
#include "tls/s2n_config.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_record.h"
#include "tls/s2n_security_policies.h"
#include "tls/s2n_tls13.h"

int main(int argc, char **argv)
{
BEGIN_TEST();
EXPECT_SUCCESS(s2n_disable_tls13_in_test());

const struct s2n_security_policy *default_security_policy, *tls13_security_policy, *fips_security_policy;
EXPECT_SUCCESS(s2n_find_security_policy_from_version("default_tls13", &tls13_security_policy));
EXPECT_SUCCESS(s2n_find_security_policy_from_version("default_fips", &fips_security_policy));
EXPECT_SUCCESS(s2n_find_security_policy_from_version("default", &default_security_policy));

char cert[S2N_MAX_TEST_PEM_SIZE] = { 0 };
EXPECT_SUCCESS(s2n_read_test_pem(S2N_DEFAULT_TEST_CERT_CHAIN, cert, S2N_MAX_TEST_PEM_SIZE));
char key[S2N_MAX_TEST_PEM_SIZE] = { 0 };
EXPECT_SUCCESS(s2n_read_test_pem(S2N_DEFAULT_TEST_PRIVATE_KEY, key, S2N_MAX_TEST_PEM_SIZE));

/* config default kTLS mode */
{
DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free);
EXPECT_NOT_NULL(config);
EXPECT_EQUAL(config->ktls_mode_requested, S2N_KTLS_MODE_DISABLED);
EXPECT_TRUE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_DISABLED));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_SEND));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_RECV));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_DUPLEX));
};

/* request config kTLS mode
*
* Enabling TX and RX modes is additive and equals Duplex
*/
{
DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free);
EXPECT_NOT_NULL(config);

EXPECT_SUCCESS(s2n_config_ktls_enable(config, S2N_KTLS_MODE_SEND));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_DISABLED));
EXPECT_TRUE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_SEND));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_RECV));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_DUPLEX));

EXPECT_SUCCESS(s2n_config_ktls_enable(config, S2N_KTLS_MODE_RECV));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_DISABLED));
EXPECT_TRUE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_SEND));
EXPECT_TRUE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_RECV));
EXPECT_TRUE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_DUPLEX));
};

/* ALLOW kTLS disable requested on config
*
* kTLS cannot be disabled once it has been enabled
*/
{
DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free);
EXPECT_NOT_NULL(config);

EXPECT_SUCCESS(s2n_config_ktls_enable(config, S2N_KTLS_MODE_DUPLEX));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_DISABLED));
EXPECT_TRUE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_SEND));
EXPECT_TRUE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_RECV));
EXPECT_TRUE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_DUPLEX));

EXPECT_SUCCESS(s2n_config_ktls_enable(config, S2N_KTLS_MODE_DISABLED));
EXPECT_TRUE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_DISABLED));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_SEND));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_RECV));
EXPECT_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_DUPLEX));
};

/* connection default kTLS mode */
{
DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT),
s2n_connection_ptr_free);
EXPECT_NOT_NULL(conn);
DEFER_CLEANUP(struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close);
EXPECT_SUCCESS(s2n_io_pair_init_non_blocking(&io_pair));
EXPECT_SUCCESS(s2n_connection_set_io_pair(conn, &io_pair));
EXPECT_TRUE(conn->managed_send_io);
EXPECT_TRUE(conn->managed_recv_io);

EXPECT_EQUAL(conn->ktls_mode_enabled, S2N_KTLS_MODE_DISABLED);
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DISABLED));
EXPECT_FALSE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_SEND));
EXPECT_FALSE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_RECV));
EXPECT_FALSE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DUPLEX));
};

/* enable kTLS modes
*
* Enabling TX and RX modes is additive and equals Duplex
*/
{
DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT),
s2n_connection_ptr_free);
EXPECT_NOT_NULL(conn);
DEFER_CLEANUP(struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close);
EXPECT_SUCCESS(s2n_io_pair_init_non_blocking(&io_pair));
EXPECT_SUCCESS(s2n_connection_set_io_pair(conn, &io_pair));
EXPECT_TRUE(conn->managed_send_io);
EXPECT_TRUE(conn->managed_recv_io);

EXPECT_EQUAL(conn->ktls_mode_enabled, S2N_KTLS_MODE_DISABLED);

EXPECT_OK(s2n_connection_mark_ktls_enabled(conn, S2N_KTLS_MODE_RECV));
EXPECT_FALSE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DISABLED));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_RECV));
EXPECT_FALSE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_SEND));
EXPECT_FALSE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DUPLEX));

EXPECT_OK(s2n_connection_mark_ktls_enabled(conn, S2N_KTLS_MODE_SEND));
EXPECT_FALSE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DISABLED));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_RECV));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_SEND));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DUPLEX));
};

/* enable kTLS duplex */
{
DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT),
s2n_connection_ptr_free);
EXPECT_NOT_NULL(conn);
DEFER_CLEANUP(struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close);
EXPECT_SUCCESS(s2n_io_pair_init_non_blocking(&io_pair));
EXPECT_SUCCESS(s2n_connection_set_io_pair(conn, &io_pair));
EXPECT_TRUE(conn->managed_send_io);
EXPECT_TRUE(conn->managed_recv_io);

EXPECT_EQUAL(conn->ktls_mode_enabled, S2N_KTLS_MODE_DISABLED);

EXPECT_OK(s2n_connection_mark_ktls_enabled(conn, S2N_KTLS_MODE_DUPLEX));
EXPECT_FALSE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DISABLED));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_SEND));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_RECV));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DUPLEX));
};

/* DISALLOW kTLS disable on connection
*
* kTLS cannot be disabled once it has been enabled
*
* Note: This behavior might change if we introduce a kernel patch which
* support user space fallback from kTLS.
*/
{
DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT),
s2n_connection_ptr_free);
EXPECT_NOT_NULL(conn);
DEFER_CLEANUP(struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close);
EXPECT_SUCCESS(s2n_io_pair_init_non_blocking(&io_pair));
EXPECT_SUCCESS(s2n_connection_set_io_pair(conn, &io_pair));
EXPECT_TRUE(conn->managed_send_io);
EXPECT_TRUE(conn->managed_recv_io);

EXPECT_EQUAL(conn->ktls_mode_enabled, S2N_KTLS_MODE_DISABLED);

EXPECT_OK(s2n_connection_mark_ktls_enabled(conn, S2N_KTLS_MODE_DUPLEX));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_SEND));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_RECV));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DUPLEX));

EXPECT_OK(s2n_connection_mark_ktls_enabled(conn, S2N_KTLS_MODE_DISABLED));
EXPECT_FALSE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DISABLED));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_SEND));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_RECV));
EXPECT_TRUE(s2n_connection_matches_ktls_mode(conn, S2N_KTLS_MODE_DUPLEX));
};

END_TEST();
}
28 changes: 28 additions & 0 deletions tls/s2n_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* permissions and limitations under the License.
*/

#include "tls/s2n_config.h"

#include <strings.h>
#include <time.h>

Expand All @@ -22,6 +24,7 @@
#include "error/s2n_errno.h"
#include "tls/s2n_cipher_preferences.h"
#include "tls/s2n_internal.h"
#include "tls/s2n_ktls.h"
#include "tls/s2n_security_policies.h"
#include "tls/s2n_tls13.h"
#include "utils/s2n_blob.h"
Expand Down Expand Up @@ -1067,3 +1070,28 @@ int s2n_config_set_recv_multi_record(struct s2n_config *config, bool enabled)

return S2N_SUCCESS;
}

int s2n_config_ktls_enable(struct s2n_config *config, s2n_ktls_mode ktls_mode)
{
POSIX_ENSURE_REF(config);

if (ktls_mode == S2N_KTLS_MODE_DISABLED) {
config->ktls_mode_requested = S2N_KTLS_MODE_DISABLED;
} else {
config->ktls_mode_requested |= ktls_mode;
}
return S2N_SUCCESS;
}

bool s2n_config_is_ktls_requested(struct s2n_config *config, s2n_ktls_mode ktls_mode)
{
POSIX_ENSURE_REF(config);

if (ktls_mode == S2N_KTLS_MODE_DUPLEX) {
return config->ktls_mode_requested == S2N_KTLS_MODE_DUPLEX;
}
if (ktls_mode == S2N_KTLS_MODE_DISABLED) {
return config->ktls_mode_requested == S2N_KTLS_MODE_DISABLED;
}
return config->ktls_mode_requested & ktls_mode;
}
7 changes: 7 additions & 0 deletions tls/s2n_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "crypto/s2n_certificate.h"
#include "crypto/s2n_dhe.h"
#include "tls/s2n_crl.h"
#include "tls/s2n_ktls.h"
#include "tls/s2n_psk.h"
#include "tls/s2n_renegotiate.h"
#include "tls/s2n_resume.h"
Expand Down Expand Up @@ -175,6 +176,11 @@ struct s2n_config {

void *renegotiate_request_ctx;
s2n_renegotiate_request_cb renegotiate_request_cb;

/* Depending on OS and configuration it is possible to use kTLS.
*
* This option indicates if connections should attempt to use kTLS. */
s2n_ktls_mode ktls_mode_requested;
};

S2N_CLEANUP_RESULT s2n_config_ptr_free(struct s2n_config **config);
Expand All @@ -190,3 +196,4 @@ void s2n_wipe_static_configs(void);
extern struct s2n_cert_chain_and_key *s2n_config_get_single_default_cert(struct s2n_config *config);
int s2n_config_get_num_default_certs(struct s2n_config *config);
S2N_RESULT s2n_config_wall_clock(struct s2n_config *config, uint64_t *output);
bool s2n_config_is_ktls_requested(struct s2n_config *config, s2n_ktls_mode ktls_mode);
36 changes: 36 additions & 0 deletions tls/s2n_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "tls/s2n_handshake.h"
#include "tls/s2n_internal.h"
#include "tls/s2n_kem.h"
#include "tls/s2n_ktls.h"
#include "tls/s2n_prf.h"
#include "tls/s2n_record.h"
#include "tls/s2n_resume.h"
Expand Down Expand Up @@ -1517,3 +1518,38 @@ S2N_RESULT s2n_connection_dynamic_free_in_buffer(struct s2n_connection *conn)

return S2N_RESULT_OK;
}

/* Marks s2n_ktls_mode enabled for the connection.
*
* Note: currently, kTLS cannot be disabled once enabled.
*/
S2N_RESULT s2n_connection_mark_ktls_enabled(struct s2n_connection *conn, s2n_ktls_mode ktls_mode)
{
RESULT_ENSURE_REF(conn);

/* kTLS I/O functionality is managed by s2n-tls. kTLS cannot be enabled
* if the application sets custom I/O. */
if ((ktls_mode == S2N_KTLS_MODE_SEND || ktls_mode == S2N_KTLS_MODE_DUPLEX) && !conn->managed_send_io) {
return S2N_RESULT_ERROR;
}
if ((ktls_mode == S2N_KTLS_MODE_RECV || ktls_mode == S2N_KTLS_MODE_DUPLEX) && !conn->managed_recv_io) {
return S2N_RESULT_ERROR;
}

conn->ktls_mode_enabled |= ktls_mode;

return S2N_RESULT_OK;
}

bool s2n_connection_matches_ktls_mode(struct s2n_connection *conn, s2n_ktls_mode ktls_mode)
{
POSIX_ENSURE_REF(conn);

if (ktls_mode == S2N_KTLS_MODE_DUPLEX) {
return conn->ktls_mode_enabled == S2N_KTLS_MODE_DUPLEX;
}
if (ktls_mode == S2N_KTLS_MODE_DISABLED) {
return conn->ktls_mode_enabled == S2N_KTLS_MODE_DISABLED;
}
return conn->ktls_mode_enabled & ktls_mode;
}
8 changes: 6 additions & 2 deletions tls/s2n_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ struct s2n_connection {
*/
uint16_t max_outgoing_fragment_length;

/* The number of bytes to send before changing the record size.
* If this value > 0 then dynamic TLS record size is enabled. Otherwise, the feature is disabled (default).
/* The number of bytes to send before changing the record size.
* If this value > 0 then dynamic TLS record size is enabled. Otherwise, the feature is disabled (default).
*/
uint32_t dynamic_record_resize_threshold;

Expand Down Expand Up @@ -385,6 +385,9 @@ struct s2n_connection {
uint32_t server_keying_material_lifetime;

struct s2n_post_handshake post_handshake;

/* Marks if kTLS has been enabled for this connection. */
s2n_ktls_mode ktls_mode_enabled;
};

S2N_CLEANUP_RESULT s2n_connection_ptr_free(struct s2n_connection **s2n_connection);
Expand Down Expand Up @@ -417,3 +420,4 @@ int s2n_connection_get_client_cert_chain(struct s2n_connection *conn, uint8_t **
int s2n_connection_get_peer_cert_chain(const struct s2n_connection *conn, struct s2n_cert_chain_and_key *cert_chain_and_key);
uint8_t s2n_connection_get_protocol_version(const struct s2n_connection *conn);
S2N_RESULT s2n_connection_set_max_fragment_length(struct s2n_connection *conn, uint16_t length);
S2N_RESULT s2n_connection_mark_ktls_enabled(struct s2n_connection *conn, s2n_ktls_mode mode);
26 changes: 26 additions & 0 deletions tls/s2n_ktls.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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 "s2n_ktls.h"

/*
* TODO implement
*/
S2N_RESULT s2n_ktls_enable(struct s2n_connection *conn, s2n_ktls_mode mode)
{
/* TODO perform managed_send_io and managed_recv_io checks */

return S2N_RESULT_OK;
}
Loading

0 comments on commit 9ee130d

Please sign in to comment.