Skip to content

Commit 6eab3ad

Browse files
authored
ktls: handle TLS1.3 key limits (#4318)
1 parent 69daf63 commit 6eab3ad

14 files changed

+590
-18
lines changed

error/s2n_errno.c

+2
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,8 @@ static const char *no_such_error = "Internal s2n error";
302302
ERR_ENTRY(S2N_ERR_ATOMIC, "Atomic operations in this environment would require locking") \
303303
ERR_ENTRY(S2N_ERR_TEST_ASSERTION, "Test assertion failed") \
304304
ERR_ENTRY(S2N_ERR_KTLS_RENEG, "kTLS does not support secure renegotiation") \
305+
ERR_ENTRY(S2N_ERR_KTLS_KEYUPDATE, "Received KeyUpdate from peer, but kernel does not support updating tls keys") \
306+
ERR_ENTRY(S2N_ERR_KTLS_KEY_LIMIT, "Reached key encryption limit, but kernel does not support updating tls keys") \
305307
/* clang-format on */
306308

307309
#define ERR_STR_CASE(ERR, str) \

error/s2n_errno.h

+2
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ typedef enum {
142142
S2N_ERR_MAX_EARLY_DATA_SIZE,
143143
S2N_ERR_EARLY_DATA_TRIAL_DECRYPT,
144144
S2N_ERR_NO_RENEGOTIATION,
145+
S2N_ERR_KTLS_KEYUPDATE,
145146
S2N_ERR_T_PROTO_END,
146147

147148
/* S2N_ERR_T_INTERNAL */
@@ -319,6 +320,7 @@ typedef enum {
319320
S2N_ERR_KTLS_BAD_CMSG,
320321
S2N_ERR_KTLS_RENEG,
321322
S2N_ERR_ATOMIC,
323+
S2N_ERR_KTLS_KEY_LIMIT,
322324
S2N_ERR_T_USAGE_END,
323325
} s2n_error;
324326

tests/unit/s2n_key_update_test.c

+64
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,46 @@ int main(int argc, char **argv)
148148
EXPECT_SUCCESS(s2n_connection_free(conn));
149149
};
150150

151+
/* Key update messages not allowed with ktls */
152+
{
153+
DEFER_CLEANUP(struct s2n_stuffer input, s2n_stuffer_free);
154+
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&input, 0));
155+
156+
DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER),
157+
s2n_connection_ptr_free);
158+
EXPECT_NOT_NULL(conn);
159+
conn->actual_protocol_version = S2N_TLS13;
160+
EXPECT_NOT_NULL(conn->secure);
161+
conn->secure->cipher_suite = &s2n_tls13_aes_256_gcm_sha384;
162+
163+
/* Fails if receiving with ktls:
164+
* Kernel key update would be required.
165+
*/
166+
conn->ktls_send_enabled = true;
167+
conn->ktls_recv_enabled = true;
168+
EXPECT_SUCCESS(s2n_stuffer_write_uint8(&input, S2N_KEY_UPDATE_NOT_REQUESTED));
169+
EXPECT_FAILURE_WITH_ERRNO(s2n_key_update_recv(conn, &input), S2N_ERR_KTLS_KEYUPDATE);
170+
EXPECT_SUCCESS(s2n_stuffer_wipe(&input));
171+
172+
/* Fails if only sending with ktls, but peer requested an update:
173+
* Kernel key update would be required.
174+
*/
175+
conn->ktls_send_enabled = true;
176+
conn->ktls_recv_enabled = false;
177+
EXPECT_SUCCESS(s2n_stuffer_write_uint8(&input, S2N_KEY_UPDATE_REQUESTED));
178+
EXPECT_FAILURE_WITH_ERRNO(s2n_key_update_recv(conn, &input), S2N_ERR_KTLS_KEYUPDATE);
179+
EXPECT_EQUAL(s2n_stuffer_data_available(&input), 0);
180+
181+
/* Succeeds if only sending with ktls and no update requested:
182+
* No kernel key update would be required.
183+
*/
184+
conn->ktls_send_enabled = true;
185+
conn->ktls_recv_enabled = false;
186+
EXPECT_SUCCESS(s2n_stuffer_write_uint8(&input, S2N_KEY_UPDATE_NOT_REQUESTED));
187+
EXPECT_SUCCESS(s2n_key_update_recv(conn, &input));
188+
EXPECT_EQUAL(s2n_stuffer_data_available(&input), 0);
189+
};
190+
151191
/* Key update message received contains invalid key update request */
152192
{
153193
DEFER_CLEANUP(struct s2n_stuffer input, s2n_stuffer_free);
@@ -442,6 +482,30 @@ int main(int argc, char **argv)
442482

443483
EXPECT_EQUAL(key_update_seq_num, expected);
444484
};
485+
486+
/* KeyUpdate fails if ktls */
487+
{
488+
DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT),
489+
s2n_connection_ptr_free);
490+
conn->actual_protocol_version = S2N_TLS13;
491+
conn->ktls_send_enabled = true;
492+
493+
/* Passes if no KeyUpdate required */
494+
s2n_blocked_status blocked = 0;
495+
EXPECT_SUCCESS(s2n_key_update_send(conn, &blocked));
496+
EXPECT_FALSE(s2n_atomic_flag_test(&conn->key_update_pending));
497+
498+
/* Set encryption limit */
499+
EXPECT_NOT_NULL(conn->secure);
500+
conn->secure->cipher_suite = cipher_suite_with_limit;
501+
EXPECT_OK(s2n_write_uint64(record_limit, conn->secure->client_sequence_number));
502+
503+
/* Fails if KeyUpdate required */
504+
EXPECT_FAILURE_WITH_ERRNO(
505+
s2n_key_update_send(conn, &blocked),
506+
S2N_ERR_KTLS_KEY_LIMIT);
507+
EXPECT_TRUE(s2n_atomic_flag_test(&conn->key_update_pending));
508+
};
445509
};
446510

447511
/* s2n_check_record_limit */

tests/unit/s2n_ktls_io_sendfile_test.c

+47
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,20 @@
1616
#include <fcntl.h>
1717
#include <sys/socket.h>
1818

19+
#include "crypto/s2n_sequence.h"
1920
#include "s2n_test.h"
2021
#include "testlib/s2n_testlib.h"
2122
#include "tls/s2n_ktls.h"
2223
#include "utils/s2n_random.h"
2324

25+
static S2N_RESULT s2n_test_get_seq_num(struct s2n_connection *conn, uint64_t *seq_num_out)
26+
{
27+
struct s2n_blob seq_num = { 0 };
28+
RESULT_GUARD(s2n_connection_get_sequence_number(conn, conn->mode, &seq_num));
29+
RESULT_GUARD_POSIX(s2n_sequence_number_to_uint64(&seq_num, seq_num_out));
30+
return S2N_RESULT_OK;
31+
}
32+
2433
int main(int argc, char **argv)
2534
{
2635
BEGIN_TEST();
@@ -213,6 +222,44 @@ int main(int argc, char **argv)
213222
EXPECT_EQUAL(blocked, S2N_NOT_BLOCKED);
214223
};
215224

225+
/* Test: key encryption limit tracked */
226+
{
227+
struct s2n_record_algorithm test_record_alg = *s2n_tls13_aes_128_gcm_sha256.record_alg;
228+
test_record_alg.encryption_limit = 0;
229+
struct s2n_cipher_suite test_cipher_suite = s2n_tls13_aes_128_gcm_sha256;
230+
test_cipher_suite.record_alg = &test_record_alg;
231+
232+
DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER),
233+
s2n_connection_ptr_free);
234+
EXPECT_NOT_NULL(conn);
235+
conn->ktls_send_enabled = true;
236+
conn->actual_protocol_version = S2N_TLS13;
237+
238+
DEFER_CLEANUP(struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close);
239+
EXPECT_SUCCESS(s2n_io_pair_init_non_blocking(&io_pair));
240+
EXPECT_SUCCESS(s2n_connection_set_write_fd(conn, io_pair.server));
241+
242+
/* Test: The sequence number starts at 0 */
243+
uint64_t seq_num = 1;
244+
EXPECT_OK(s2n_test_get_seq_num(conn, &seq_num));
245+
EXPECT_EQUAL(seq_num, 0);
246+
247+
/* Test: The sequence number tracks data sent */
248+
s2n_blocked_status blocked = S2N_NOT_BLOCKED;
249+
size_t bytes_written = 0;
250+
EXPECT_SUCCESS(s2n_sendfile(conn, ro_file, 0, sizeof(test_data),
251+
&bytes_written, &blocked));
252+
EXPECT_OK(s2n_test_get_seq_num(conn, &seq_num));
253+
EXPECT_TRUE(seq_num > 0);
254+
255+
/* Test: Enforce the encryption limit */
256+
EXPECT_NOT_NULL(conn->secure);
257+
conn->secure->cipher_suite = &test_cipher_suite;
258+
EXPECT_FAILURE_WITH_ERRNO(
259+
s2n_sendfile(conn, ro_file, 0, sizeof(test_data), &bytes_written, &blocked),
260+
S2N_ERR_KTLS_KEY_LIMIT);
261+
};
262+
216263
EXPECT_EQUAL(close(ro_file), 0);
217264
END_TEST();
218265
}

tests/unit/s2n_ktls_io_test.c

+133
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* permissions and limitations under the License.
1414
*/
1515

16+
#include "crypto/s2n_sequence.h"
1617
#include "s2n_test.h"
1718
#include "testlib/s2n_ktls_test_utils.h"
1819
#include "testlib/s2n_mem_testlib.h"
@@ -62,6 +63,15 @@ static ssize_t s2n_test_ktls_recvmsg_eof(void *io_context, struct msghdr *msg)
6263
return 0;
6364
}
6465

66+
static ssize_t s2n_test_ktls_sendmsg_mark_all_sent(void *io_context, const struct msghdr *msg)
67+
{
68+
size_t sent = 0;
69+
for (size_t i = 0; i < msg->msg_iovlen; i++) {
70+
sent += msg->msg_iov[i].iov_len;
71+
}
72+
return sent;
73+
}
74+
6575
ssize_t s2n_test_ktls_recvmsg_io_stuffer_and_ctrunc(void *io_context, struct msghdr *msg)
6676
{
6777
POSIX_ENSURE_REF(msg);
@@ -74,6 +84,14 @@ ssize_t s2n_test_ktls_recvmsg_io_stuffer_and_ctrunc(void *io_context, struct msg
7484
return ret;
7585
}
7686

87+
static S2N_RESULT s2n_assert_seq_num_equal(struct s2n_blob actual_blob, uint64_t expected)
88+
{
89+
uint64_t actual = 0;
90+
RESULT_GUARD_POSIX(s2n_sequence_number_to_uint64(&actual_blob, &actual));
91+
RESULT_ENSURE(actual == expected, S2N_ERR_TEST_ASSERTION);
92+
return S2N_RESULT_OK;
93+
}
94+
7795
int main(int argc, char **argv)
7896
{
7997
BEGIN_TEST();
@@ -1185,5 +1203,120 @@ int main(int argc, char **argv)
11851203
};
11861204
};
11871205

1206+
/* Test: key encryption limit tracked */
1207+
{
1208+
uint8_t large_test_data[S2N_TLS_MAXIMUM_FRAGMENT_LENGTH * 10] = { 0 };
1209+
const size_t large_test_data_records = sizeof(large_test_data) / S2N_TLS_MAXIMUM_FRAGMENT_LENGTH;
1210+
/* For simplicity, keep our test data a positive even multiple of the max frag size */
1211+
EXPECT_TRUE(sizeof(large_test_data) % S2N_TLS_MAXIMUM_FRAGMENT_LENGTH == 0);
1212+
EXPECT_TRUE(large_test_data_records > 0);
1213+
const size_t test_encryption_limit = large_test_data_records;
1214+
1215+
struct s2n_record_algorithm test_record_alg = *s2n_tls13_aes_128_gcm_sha256.record_alg;
1216+
test_record_alg.encryption_limit = test_encryption_limit;
1217+
struct s2n_cipher_suite test_cipher_suite = s2n_tls13_aes_128_gcm_sha256;
1218+
test_cipher_suite.record_alg = &test_record_alg;
1219+
1220+
for (s2n_mode mode = 0; mode <= 1; mode++) {
1221+
DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(mode),
1222+
s2n_connection_ptr_free);
1223+
EXPECT_NOT_NULL(conn);
1224+
EXPECT_OK(s2n_ktls_set_sendmsg_cb(conn, s2n_test_ktls_sendmsg_mark_all_sent, conn));
1225+
conn->ktls_send_enabled = true;
1226+
EXPECT_NOT_NULL(conn->secure);
1227+
conn->secure->cipher_suite = &test_cipher_suite;
1228+
conn->actual_protocol_version = S2N_TLS13;
1229+
1230+
s2n_blocked_status blocked = S2N_NOT_BLOCKED;
1231+
1232+
/* Test: Sequence number tracked correctly */
1233+
{
1234+
DEFER_CLEANUP(struct s2n_blob seq_num = { 0 }, s2n_blob_zero);
1235+
EXPECT_OK(s2n_connection_get_sequence_number(conn, conn->mode, &seq_num));
1236+
1237+
/* Test: All connections start with zero records sent */
1238+
uint64_t expected_seq_num = 0;
1239+
EXPECT_OK(s2n_assert_seq_num_equal(seq_num, expected_seq_num));
1240+
1241+
/* Test: Send no data */
1242+
EXPECT_EQUAL(s2n_send(conn, large_test_data, 0, &blocked), 0);
1243+
EXPECT_OK(s2n_assert_seq_num_equal(seq_num, expected_seq_num));
1244+
1245+
/* Test: Send one minimum sized record */
1246+
expected_seq_num++;
1247+
EXPECT_EQUAL(s2n_send(conn, large_test_data, 1, &blocked), 1);
1248+
EXPECT_OK(s2n_assert_seq_num_equal(seq_num, expected_seq_num));
1249+
1250+
/* Test: Send one maximum sized record */
1251+
expected_seq_num++;
1252+
EXPECT_EQUAL(
1253+
s2n_send(conn, large_test_data, S2N_TLS_MAXIMUM_FRAGMENT_LENGTH, &blocked),
1254+
S2N_TLS_MAXIMUM_FRAGMENT_LENGTH);
1255+
EXPECT_OK(s2n_assert_seq_num_equal(seq_num, expected_seq_num));
1256+
1257+
/* Test: Send multiple records */
1258+
expected_seq_num += 2;
1259+
EXPECT_EQUAL(
1260+
s2n_send(conn, large_test_data, S2N_TLS_MAXIMUM_FRAGMENT_LENGTH + 1, &blocked),
1261+
S2N_TLS_MAXIMUM_FRAGMENT_LENGTH + 1);
1262+
EXPECT_OK(s2n_assert_seq_num_equal(seq_num, expected_seq_num));
1263+
1264+
/* Test: Send enough data to hit the encryption limit */
1265+
EXPECT_FAILURE_WITH_ERRNO(
1266+
s2n_send(conn, large_test_data, sizeof(large_test_data), &blocked),
1267+
S2N_ERR_KTLS_KEY_LIMIT);
1268+
EXPECT_OK(s2n_assert_seq_num_equal(seq_num, expected_seq_num));
1269+
};
1270+
1271+
/* Test: Exact encryption limit boundary */
1272+
{
1273+
DEFER_CLEANUP(struct s2n_blob seq_num = { 0 }, s2n_blob_zero);
1274+
EXPECT_OK(s2n_connection_get_sequence_number(conn, conn->mode, &seq_num));
1275+
1276+
/* Send enough records to hit but not exceed the encryption limit */
1277+
for (size_t i = 0; i < test_encryption_limit; i++) {
1278+
EXPECT_EQUAL(s2n_send(conn, large_test_data, 1, &blocked), 1);
1279+
}
1280+
EXPECT_OK(s2n_assert_seq_num_equal(seq_num, test_encryption_limit));
1281+
1282+
/* One more record should exceed the encryption limit */
1283+
EXPECT_FAILURE_WITH_ERRNO(
1284+
s2n_send(conn, large_test_data, 1, &blocked),
1285+
S2N_ERR_KTLS_KEY_LIMIT);
1286+
EXPECT_OK(s2n_assert_seq_num_equal(seq_num, test_encryption_limit));
1287+
};
1288+
1289+
/* Test: Limit not tracked with TLS1.2 */
1290+
{
1291+
DEFER_CLEANUP(struct s2n_blob seq_num = { 0 }, s2n_blob_zero);
1292+
EXPECT_OK(s2n_connection_get_sequence_number(conn, conn->mode, &seq_num));
1293+
1294+
/* Sequence number not incremented with TLS1.2 */
1295+
conn->actual_protocol_version = S2N_TLS12;
1296+
EXPECT_EQUAL(
1297+
s2n_send(conn, large_test_data, sizeof(large_test_data), &blocked),
1298+
sizeof(large_test_data));
1299+
EXPECT_OK(s2n_assert_seq_num_equal(seq_num, 0));
1300+
1301+
/* Sequence number incremented with TLS1.3 */
1302+
conn->actual_protocol_version = S2N_TLS13;
1303+
EXPECT_EQUAL(
1304+
s2n_send(conn, large_test_data, sizeof(large_test_data), &blocked),
1305+
sizeof(large_test_data));
1306+
EXPECT_OK(s2n_assert_seq_num_equal(seq_num, test_encryption_limit));
1307+
1308+
/* Passing the limit with TLS1.3 is an error */
1309+
conn->actual_protocol_version = S2N_TLS13;
1310+
EXPECT_FAILURE_WITH_ERRNO(
1311+
s2n_send(conn, large_test_data, 1, &blocked),
1312+
S2N_ERR_KTLS_KEY_LIMIT);
1313+
1314+
/* Passing the limit with TLS1.2 is NOT an error */
1315+
conn->actual_protocol_version = S2N_TLS12;
1316+
EXPECT_EQUAL(s2n_send(conn, large_test_data, 1, &blocked), 1);
1317+
};
1318+
}
1319+
};
1320+
11881321
END_TEST();
11891322
}

tests/unit/s2n_safety_test.c

+51
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,57 @@ int main(int argc, char **argv)
387387
CHECK_OVF(s2n_add_overflow, uint32_t, 100, ACTUAL_MAX - 99);
388388
CHECK_OVF(s2n_add_overflow, uint32_t, 100, ACTUAL_MAX - 1);
389389

390+
/* Test: S2N_ADD_IS_OVERFLOW_SAFE */
391+
{
392+
const size_t num = 100;
393+
394+
uint64_t success_test_values[][3] = {
395+
{ 0, 0, 0 },
396+
{ 1, 0, 1 },
397+
{ 0, 0, UINT8_MAX },
398+
{ 1, 1, UINT8_MAX },
399+
{ UINT8_MAX, 0, UINT8_MAX },
400+
{ UINT8_MAX - num, num, UINT8_MAX },
401+
{ UINT8_MAX / 2, UINT8_MAX / 2, UINT8_MAX },
402+
{ 1, 1, UINT64_MAX },
403+
{ UINT64_MAX, 0, UINT64_MAX },
404+
{ UINT64_MAX - num, num, UINT64_MAX },
405+
{ UINT64_MAX / 2, UINT64_MAX / 2, UINT64_MAX },
406+
};
407+
for (size_t i = 0; i < s2n_array_len(success_test_values); i++) {
408+
uint64_t v1 = success_test_values[i][0];
409+
uint64_t v2 = success_test_values[i][1];
410+
uint64_t max = success_test_values[i][2];
411+
EXPECT_TRUE(S2N_ADD_IS_OVERFLOW_SAFE(v1, v2, max));
412+
EXPECT_TRUE(S2N_ADD_IS_OVERFLOW_SAFE(v2, v1, max));
413+
}
414+
415+
uint64_t failure_test_values[][3] = {
416+
{ 1, 0, 0 },
417+
{ UINT8_MAX, 0, 0 },
418+
{ UINT64_MAX, 0, UINT8_MAX },
419+
{ UINT64_MAX, UINT64_MAX, UINT8_MAX },
420+
{ UINT8_MAX, 1, UINT8_MAX },
421+
{ UINT8_MAX - 1, UINT8_MAX - 1, UINT8_MAX },
422+
{ UINT16_MAX, 1, UINT16_MAX },
423+
{ UINT64_MAX, 1, UINT64_MAX },
424+
{ UINT8_MAX, num, UINT8_MAX },
425+
{ UINT16_MAX, num, UINT16_MAX },
426+
{ UINT64_MAX, num, UINT64_MAX },
427+
{ UINT8_MAX, UINT8_MAX, UINT8_MAX },
428+
{ UINT16_MAX, UINT16_MAX, UINT16_MAX },
429+
{ UINT64_MAX, UINT64_MAX, UINT64_MAX },
430+
{ UINT64_MAX - num, UINT64_MAX - num, UINT64_MAX },
431+
};
432+
for (size_t i = 0; i < s2n_array_len(failure_test_values); i++) {
433+
uint64_t v1 = failure_test_values[i][0];
434+
uint64_t v2 = failure_test_values[i][1];
435+
uint64_t max = failure_test_values[i][2];
436+
EXPECT_FALSE(S2N_ADD_IS_OVERFLOW_SAFE(v1, v2, max));
437+
EXPECT_FALSE(S2N_ADD_IS_OVERFLOW_SAFE(v2, v1, max));
438+
}
439+
}
440+
390441
END_TEST();
391442
return 0;
392443
}

0 commit comments

Comments
 (0)