-
Notifications
You must be signed in to change notification settings - Fork 714
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ktls: ktls interface and building blocks #3707
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
/* | ||
* 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 | ||
* | ||
* Requesting Duplex means the Send and Recv are also requested | ||
*/ | ||
{ | ||
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_FALSE(s2n_config_is_ktls_requested(config, S2N_KTLS_MODE_SEND)); | ||
EXPECT_TRUE(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_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(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,8 @@ | |
* permissions and limitations under the License. | ||
*/ | ||
|
||
#include "tls/s2n_config.h" | ||
|
||
#include <strings.h> | ||
#include <time.h> | ||
|
||
|
@@ -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" | ||
|
@@ -1067,3 +1070,26 @@ int s2n_config_set_recv_multi_record(struct s2n_config *config, bool enabled) | |
|
||
return S2N_SUCCESS; | ||
} | ||
|
||
/* Indicates if the connection should attempt to enable kTLS. */ | ||
int s2n_config_ktls_enable(struct s2n_config *config, s2n_ktls_mode ktls_mode) | ||
{ | ||
POSIX_ENSURE_REF(config); | ||
|
||
config->ktls_mode_requested = ktls_mode; | ||
return S2N_SUCCESS; | ||
} | ||
|
||
/* Enabling Duplex mode means that both Send and Recv are also requested. */ | ||
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay maybe I don't fully understand the purpose of this function, but if it's to tell the user which mode is set, why not just:
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
@@ -1517,3 +1518,41 @@ 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am confused. Are both of these functions that you've added APIs? Why is only one declared in connection.h? |
||
{ | ||
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; | ||
} | ||
|
||
/* Indicates if the mode matches the connection's current kTLS configuration. | ||
* | ||
* Enabling Duplex mode means that both Send and Recv are also enabled. */ | ||
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; | ||
} |
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 */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this file at this point in the project? Seems like there's nothing in here that we need yet. What purpose is this function serving? |
||
|
||
return S2N_RESULT_OK; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really sure this comment is accurate. The function enables ktls, it doesn't indicate anything.