Skip to content

Commit 0fb3769

Browse files
authored
ktls: add TLS1.3 support (#4314)
1 parent 72aa95d commit 0fb3769

9 files changed

+305
-80
lines changed

crypto/s2n_aead_cipher_aes_gcm.c

+100-23
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ static int s2n_aead_cipher_aes_gcm_destroy_key(struct s2n_session_key *key)
377377

378378
#endif
379379

380-
static S2N_RESULT s2n_aead_cipher_aes128_gcm_set_ktls_info(struct s2n_ktls_crypto_info_inputs *in,
381-
struct s2n_ktls_crypto_info *out)
380+
static S2N_RESULT s2n_tls12_aead_cipher_aes128_gcm_set_ktls_info(
381+
struct s2n_ktls_crypto_info_inputs *in, struct s2n_ktls_crypto_info *out)
382382
{
383383
RESULT_ENSURE_REF(in);
384384
RESULT_ENSURE_REF(out);
@@ -389,29 +389,48 @@ static S2N_RESULT s2n_aead_cipher_aes128_gcm_set_ktls_info(struct s2n_ktls_crypt
389389

390390
RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size);
391391
RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key));
392-
393-
RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->iv.size);
394-
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data, sizeof(crypto_info->iv));
395-
396392
RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size);
397393
RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq));
398394

399-
/* The salt is a prefix of the IV
395+
/* TLS1.2 uses partially explicit nonces. That means that although part of the
396+
* nonce is still fixed and implicit (the salt), the remainder is explicit
397+
* (written into the record) and must be unique per record. The RFC5288 suggests
398+
* using the sequence number as the explicit part.
399+
*
400+
* Therefore, ktls expects the salt to contain the iv derived from the secret
401+
* and should generate the remainder of the nonce per-record.
400402
*
401-
*= https://www.rfc-editor.org/rfc/rfc4106#section-4
402-
*# The salt field is a four-octet value that is assigned at the
403-
*# beginning of the security association, and then remains constant
404-
*# for the life of the security association.
403+
* See the TLS1.2 RFC:
404+
* - https://datatracker.ietf.org/doc/html/rfc5246#section-6.2.3.3
405+
* And RFC5288, which defines the TLS1.2 AES-GCM cipher suites:
406+
* - https://datatracker.ietf.org/doc/html/rfc5288#section-3
405407
*/
406408
RESULT_ENSURE_LTE(sizeof(crypto_info->salt), in->iv.size);
407409
RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, sizeof(crypto_info->salt));
408410

411+
/* Because TLS1.2 uses partially explicit nonces, the kernel should not
412+
* use the iv in crypto_info but instead use a unique value for each record.
413+
*
414+
* As of this commit, Openssl has chosen to set the TLS1.2 IV to random
415+
* bytes when sending and all zeroes when receiving:
416+
* https://github.com/openssl/openssl/blob/de8e0851a1c0d22533801f081781a9f0be56c2c2/ssl/record/methods/ktls_meth.c#L197-L204
417+
* And GnuTLS has chosen to set the TLS1.2 IV to the sequence number:
418+
* https://github.com/gnutls/gnutls/blob/3f42ae70a1672673cb8f27c2dd3da1a34d1cbdd7/lib/system/ktls.c#L547-L550
419+
*
420+
* We (fairly arbitrarily) choose to also set it to the current sequence number.
421+
*/
422+
RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->seq.size);
423+
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->seq.data, sizeof(crypto_info->iv));
424+
409425
RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info,
410426
sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_128)));
411427
return S2N_RESULT_OK;
412428
}
413429

414-
static S2N_RESULT s2n_aead_cipher_aes256_gcm_set_ktls_info(
430+
/* TLS1.2 AES256 is configured like TLS1.2 AES128, but with a larger key size.
431+
* See TLS1.2 AES128 for details (particularly a discussion of salt + iv).
432+
*/
433+
static S2N_RESULT s2n_tls12_aead_cipher_aes256_gcm_set_ktls_info(
415434
struct s2n_ktls_crypto_info_inputs *in, struct s2n_ktls_crypto_info *out)
416435
{
417436
RESULT_ENSURE_REF(in);
@@ -423,22 +442,78 @@ static S2N_RESULT s2n_aead_cipher_aes256_gcm_set_ktls_info(
423442

424443
RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size);
425444
RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key));
445+
RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size);
446+
RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq));
447+
RESULT_ENSURE_LTE(sizeof(crypto_info->salt), in->iv.size);
448+
RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, sizeof(crypto_info->salt));
449+
RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->seq.size);
450+
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->seq.data, sizeof(crypto_info->iv));
426451

427-
RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->iv.size);
428-
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data, sizeof(crypto_info->iv));
452+
RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info,
453+
sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_256)));
454+
return S2N_RESULT_OK;
455+
}
456+
457+
static S2N_RESULT s2n_tls13_aead_cipher_aes128_gcm_set_ktls_info(
458+
struct s2n_ktls_crypto_info_inputs *in, struct s2n_ktls_crypto_info *out)
459+
{
460+
RESULT_ENSURE_REF(in);
461+
RESULT_ENSURE_REF(out);
462+
463+
s2n_ktls_crypto_info_tls12_aes_gcm_128 *crypto_info = &out->ciphers.aes_gcm_128;
464+
crypto_info->info.version = TLS_1_3_VERSION;
465+
crypto_info->info.cipher_type = TLS_CIPHER_AES_GCM_128;
429466

467+
RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size);
468+
RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key));
430469
RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size);
431470
RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq));
432471

433-
/* The salt is a prefix of the IV
472+
/* TLS1.3 uses fully implicit nonces. The fixed, implicit IV value derived from
473+
* the secret is xored with the sequence number to produce a unique per-record nonce.
434474
*
435-
*= https://www.rfc-editor.org/rfc/rfc4106#section-4
436-
*# The salt field is a four-octet value that is assigned at the
437-
*# beginning of the security association, and then remains constant
438-
*# for the life of the security association.
475+
* See the TLS1.3 RFC:
476+
* - https://www.rfc-editor.org/rfc/rfc8446.html#section-5.3
477+
*
478+
* ktls handles this with the same structure as TLS1.2 uses for its partially
479+
* explicit nonces by splitting the implicit IV between the salt and iv fields.
439480
*/
440-
RESULT_ENSURE_LTE(sizeof(crypto_info->salt), in->iv.size);
441-
RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, sizeof(crypto_info->salt));
481+
size_t salt_size = sizeof(crypto_info->salt);
482+
RESULT_ENSURE_LTE(salt_size, in->iv.size);
483+
RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, salt_size);
484+
size_t iv_remainder = in->iv.size - salt_size;
485+
RESULT_ENSURE_LTE(sizeof(crypto_info->iv), iv_remainder);
486+
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data + salt_size, sizeof(crypto_info->iv));
487+
488+
RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info,
489+
sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_128)));
490+
return S2N_RESULT_OK;
491+
}
492+
493+
/* TLS1.3 AES256 is configured like TLS1.3 AES128, but with a larger key size.
494+
* See TLS1.3 AES128 for details (particularly a discussion of salt + iv).
495+
*/
496+
static S2N_RESULT s2n_tls13_aead_cipher_aes256_gcm_set_ktls_info(
497+
struct s2n_ktls_crypto_info_inputs *in, struct s2n_ktls_crypto_info *out)
498+
{
499+
RESULT_ENSURE_REF(in);
500+
RESULT_ENSURE_REF(out);
501+
502+
s2n_ktls_crypto_info_tls12_aes_gcm_256 *crypto_info = &out->ciphers.aes_gcm_256;
503+
crypto_info->info.version = TLS_1_3_VERSION;
504+
crypto_info->info.cipher_type = TLS_CIPHER_AES_GCM_256;
505+
506+
RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size);
507+
RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key));
508+
RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size);
509+
RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq));
510+
511+
size_t salt_size = sizeof(crypto_info->salt);
512+
RESULT_ENSURE_LTE(salt_size, in->iv.size);
513+
RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, salt_size);
514+
size_t iv_remainder = in->iv.size - salt_size;
515+
RESULT_ENSURE_LTE(sizeof(crypto_info->iv), iv_remainder);
516+
RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data + salt_size, sizeof(crypto_info->iv));
442517

443518
RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info,
444519
sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_256)));
@@ -459,7 +534,7 @@ const struct s2n_cipher s2n_aes128_gcm = {
459534
.set_encryption_key = s2n_aead_cipher_aes128_gcm_set_encryption_key,
460535
.set_decryption_key = s2n_aead_cipher_aes128_gcm_set_decryption_key,
461536
.destroy_key = s2n_aead_cipher_aes_gcm_destroy_key,
462-
.set_ktls_info = s2n_aead_cipher_aes128_gcm_set_ktls_info,
537+
.set_ktls_info = s2n_tls12_aead_cipher_aes128_gcm_set_ktls_info,
463538
};
464539

465540
const struct s2n_cipher s2n_aes256_gcm = {
@@ -476,7 +551,7 @@ const struct s2n_cipher s2n_aes256_gcm = {
476551
.set_encryption_key = s2n_aead_cipher_aes256_gcm_set_encryption_key,
477552
.set_decryption_key = s2n_aead_cipher_aes256_gcm_set_decryption_key,
478553
.destroy_key = s2n_aead_cipher_aes_gcm_destroy_key,
479-
.set_ktls_info = s2n_aead_cipher_aes256_gcm_set_ktls_info,
554+
.set_ktls_info = s2n_tls12_aead_cipher_aes256_gcm_set_ktls_info,
480555
};
481556

482557
/* TLS 1.3 GCM ciphers */
@@ -494,6 +569,7 @@ const struct s2n_cipher s2n_tls13_aes128_gcm = {
494569
.set_encryption_key = s2n_aead_cipher_aes128_gcm_set_encryption_key_tls13,
495570
.set_decryption_key = s2n_aead_cipher_aes128_gcm_set_decryption_key_tls13,
496571
.destroy_key = s2n_aead_cipher_aes_gcm_destroy_key,
572+
.set_ktls_info = s2n_tls13_aead_cipher_aes128_gcm_set_ktls_info,
497573
};
498574

499575
const struct s2n_cipher s2n_tls13_aes256_gcm = {
@@ -510,4 +586,5 @@ const struct s2n_cipher s2n_tls13_aes256_gcm = {
510586
.set_encryption_key = s2n_aead_cipher_aes256_gcm_set_encryption_key_tls13,
511587
.set_decryption_key = s2n_aead_cipher_aes256_gcm_set_decryption_key_tls13,
512588
.destroy_key = s2n_aead_cipher_aes_gcm_destroy_key,
589+
.set_ktls_info = s2n_tls13_aead_cipher_aes256_gcm_set_ktls_info,
513590
};

crypto/s2n_ktls_crypto.h

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
typedef struct tls12_crypto_info_aes_gcm_256 s2n_ktls_crypto_info_tls12_aes_gcm_256;
2626
#else
2727
#define TLS_1_2_VERSION 0
28+
#define TLS_1_3_VERSION 0
2829

2930
#define TLS_CIPHER_AES_GCM_128 0
3031
typedef struct s2n_ktls_crypto_info_stub s2n_ktls_crypto_info_tls12_aes_gcm_128;

tests/features/S2N_KTLS_SUPPORTED.c

+9-8
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,18 @@
2020

2121
int main()
2222
{
23-
/* Struct defined when kTLS support was added to linux
23+
/* Initially ktls only supported AES-128 and TLS1.2:
2424
* https://github.com/torvalds/linux/blob/3c4d7559159bfe1e3b94df3a657b2cda3a34e218/include/uapi/linux/tls.h
25+
*
26+
* However, for simplicity our ktls probe will also require AES-256 and TLS1.3.
27+
* If this prevents some customers from using ktls, we can split our single ktls
28+
* feature probe into more fine-grained feature probes.
2529
*/
30+
int versions[] = { TLS_1_2_VERSION, TLS_1_3_VERSION };
31+
int cipher_types[] = { TLS_CIPHER_AES_GCM_128, TLS_CIPHER_AES_GCM_256 };
32+
2633
struct tls12_crypto_info_aes_gcm_128 aes_crypto_info_128 = { 0 };
27-
int aes_gcm_128_cipher_type = TLS_CIPHER_AES_GCM_128;
2834
struct tls12_crypto_info_aes_gcm_256 aes_crypto_info_256 = { 0 };
29-
int aes_gcm_256_cipher_type = TLS_CIPHER_AES_GCM_256;
30-
struct tls_crypto_info crypto_info = { 0 };
31-
32-
int get_record_type = TLS_GET_RECORD_TYPE;
33-
int set_record_type = TLS_SET_RECORD_TYPE;
34-
35+
int operations[] = { TLS_GET_RECORD_TYPE, TLS_SET_RECORD_TYPE };
3536
return 0;
3637
}

tests/unit/s2n_ktls_test.c

+9-9
Original file line numberDiff line numberDiff line change
@@ -189,14 +189,14 @@ int main(int argc, char **argv)
189189
EXPECT_EQUAL(test_key.size, sizeof(value->key));
190190
EXPECT_BYTEARRAY_EQUAL(test_key.data, value->key, sizeof(value->key));
191191

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

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

198-
EXPECT_TRUE(test_seq.size >= sizeof(value->rec_seq));
199-
EXPECT_BYTEARRAY_EQUAL(test_seq.data, value->rec_seq, sizeof(value->rec_seq));
198+
EXPECT_TRUE(test_iv.size >= sizeof(value->iv));
199+
EXPECT_BYTEARRAY_EQUAL(test_seq.data, value->iv, sizeof(value->iv));
200200
};
201201

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

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

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

230-
EXPECT_TRUE(test_seq.size >= sizeof(value->rec_seq));
231-
EXPECT_BYTEARRAY_EQUAL(test_seq.data, value->rec_seq, sizeof(value->rec_seq));
230+
EXPECT_TRUE(test_iv.size >= sizeof(value->iv));
231+
EXPECT_BYTEARRAY_EQUAL(test_seq.data, value->iv, sizeof(value->iv));
232232
};
233233
};
234234

@@ -309,7 +309,7 @@ int main(int argc, char **argv)
309309
s2n_connection_ptr_free);
310310
EXPECT_OK(s2n_test_configure_connection_for_ktls(server_conn));
311311

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

315315
server_conn->actual_protocol_version = S2N_TLS11;

0 commit comments

Comments
 (0)