Skip to content
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: add TLS1.3 support #4314

Merged
merged 6 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 101 additions & 23 deletions crypto/s2n_aead_cipher_aes_gcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,8 @@ static int s2n_aead_cipher_aes_gcm_destroy_key(struct s2n_session_key *key)

#endif

static S2N_RESULT s2n_aead_cipher_aes128_gcm_set_ktls_info(struct s2n_ktls_crypto_info_inputs *in,
struct s2n_ktls_crypto_info *out)
static S2N_RESULT s2n_tls12_aead_cipher_aes128_gcm_set_ktls_info(
struct s2n_ktls_crypto_info_inputs *in, struct s2n_ktls_crypto_info *out)
{
RESULT_ENSURE_REF(in);
RESULT_ENSURE_REF(out);
Expand All @@ -389,29 +389,49 @@ static S2N_RESULT s2n_aead_cipher_aes128_gcm_set_ktls_info(struct s2n_ktls_crypt

RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size);
RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key));

RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->iv.size);
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data, sizeof(crypto_info->iv));

RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size);
RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq));

/* The salt is a prefix of the IV
/* TLS1.2 uses partially explicit nonces. That means that although part of the
* nonce is still fixed and implicit (the salt), the remainder is explicit
* (written into the record) and must be unique per record. The RFC5288 suggests
* using the sequence number, which is how s2n-tls implements its nonces.
lrstewart marked this conversation as resolved.
Show resolved Hide resolved
*
* Therefore, ktls expects the salt to contain the iv derived from the secret
* and should generate the remainder of the nonce per-record.
*
*= https://www.rfc-editor.org/rfc/rfc4106#section-4
*# The salt field is a four-octet value that is assigned at the
*# beginning of the security association, and then remains constant
*# for the life of the security association.
* See the TLS1.2 RFC:
* - https://datatracker.ietf.org/doc/html/rfc5246#section-6.2.3.3
* And RFC5288, which defines the TLS1.2 AES-GCM cipher suites:
* - https://datatracker.ietf.org/doc/html/rfc5288#section-3
*/
RESULT_ENSURE_LTE(sizeof(crypto_info->salt), in->iv.size);
RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, sizeof(crypto_info->salt));

/* Because TLS1.2 uses partially explicit nonces, the kernel should not
* make use of the iv in crypto_info but instead use the current sequence number,
* updated with each record sent.
lrstewart marked this conversation as resolved.
Show resolved Hide resolved
*
* As of this commit, Openssl has chosen to set the TLS1.2 IV to random
* bytes when sending and all zeroes when receiving:
* https://github.com/openssl/openssl/blob/de8e0851a1c0d22533801f081781a9f0be56c2c2/ssl/record/methods/ktls_meth.c#L197-L204
* And GnuTLS has chosen to set the TLS1.2 IV to the sequence number:
* https://github.com/gnutls/gnutls/blob/3f42ae70a1672673cb8f27c2dd3da1a34d1cbdd7/lib/system/ktls.c#L547-L550
*
* We (fairly arbitrarily) choose to also set it to the current sequence number.
*/
RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->seq.size);
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->seq.data, sizeof(crypto_info->iv));
lrstewart marked this conversation as resolved.
Show resolved Hide resolved

RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info,
sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_128)));
return S2N_RESULT_OK;
}

static S2N_RESULT s2n_aead_cipher_aes256_gcm_set_ktls_info(
/* TLS1.2 AES256 is configured like TLS1.2 AES128, but with a larger key size.
* See TLS1.2 AES128 for details (particularly a discussion of salt + iv).
*/
static S2N_RESULT s2n_tls12_aead_cipher_aes256_gcm_set_ktls_info(
struct s2n_ktls_crypto_info_inputs *in, struct s2n_ktls_crypto_info *out)
{
RESULT_ENSURE_REF(in);
Expand All @@ -423,22 +443,78 @@ static S2N_RESULT s2n_aead_cipher_aes256_gcm_set_ktls_info(

RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size);
RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key));
RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size);
RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq));
RESULT_ENSURE_LTE(sizeof(crypto_info->salt), in->iv.size);
RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, sizeof(crypto_info->salt));
RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->seq.size);
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->seq.data, sizeof(crypto_info->iv));

RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->iv.size);
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data, sizeof(crypto_info->iv));
RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info,
sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_256)));
return S2N_RESULT_OK;
}

static S2N_RESULT s2n_tls13_aead_cipher_aes128_gcm_set_ktls_info(
struct s2n_ktls_crypto_info_inputs *in, struct s2n_ktls_crypto_info *out)
{
RESULT_ENSURE_REF(in);
RESULT_ENSURE_REF(out);

s2n_ktls_crypto_info_tls12_aes_gcm_128 *crypto_info = &out->ciphers.aes_gcm_128;
crypto_info->info.version = TLS_1_3_VERSION;
crypto_info->info.cipher_type = TLS_CIPHER_AES_GCM_128;

RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size);
RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key));
RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size);
RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq));

/* The salt is a prefix of the IV
/* TLS1.3 uses fully implicit nonces. The fixed, implicit IV value derived from
* the secret is xored with the sequence number to produce a unique per-record nonce.
*
*= https://www.rfc-editor.org/rfc/rfc4106#section-4
*# The salt field is a four-octet value that is assigned at the
*# beginning of the security association, and then remains constant
*# for the life of the security association.
* See the TLS1.3 RFC:
* - https://www.rfc-editor.org/rfc/rfc8446.html#section-5.3
*
* ktls handles this with the same structure as TLS1.2 uses for its partially
* explicit nonces by splitting the implicit IV between the salt and iv fields.
*/
RESULT_ENSURE_LTE(sizeof(crypto_info->salt), in->iv.size);
RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, sizeof(crypto_info->salt));
size_t salt_size = sizeof(crypto_info->salt);
RESULT_ENSURE_LTE(salt_size, in->iv.size);
RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, salt_size);
size_t iv_remainder = in->iv.size - salt_size;
RESULT_ENSURE_LTE(sizeof(crypto_info->iv), iv_remainder);
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data + salt_size, sizeof(crypto_info->iv));

RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info,
sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_128)));
return S2N_RESULT_OK;
}

/* TLS1.3 AES256 is configured like TLS1.3 AES128, but with a larger key size.
* See TLS1.3 AES128 for details (particularly a discussion of salt + iv).
*/
static S2N_RESULT s2n_tls13_aead_cipher_aes256_gcm_set_ktls_info(
struct s2n_ktls_crypto_info_inputs *in, struct s2n_ktls_crypto_info *out)
{
RESULT_ENSURE_REF(in);
RESULT_ENSURE_REF(out);

s2n_ktls_crypto_info_tls12_aes_gcm_256 *crypto_info = &out->ciphers.aes_gcm_256;
crypto_info->info.version = TLS_1_3_VERSION;
crypto_info->info.cipher_type = TLS_CIPHER_AES_GCM_256;

RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size);
RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key));
RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size);
RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq));

size_t salt_size = sizeof(crypto_info->salt);
RESULT_ENSURE_LTE(salt_size, in->iv.size);
RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, salt_size);
size_t iv_remainder = in->iv.size - salt_size;
RESULT_ENSURE_LTE(sizeof(crypto_info->iv), iv_remainder);
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data + salt_size, sizeof(crypto_info->iv));

RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info,
sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_256)));
Expand All @@ -459,7 +535,7 @@ const struct s2n_cipher s2n_aes128_gcm = {
.set_encryption_key = s2n_aead_cipher_aes128_gcm_set_encryption_key,
.set_decryption_key = s2n_aead_cipher_aes128_gcm_set_decryption_key,
.destroy_key = s2n_aead_cipher_aes_gcm_destroy_key,
.set_ktls_info = s2n_aead_cipher_aes128_gcm_set_ktls_info,
.set_ktls_info = s2n_tls12_aead_cipher_aes128_gcm_set_ktls_info,
};

const struct s2n_cipher s2n_aes256_gcm = {
Expand All @@ -476,7 +552,7 @@ const struct s2n_cipher s2n_aes256_gcm = {
.set_encryption_key = s2n_aead_cipher_aes256_gcm_set_encryption_key,
.set_decryption_key = s2n_aead_cipher_aes256_gcm_set_decryption_key,
.destroy_key = s2n_aead_cipher_aes_gcm_destroy_key,
.set_ktls_info = s2n_aead_cipher_aes256_gcm_set_ktls_info,
.set_ktls_info = s2n_tls12_aead_cipher_aes256_gcm_set_ktls_info,
};

/* TLS 1.3 GCM ciphers */
Expand All @@ -494,6 +570,7 @@ const struct s2n_cipher s2n_tls13_aes128_gcm = {
.set_encryption_key = s2n_aead_cipher_aes128_gcm_set_encryption_key_tls13,
.set_decryption_key = s2n_aead_cipher_aes128_gcm_set_decryption_key_tls13,
.destroy_key = s2n_aead_cipher_aes_gcm_destroy_key,
.set_ktls_info = s2n_tls13_aead_cipher_aes128_gcm_set_ktls_info,
};

const struct s2n_cipher s2n_tls13_aes256_gcm = {
Expand All @@ -510,4 +587,5 @@ const struct s2n_cipher s2n_tls13_aes256_gcm = {
.set_encryption_key = s2n_aead_cipher_aes256_gcm_set_encryption_key_tls13,
.set_decryption_key = s2n_aead_cipher_aes256_gcm_set_decryption_key_tls13,
.destroy_key = s2n_aead_cipher_aes_gcm_destroy_key,
.set_ktls_info = s2n_tls13_aead_cipher_aes256_gcm_set_ktls_info,
};
1 change: 1 addition & 0 deletions crypto/s2n_ktls_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
typedef struct tls12_crypto_info_aes_gcm_256 s2n_ktls_crypto_info_tls12_aes_gcm_256;
#else
#define TLS_1_2_VERSION 0
#define TLS_1_3_VERSION 0

#define TLS_CIPHER_AES_GCM_128 0
typedef struct s2n_ktls_crypto_info_stub s2n_ktls_crypto_info_tls12_aes_gcm_128;
Expand Down
17 changes: 9 additions & 8 deletions tests/features/S2N_KTLS_SUPPORTED.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,18 @@

int main()
{
/* Struct defined when kTLS support was added to linux
/* Initially ktls only supported AES-128 and TLS1.2:
* https://github.com/torvalds/linux/blob/3c4d7559159bfe1e3b94df3a657b2cda3a34e218/include/uapi/linux/tls.h
*
* However, for simplicity our ktls probe will also require AES-256 and TLS1.3.
* If this prevents some customers from using ktls, we can split our single ktls
* feature probe into more fine-grained feature probes.
*/
int versions[] = { TLS_1_2_VERSION, TLS_1_3_VERSION };
int cipher_types[] = { TLS_CIPHER_AES_GCM_128, TLS_CIPHER_AES_GCM_256 };

struct tls12_crypto_info_aes_gcm_128 aes_crypto_info_128 = { 0 };
int aes_gcm_128_cipher_type = TLS_CIPHER_AES_GCM_128;
struct tls12_crypto_info_aes_gcm_256 aes_crypto_info_256 = { 0 };
int aes_gcm_256_cipher_type = TLS_CIPHER_AES_GCM_256;
struct tls_crypto_info crypto_info = { 0 };

int get_record_type = TLS_GET_RECORD_TYPE;
int set_record_type = TLS_SET_RECORD_TYPE;

int operations[] = { TLS_GET_RECORD_TYPE, TLS_SET_RECORD_TYPE };
return 0;
}
20 changes: 10 additions & 10 deletions tests/unit/s2n_ktls_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,14 @@ int main(int argc, char **argv)
EXPECT_EQUAL(test_key.size, sizeof(value->key));
EXPECT_BYTEARRAY_EQUAL(test_key.data, value->key, sizeof(value->key));

EXPECT_TRUE(test_iv.size >= sizeof(value->iv));
EXPECT_BYTEARRAY_EQUAL(test_iv.data, value->iv, sizeof(value->iv));
EXPECT_TRUE(test_seq.size >= sizeof(value->rec_seq));
EXPECT_BYTEARRAY_EQUAL(test_seq.data, value->rec_seq, sizeof(value->rec_seq));

EXPECT_TRUE(test_iv.size >= sizeof(value->salt));
EXPECT_BYTEARRAY_EQUAL(test_iv.data, value->salt, sizeof(value->salt));

EXPECT_TRUE(test_seq.size >= sizeof(value->rec_seq));
EXPECT_BYTEARRAY_EQUAL(test_seq.data, value->rec_seq, sizeof(value->rec_seq));
EXPECT_TRUE(test_iv.size >= sizeof(value->iv));
EXPECT_BYTEARRAY_EQUAL(test_seq.data, value->iv, sizeof(value->iv));
};

/* s2n_aes256_gcm */
Expand All @@ -221,14 +221,14 @@ int main(int argc, char **argv)
EXPECT_EQUAL(test_key.size, sizeof(value->key));
EXPECT_BYTEARRAY_EQUAL(test_key.data, value->key, sizeof(value->key));

EXPECT_TRUE(test_iv.size >= sizeof(value->iv));
EXPECT_BYTEARRAY_EQUAL(test_iv.data, value->iv, sizeof(value->iv));
EXPECT_TRUE(test_seq.size >= sizeof(value->rec_seq));
EXPECT_BYTEARRAY_EQUAL(test_seq.data, value->rec_seq, sizeof(value->rec_seq));

EXPECT_TRUE(test_iv.size >= sizeof(value->salt));
EXPECT_BYTEARRAY_EQUAL(test_iv.data, value->salt, sizeof(value->salt));

EXPECT_TRUE(test_seq.size >= sizeof(value->rec_seq));
EXPECT_BYTEARRAY_EQUAL(test_seq.data, value->rec_seq, sizeof(value->rec_seq));
EXPECT_TRUE(test_iv.size >= sizeof(value->iv));
EXPECT_BYTEARRAY_EQUAL(test_seq.data, value->iv, sizeof(value->iv));
};
};

Expand Down Expand Up @@ -303,13 +303,13 @@ int main(int argc, char **argv)
EXPECT_FAILURE_WITH_ERRNO(s2n_connection_ktls_enable_recv(server_conn), S2N_ERR_HANDSHAKE_NOT_COMPLETE);
};

/* Fail if unsupported protocols */
/* Fail if unsupported protocol */
{
DEFER_CLEANUP(struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER),
s2n_connection_ptr_free);
EXPECT_OK(s2n_test_configure_connection_for_ktls(server_conn));

server_conn->actual_protocol_version = S2N_TLS13;
server_conn->actual_protocol_version = S2N_TLS13 + 1;
EXPECT_FAILURE_WITH_ERRNO(s2n_connection_ktls_enable_send(server_conn), S2N_ERR_KTLS_UNSUPPORTED_CONN);

server_conn->actual_protocol_version = S2N_TLS11;
Expand Down
Loading
Loading