KTLS additional ciphersuites

Key update supported for patched kernels [1]

Configuration option `ktls = false` [2]

following ciphersuites are now supported: [3]
* TLS_AES_128_CCM_SHA256
* TLS_CHACHA20_POLY1305_SHA256

Ivalidate session on KTLS error as there is no way to recover and new
sockets as well as session have to be created. [4]

[1] https://gitlab.com/gnutls/gnutls/-/merge_requests/1625
[2] https://gitlab.com/gnutls/gnutls/-/merge_requests/1673/diffs?commit_id=aefd7319c0b7b2410d06238246b7755b289e4837
[3] https://gitlab.com/gnutls/gnutls/-/merge_requests/1676
[4] https://gitlab.com/gnutls/gnutls/-/merge_requests/1664

Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
This commit is contained in:
Frantisek Krenzelok 2022-12-08 16:57:23 +01:00
parent d401f95817
commit c1f8e66db2
No known key found for this signature in database
GPG Key ID: EBB409071C118684
5 changed files with 1453 additions and 1 deletions

View File

@ -0,0 +1,273 @@
From 4380f347b2fff4af10537930400b68df61bee442 Mon Sep 17 00:00:00 2001
From: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
Date: Thu, 1 Dec 2022 15:37:33 +0100
Subject: [PATCH 1/2] KTLS: add ciphersuites
* TLS_AES_128_CCM_SHA256
* TLS_CHACHA20_POLY1305_SHA256
Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
---
lib/system/ktls.c | 159 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 153 insertions(+), 6 deletions(-)
diff --git a/lib/system/ktls.c b/lib/system/ktls.c
index 703775960..792d09ccf 100644
--- a/lib/system/ktls.c
+++ b/lib/system/ktls.c
@@ -86,7 +86,7 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
gnutls_datum_t mac_key;
gnutls_datum_t iv;
gnutls_datum_t cipher_key;
- unsigned char seq_number[8];
+ unsigned char seq_number[12];
int sockin, sockout;
int ret;
@@ -97,7 +97,9 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
int version = gnutls_protocol_get_version(session);
if ((version != GNUTLS_TLS1_3 && version != GNUTLS_TLS1_2) ||
(gnutls_cipher_get(session) != GNUTLS_CIPHER_AES_128_GCM &&
- gnutls_cipher_get(session) != GNUTLS_CIPHER_AES_256_GCM)) {
+ gnutls_cipher_get(session) != GNUTLS_CIPHER_AES_256_GCM &&
+ gnutls_cipher_get(session) != GNUTLS_CIPHER_AES_128_CCM &&
+ gnutls_cipher_get(session) != GNUTLS_CIPHER_CHACHA20_POLY1305)) {
return GNUTLS_E_UNIMPLEMENTED_FEATURE;
}
@@ -114,7 +116,7 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
case GNUTLS_CIPHER_AES_128_GCM:
{
struct tls12_crypto_info_aes_gcm_128 crypto_info;
- memset(&crypto_info, 0, sizeof(crypto_info));
+ memset(&crypto_info, 0, sizeof (crypto_info));
crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
assert(cipher_key.size == TLS_CIPHER_AES_GCM_128_KEY_SIZE);
@@ -150,7 +152,7 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
case GNUTLS_CIPHER_AES_256_GCM:
{
struct tls12_crypto_info_aes_gcm_256 crypto_info;
- memset(&crypto_info, 0, sizeof(crypto_info));
+ memset(&crypto_info, 0, sizeof (crypto_info));
crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_256;
assert (cipher_key.size == TLS_CIPHER_AES_GCM_256_KEY_SIZE);
@@ -182,9 +184,83 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
}
}
break;
+ case GNUTLS_CIPHER_AES_128_CCM:
+ {
+ struct tls12_crypto_info_aes_ccm_128 crypto_info;
+ memset(&crypto_info, 0, sizeof (crypto_info));
+
+ crypto_info.info.cipher_type = TLS_CIPHER_AES_CCM_128;
+ assert(cipher_key.size == TLS_CIPHER_AES_CCM_128_KEY_SIZE);
+
+ /* for TLS 1.2 IV is generated in kernel */
+ if (version == GNUTLS_TLS1_2) {
+ crypto_info.info.version = TLS_1_2_VERSION;
+ memcpy(crypto_info.iv, seq_number, TLS_CIPHER_AES_CCM_128_IV_SIZE);
+ } else {
+ crypto_info.info.version = TLS_1_3_VERSION;
+ assert(iv.size == TLS_CIPHER_AES_CCM_128_SALT_SIZE
+ + TLS_CIPHER_AES_CCM_128_IV_SIZE);
+
+ memcpy(crypto_info.iv, iv.data +
+ TLS_CIPHER_AES_CCM_128_SALT_SIZE,
+ TLS_CIPHER_AES_CCM_128_IV_SIZE);
+ }
+
+ memcpy(crypto_info.salt, iv.data,
+ TLS_CIPHER_AES_CCM_128_SALT_SIZE);
+ memcpy(crypto_info.rec_seq, seq_number,
+ TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE);
+ memcpy(crypto_info.key, cipher_key.data,
+ TLS_CIPHER_AES_CCM_128_KEY_SIZE);
+
+ if (setsockopt (sockin, SOL_TLS, TLS_RX,
+ &crypto_info, sizeof (crypto_info))) {
+ session->internals.ktls_enabled &= ~GNUTLS_KTLS_RECV;
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ }
+ }
+ break;
+ case GNUTLS_CIPHER_CHACHA20_POLY1305:
+ {
+ struct tls12_crypto_info_chacha20_poly1305 crypto_info;
+ memset(&crypto_info, 0, sizeof (crypto_info));
+
+ crypto_info.info.cipher_type = TLS_CIPHER_CHACHA20_POLY1305;
+ assert(cipher_key.size == TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
+
+ /* for TLS 1.2 IV is generated in kernel */
+ if (version == GNUTLS_TLS1_2) {
+ crypto_info.info.version = TLS_1_2_VERSION;
+ memcpy(crypto_info.iv, seq_number, TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
+ } else {
+ crypto_info.info.version = TLS_1_3_VERSION;
+ assert(iv.size == TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE
+ + TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
+
+ memcpy(crypto_info.iv, iv.data +
+ TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE,
+ TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
+ }
+
+ memcpy(crypto_info.salt, iv.data,
+ TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE);
+ memcpy(crypto_info.rec_seq, seq_number,
+ TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE);
+ memcpy(crypto_info.key, cipher_key.data,
+ TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
+
+ if (setsockopt (sockin, SOL_TLS, TLS_RX,
+ &crypto_info, sizeof (crypto_info))) {
+ session->internals.ktls_enabled &= ~GNUTLS_KTLS_RECV;
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ }
+ }
+ break;
default:
assert(0);
}
+
+
}
ret = gnutls_record_get_state (session, 0, &mac_key, &iv, &cipher_key,
@@ -198,7 +274,7 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
case GNUTLS_CIPHER_AES_128_GCM:
{
struct tls12_crypto_info_aes_gcm_128 crypto_info;
- memset(&crypto_info, 0, sizeof(crypto_info));
+ memset(&crypto_info, 0, sizeof (crypto_info));
crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
@@ -234,7 +310,7 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
case GNUTLS_CIPHER_AES_256_GCM:
{
struct tls12_crypto_info_aes_gcm_256 crypto_info;
- memset(&crypto_info, 0, sizeof(crypto_info));
+ memset(&crypto_info, 0, sizeof (crypto_info));
crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_256;
assert (cipher_key.size == TLS_CIPHER_AES_GCM_256_KEY_SIZE);
@@ -266,10 +342,81 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
}
}
break;
+ case GNUTLS_CIPHER_AES_128_CCM:
+ {
+ struct tls12_crypto_info_aes_ccm_128 crypto_info;
+ memset(&crypto_info, 0, sizeof (crypto_info));
+
+ crypto_info.info.cipher_type = TLS_CIPHER_AES_CCM_128;
+ assert (cipher_key.size == TLS_CIPHER_AES_CCM_128_KEY_SIZE);
+
+ /* for TLS 1.2 IV is generated in kernel */
+ if (version == GNUTLS_TLS1_2) {
+ crypto_info.info.version = TLS_1_2_VERSION;
+ memcpy(crypto_info.iv, seq_number, TLS_CIPHER_AES_CCM_128_IV_SIZE);
+ } else {
+ crypto_info.info.version = TLS_1_3_VERSION;
+ assert (iv.size == TLS_CIPHER_AES_CCM_128_SALT_SIZE +
+ TLS_CIPHER_AES_CCM_128_IV_SIZE);
+
+ memcpy (crypto_info.iv, iv.data + TLS_CIPHER_AES_CCM_128_SALT_SIZE,
+ TLS_CIPHER_AES_CCM_128_IV_SIZE);
+ }
+
+ memcpy (crypto_info.salt, iv.data,
+ TLS_CIPHER_AES_CCM_128_SALT_SIZE);
+ memcpy (crypto_info.rec_seq, seq_number,
+ TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE);
+ memcpy (crypto_info.key, cipher_key.data,
+ TLS_CIPHER_AES_CCM_128_KEY_SIZE);
+
+ if (setsockopt (sockout, SOL_TLS, TLS_TX,
+ &crypto_info, sizeof (crypto_info))) {
+ session->internals.ktls_enabled &= ~GNUTLS_KTLS_SEND;
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ }
+ }
+ break;
+ case GNUTLS_CIPHER_CHACHA20_POLY1305:
+ {
+ struct tls12_crypto_info_chacha20_poly1305 crypto_info;
+ memset(&crypto_info, 0, sizeof (crypto_info));
+
+ crypto_info.info.cipher_type = TLS_CIPHER_CHACHA20_POLY1305;
+ assert (cipher_key.size == TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
+
+ /* for TLS 1.2 IV is generated in kernel */
+ if (version == GNUTLS_TLS1_2) {
+ crypto_info.info.version = TLS_1_2_VERSION;
+ memcpy(crypto_info.iv, seq_number, TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
+ } else {
+ crypto_info.info.version = TLS_1_3_VERSION;
+ assert (iv.size == TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE +
+ TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
+
+ memcpy (crypto_info.iv, iv.data + TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE,
+ TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
+ }
+
+ memcpy (crypto_info.salt, iv.data,
+ TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE);
+ memcpy (crypto_info.rec_seq, seq_number,
+ TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE);
+ memcpy (crypto_info.key, cipher_key.data,
+ TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE);
+
+ if (setsockopt (sockout, SOL_TLS, TLS_TX,
+ &crypto_info, sizeof (crypto_info))) {
+ session->internals.ktls_enabled &= ~GNUTLS_KTLS_SEND;
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ }
+ }
+ break;
default:
assert(0);
}
+
// set callback for sending handshake messages
gnutls_handshake_set_read_function(session,
_gnutls_ktls_send_handshake_msg);
--
2.38.1
From 24bd0559302f8a7adf9f072f61f2aa03efa664f6 Mon Sep 17 00:00:00 2001
From: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
Date: Fri, 2 Dec 2022 11:07:48 +0100
Subject: [PATCH 2/2] KTLS: add ciphersuites (tests)
Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
---
tests/gnutls_ktls.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tests/gnutls_ktls.c b/tests/gnutls_ktls.c
index 8f9c5fa36..919270778 100644
--- a/tests/gnutls_ktls.c
+++ b/tests/gnutls_ktls.c
@@ -350,8 +350,12 @@ void doit(void)
{
run("NORMAL:-VERS-ALL:+VERS-TLS1.2:-CIPHER-ALL:+AES-128-GCM");
run("NORMAL:-VERS-ALL:+VERS-TLS1.2:-CIPHER-ALL:+AES-256-GCM");
+ run("NORMAL:-VERS-ALL:+VERS-TLS1.2:-CIPHER-ALL:+AES-128-CCM");
+ run("NORMAL:-VERS-ALL:+VERS-TLS1.2:-CIPHER-ALL:+CHACHA20-POLY1305");
run("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM");
run("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM");
+ run("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-CCM");
+ run("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+CHACHA20-POLY1305");
}
#endif /* _WIN32 */
--
2.38.1

View File

@ -0,0 +1,62 @@
From 9533fcbacdb5532425568e3874cfea9f0a9b55d5 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Mon, 28 Nov 2022 11:10:58 +0900
Subject: [PATCH 1/2] src: fix memory leak in print_rawpk_info
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
src/common.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/common.c b/src/common.c
index 6d2056f95..20327b41c 100644
--- a/src/common.c
+++ b/src/common.c
@@ -222,7 +222,7 @@ print_rawpk_info(gnutls_session_t session, FILE *out, int flag, int print_cert,
if (ret < 0) {
fprintf(stderr, "Encoding error: %s\n",
gnutls_strerror(ret));
- return;
+ goto cleanup;
}
log_msg(out, "\n%s\n", (char*)pem.data);
@@ -230,6 +230,8 @@ print_rawpk_info(gnutls_session_t session, FILE *out, int flag, int print_cert,
gnutls_free(pem.data);
}
+ cleanup:
+ gnutls_pcert_deinit(&pk_cert);
}
/* returns false (0) if not verified, or true (1) otherwise
--
2.38.1
From ceac5211c073ba8dc86fe7cfb25504db33729fa9 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Mon, 28 Nov 2022 11:14:53 +0900
Subject: [PATCH 2/2] tests: fix memory leak in resume-with-previous-stek
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
tests/resume-with-previous-stek.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/resume-with-previous-stek.c b/tests/resume-with-previous-stek.c
index 94f165627..98aba8d84 100644
--- a/tests/resume-with-previous-stek.c
+++ b/tests/resume-with-previous-stek.c
@@ -127,6 +127,8 @@ static void client(int fd, int *resume, unsigned rounds, const char *prio)
gnutls_deinit(session);
}
+
+ gnutls_free(session_data.data);
}
typedef void (* gnutls_stek_rotation_callback_t) (const gnutls_datum_t *prev_key,
--
2.38.1

View File

@ -0,0 +1,957 @@
From c83b9ecbe8e7e5442867281236d8c9e1bd227204 Mon Sep 17 00:00:00 2001
From: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
Date: Tue, 2 Aug 2022 15:00:50 +0200
Subject: [PATCH 1/7] KTLS: set key on specific interfaces
It is now possible to set key on specific interface.
If interface given is not ktls enabled then it will be ignored.
Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
---
lib/handshake.c | 2 +-
lib/system/ktls.c | 12 +++++++-----
lib/system/ktls.h | 7 ++++++-
3 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/lib/handshake.c b/lib/handshake.c
index 21edc5ece..cb2bc3ae9 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -2924,7 +2924,7 @@ int gnutls_handshake(gnutls_session_t session)
#ifdef ENABLE_KTLS
if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_DUPLEX)) {
- _gnutls_ktls_set_keys(session);
+ _gnutls_ktls_set_keys(session, GNUTLS_KTLS_DUPLEX);
}
#endif
diff --git a/lib/system/ktls.c b/lib/system/ktls.c
index ddf27fac7..70b9b9b3a 100644
--- a/lib/system/ktls.c
+++ b/lib/system/ktls.c
@@ -80,7 +80,7 @@ void _gnutls_ktls_enable(gnutls_session_t session)
}
}
-int _gnutls_ktls_set_keys(gnutls_session_t session)
+int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable_flags_t in)
{
gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(session);
gnutls_datum_t mac_key;
@@ -107,7 +107,9 @@ int _gnutls_ktls_set_keys(gnutls_session_t session)
return ret;
}
- if(session->internals.ktls_enabled & GNUTLS_KTLS_RECV){
+ in &= session->internals.ktls_enabled;
+
+ if(in & GNUTLS_KTLS_RECV){
switch (cipher) {
case GNUTLS_CIPHER_AES_128_GCM:
{
@@ -191,7 +193,7 @@ int _gnutls_ktls_set_keys(gnutls_session_t session)
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
}
- if(session->internals.ktls_enabled & GNUTLS_KTLS_SEND){
+ if(in & GNUTLS_KTLS_SEND){
switch (cipher) {
case GNUTLS_CIPHER_AES_128_GCM:
{
@@ -269,7 +271,7 @@ int _gnutls_ktls_set_keys(gnutls_session_t session)
}
}
- return 0;
+ return in;
}
ssize_t _gnutls_ktls_send_file(gnutls_session_t session, int fd,
@@ -465,7 +467,7 @@ gnutls_transport_is_ktls_enabled(gnutls_session_t session) {
void _gnutls_ktls_enable(gnutls_session_t session) {
}
-int _gnutls_ktls_set_keys(gnutls_session_t session) {
+int _gnutls_ktls_set_keys(gnutls_session_t sessioni, gnutls_transport_ktls_enable_flags_t in) {
return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
}
diff --git a/lib/system/ktls.h b/lib/system/ktls.h
index 8a98a8eb8..c8059092d 100644
--- a/lib/system/ktls.h
+++ b/lib/system/ktls.h
@@ -4,14 +4,19 @@
#include "gnutls_int.h"
void _gnutls_ktls_enable(gnutls_session_t session);
-int _gnutls_ktls_set_keys(gnutls_session_t session);
+
+int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable_flags_t in);
+
ssize_t _gnutls_ktls_send_file(gnutls_session_t session, int fd,
off_t *offset, size_t count);
+
int _gnutls_ktls_send_control_msg(gnutls_session_t session, unsigned char record_type,
const void *data, size_t data_size);
#define _gnutls_ktls_send(x, y, z) _gnutls_ktls_send_control_msg(x, GNUTLS_APPLICATION_DATA, y, z);
+
int _gnutls_ktls_recv_control_msg(gnutls_session_t session, unsigned char *record_type,
void *data, size_t data_size);
+
int _gnutls_ktls_recv_int(gnutls_session_t session, content_type_t type, void *data, size_t data_size);
#define _gnutls_ktls_recv(x, y, z) _gnutls_ktls_recv_int(x, GNUTLS_APPLICATION_DATA, y, z)
--
2.39.0
From f8c71030151e3a0d397e9712541236f1a76434a3 Mon Sep 17 00:00:00 2001
From: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
Date: Tue, 2 Aug 2022 13:35:39 +0200
Subject: [PATCH 2/7] KTLS: set new keys for keyupdate
set new keys durring gnutls_session_key_update()
setting keys
Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
---
lib/tls13/key_update.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/lib/tls13/key_update.c b/lib/tls13/key_update.c
index c6f6e0aa1..10c0a9110 100644
--- a/lib/tls13/key_update.c
+++ b/lib/tls13/key_update.c
@@ -27,6 +27,7 @@
#include "mem.h"
#include "mbuffers.h"
#include "secrets.h"
+#include "system/ktls.h"
#define KEY_UPDATES_WINDOW 1000
#define KEY_UPDATES_PER_WINDOW 8
@@ -49,8 +50,16 @@ static int update_keys(gnutls_session_t session, hs_stage_t stage)
* write keys */
if (session->internals.recv_state == RECV_STATE_EARLY_START) {
ret = _tls13_write_connection_state_init(session, stage);
+ if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND))
+ ret = _gnutls_ktls_set_keys(session, GNUTLS_KTLS_SEND);
} else {
ret = _tls13_connection_state_init(session, stage);
+
+ if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND) && stage == STAGE_UPD_OURS)
+ ret = _gnutls_ktls_set_keys(session, GNUTLS_KTLS_SEND);
+ else if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_RECV) && stage == STAGE_UPD_PEERS)
+ ret = _gnutls_ktls_set_keys(session, GNUTLS_KTLS_RECV);
+
}
if (ret < 0)
return gnutls_assert_val(ret);
--
2.39.0
From b93af37d972e02b095e14d4209bf5d5520a4893c Mon Sep 17 00:00:00 2001
From: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
Date: Wed, 3 Aug 2022 14:20:35 +0200
Subject: [PATCH 3/7] KTLS: send update key request
Set hanshake send function after interface initialization
TODO: handel setting function differently
Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
---
lib/record.c | 23 ++++++++++++++++-------
lib/system/ktls.c | 21 +++++++++++++++++++++
lib/system/ktls.h | 5 +++++
3 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/lib/record.c b/lib/record.c
index fd24acaf1..aad128e1f 100644
--- a/lib/record.c
+++ b/lib/record.c
@@ -2065,11 +2065,17 @@ gnutls_record_send2(gnutls_session_t session, const void *data,
session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_3;
FALLTHROUGH;
case RECORD_SEND_KEY_UPDATE_3:
- ret = _gnutls_send_int(session, GNUTLS_APPLICATION_DATA,
- -1, EPOCH_WRITE_CURRENT,
- session->internals.record_key_update_buffer.data,
- session->internals.record_key_update_buffer.length,
- MBUFFER_FLUSH);
+ if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND)) {
+ return _gnutls_ktls_send(session,
+ session->internals.record_key_update_buffer.data,
+ session->internals.record_key_update_buffer.length);
+ } else {
+ ret = _gnutls_send_int(session, GNUTLS_APPLICATION_DATA,
+ -1, EPOCH_WRITE_CURRENT,
+ session->internals.record_key_update_buffer.data,
+ session->internals.record_key_update_buffer.length,
+ MBUFFER_FLUSH);
+ }
_gnutls_buffer_clear(&session->internals.record_key_update_buffer);
session->internals.rsend_state = RECORD_SEND_NORMAL;
if (ret < 0)
@@ -2494,8 +2500,11 @@ gnutls_handshake_write(gnutls_session_t session,
return gnutls_assert_val(0);
/* When using this, the outgoing handshake messages should
- * also be handled manually */
- if (!session->internals.h_read_func)
+ * also be handled manually unless KTLS is enabled exclusively
+ * in GNUTLS_KTLS_RECV mode in which case the outgoing messages
+ * are handled by GnuTLS.
+ */
+ if (!session->internals.h_read_func && !IS_KTLS_ENABLED(session, GNUTLS_KTLS_RECV))
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
if (session->internals.initial_negotiation_completed) {
diff --git a/lib/system/ktls.c b/lib/system/ktls.c
index 70b9b9b3a..5da0a8069 100644
--- a/lib/system/ktls.c
+++ b/lib/system/ktls.c
@@ -269,6 +269,9 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
default:
assert(0);
}
+ // set callback for sending handshake messages
+ gnutls_handshake_set_read_function(session,
+ _gnutls_ktls_send_handshake_msg);
}
return in;
@@ -355,6 +358,15 @@ int _gnutls_ktls_send_control_msg(gnutls_session_t session,
return data_size;
}
+int _gnutls_ktls_send_handshake_msg(gnutls_session_t session,
+ gnutls_record_encryption_level_t level,
+ gnutls_handshake_description_t htype,
+ const void *data, size_t data_size)
+{
+ return _gnutls_ktls_send_control_msg(session, GNUTLS_HANDSHAKE,
+ data, data_size);
+}
+
int _gnutls_ktls_recv_control_msg(gnutls_session_t session,
unsigned char *record_type, void *data, size_t data_size)
{
@@ -481,6 +493,15 @@ int _gnutls_ktls_send_control_msg(gnutls_session_t session,
return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
}
+int _gnutls_ktls_send_handshake_msg(gnutls_session_t session,
+ gnutls_record_encryption_level_t level,
+ gnutls_handshake_description_t htype,
+ const void *data, size_t data_size)
+{
+ (void)level;
+ return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
+}
+
int _gnutls_ktls_recv_int(gnutls_session_t session, content_type_t type,
void *data, size_t data_size) {
return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
diff --git a/lib/system/ktls.h b/lib/system/ktls.h
index c8059092d..8d61a49df 100644
--- a/lib/system/ktls.h
+++ b/lib/system/ktls.h
@@ -10,6 +10,11 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
ssize_t _gnutls_ktls_send_file(gnutls_session_t session, int fd,
off_t *offset, size_t count);
+int _gnutls_ktls_send_handshake_msg(gnutls_session_t session,
+ gnutls_record_encryption_level_t level,
+ gnutls_handshake_description_t htype,
+ const void *data, size_t data_size);
+
int _gnutls_ktls_send_control_msg(gnutls_session_t session, unsigned char record_type,
const void *data, size_t data_size);
#define _gnutls_ktls_send(x, y, z) _gnutls_ktls_send_control_msg(x, GNUTLS_APPLICATION_DATA, y, z);
--
2.39.0
From 7128338208d092275ac72785f85019d16951fab9 Mon Sep 17 00:00:00 2001
From: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
Date: Mon, 22 Aug 2022 10:50:37 +0200
Subject: [PATCH 4/7] KTLS: receive key update
handle received GNUTLS_HANDSHAKE_KEY_UPDATE set keys accordingly
Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
---
lib/system/ktls.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/lib/system/ktls.c b/lib/system/ktls.c
index 5da0a8069..f3cb343ae 100644
--- a/lib/system/ktls.c
+++ b/lib/system/ktls.c
@@ -452,7 +452,13 @@ int _gnutls_ktls_recv_int(gnutls_session_t session, content_type_t type,
ret = 0;
break;
case GNUTLS_HANDSHAKE:
- // ignore post-handshake messages
+ ret = gnutls_handshake_write(session,
+ GNUTLS_ENCRYPTION_LEVEL_APPLICATION,
+ data, ret);
+
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
if (type != record_type)
return GNUTLS_E_AGAIN;
break;
--
2.39.0
From 14eadde1f2cdfaf858dc2029dac5503e48a49935 Mon Sep 17 00:00:00 2001
From: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
Date: Fri, 5 Aug 2022 16:38:02 +0200
Subject: [PATCH 5/7] KTLS: set write alert callback
Use callback for sending alerts.
Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
---
lib/alert.c | 13 ++++---------
lib/system/ktls.c | 15 +++++++++++++++
lib/system/ktls.h | 5 +++++
3 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/lib/alert.c b/lib/alert.c
index 50bd1d3de..fda8cd79f 100644
--- a/lib/alert.c
+++ b/lib/alert.c
@@ -182,15 +182,10 @@ gnutls_alert_send(gnutls_session_t session, gnutls_alert_level_t level,
return ret;
}
- if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND)) {
- ret =
- _gnutls_ktls_send_control_msg(session, GNUTLS_ALERT, data, 2);
- } else {
- ret =
- _gnutls_send_int(session, GNUTLS_ALERT, -1,
- EPOCH_WRITE_CURRENT, data, 2,
- MBUFFER_FLUSH);
- }
+ ret = _gnutls_send_int(session, GNUTLS_ALERT, -1,
+ EPOCH_WRITE_CURRENT, data, 2,
+ MBUFFER_FLUSH);
+
return (ret < 0) ? ret : 0;
}
diff --git a/lib/system/ktls.c b/lib/system/ktls.c
index f3cb343ae..703775960 100644
--- a/lib/system/ktls.c
+++ b/lib/system/ktls.c
@@ -269,9 +269,13 @@ int _gnutls_ktls_set_keys(gnutls_session_t session, gnutls_transport_ktls_enable
default:
assert(0);
}
+
// set callback for sending handshake messages
gnutls_handshake_set_read_function(session,
_gnutls_ktls_send_handshake_msg);
+
+ // set callback for sending alert messages
+ gnutls_alert_set_read_function(session, _gnutls_ktls_send_alert_msg);
}
return in;
@@ -367,6 +371,17 @@ int _gnutls_ktls_send_handshake_msg(gnutls_session_t session,
data, data_size);
}
+int _gnutls_ktls_send_alert_msg(gnutls_session_t session,
+ gnutls_record_encryption_level_t level,
+ gnutls_alert_level_t alert_level,
+ gnutls_alert_description_t alert_desc)
+{
+ uint8_t data[2];
+ data[0] = (uint8_t) alert_level;
+ data[1] = (uint8_t) alert_desc;
+ return _gnutls_ktls_send_control_msg(session, GNUTLS_ALERT, data, 2);
+}
+
int _gnutls_ktls_recv_control_msg(gnutls_session_t session,
unsigned char *record_type, void *data, size_t data_size)
{
diff --git a/lib/system/ktls.h b/lib/system/ktls.h
index 8d61a49df..64e1c9c1c 100644
--- a/lib/system/ktls.h
+++ b/lib/system/ktls.h
@@ -15,6 +15,11 @@ int _gnutls_ktls_send_handshake_msg(gnutls_session_t session,
gnutls_handshake_description_t htype,
const void *data, size_t data_size);
+int _gnutls_ktls_send_alert_msg(gnutls_session_t session,
+ gnutls_record_encryption_level_t level,
+ gnutls_alert_level_t alert_level,
+ gnutls_alert_description_t alert_desc);
+
int _gnutls_ktls_send_control_msg(gnutls_session_t session, unsigned char record_type,
const void *data, size_t data_size);
#define _gnutls_ktls_send(x, y, z) _gnutls_ktls_send_control_msg(x, GNUTLS_APPLICATION_DATA, y, z);
--
2.39.0
From 38b8708d66e592c09edf2745c921436f56607a96 Mon Sep 17 00:00:00 2001
From: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
Date: Tue, 9 Aug 2022 12:11:16 +0200
Subject: [PATCH 6/7] KTLS: rekey test
Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
---
tests/Makefile.am | 2 +
tests/ktls_keyupdate.c | 381 ++++++++++++++++++++++++++++++++++++++++
tests/ktls_keyupdate.sh | 46 +++++
3 files changed, 429 insertions(+)
create mode 100644 tests/ktls_keyupdate.c
create mode 100755 tests/ktls_keyupdate.sh
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1122886b3..2d345d478 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -500,6 +500,8 @@ endif
if ENABLE_KTLS
indirect_tests += gnutls_ktls
dist_check_SCRIPTS += ktls.sh
+indirect_tests += ktls_keyupdate
+dist_check_SCRIPTS += ktls_keyupdate.sh
endif
if !WINDOWS
diff --git a/tests/ktls_keyupdate.c b/tests/ktls_keyupdate.c
new file mode 100644
index 000000000..9fbff38ae
--- /dev/null
+++ b/tests/ktls_keyupdate.c
@@ -0,0 +1,381 @@
+// Copyright (C) 2022 Red Hat, Inc.
+//
+// Author: Frantisek Krenzelok
+//
+// This file is part of GnuTLS.
+//
+// GnuTLS is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3 of the License, or (at
+// your option) any later version.
+//
+// GnuTLS is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GnuTLS; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#include <gnutls/dtls.h>
+#include <gnutls/socket.h>
+#include <signal.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "cert-common.h"
+#include "utils.h"
+
+#if defined(_WIN32)
+
+int main(void)
+{
+ exit(77);
+}
+
+#else
+
+
+#define MAX_BUF 1024
+#define MSG "Hello world!"
+
+#define HANDSHAKE(session, name, ret)\
+{\
+ do {\
+ ret = gnutls_handshake(session);\
+ }\
+ while (ret < 0 && gnutls_error_is_fatal(ret) == 0);\
+ if (ret < 0) {\
+ fail("%s: Handshake failed\n", name);\
+ goto end;\
+ }\
+}
+
+#define SEND_MSG(session, name, ret)\
+{\
+ do {\
+ ret = gnutls_record_send(session, MSG, strlen(MSG)+1);\
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);\
+ if (ret < 0) {\
+ fail("%s: data sending has failed (%s)\n",name,\
+ gnutls_strerror(ret));\
+ goto end;\
+ }\
+}
+
+#define RECV_MSG(session, name, buffer, buffer_len, ret)\
+{\
+ memset(buffer, 0, sizeof(buffer));\
+ do{\
+ ret = gnutls_record_recv(session, buffer, sizeof(buffer));\
+ }\
+ while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);\
+ if (ret == 0) {\
+ success("%s: Peer has closed the TLS connection\n", name);\
+ goto end;\
+ } else if (ret < 0) {\
+ fail("%s: Error -> %s\n", name, gnutls_strerror(ret));\
+ goto end;\
+ }\
+ if(strncmp(buffer, MSG, ret)){\
+ fail("%s: Message doesn't match\n", name);\
+ goto end;\
+ }\
+}
+
+#define KEY_UPDATE(session, name, peer_req, ret)\
+{\
+ do {\
+ ret = gnutls_session_key_update(session, peer_req);\
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);\
+ if (ret < 0) {\
+ fail("%s: key update has failed (%s)\n", name, \
+ gnutls_strerror(ret));\
+ goto end;\
+ }\
+}
+
+#define CHECK_KTLS_ENABLED(session, ret)\
+{\
+ ret = gnutls_transport_is_ktls_enabled(session);\
+ if (!(ret & GNUTLS_KTLS_RECV)){\
+ fail("client: KTLS was not properly initialized\n");\
+ goto end;\
+ }\
+}
+
+static void server_log_func(int level, const char *str)
+{
+ fprintf(stderr, "server|<%d>| %s", level, str);
+}
+
+static void client_log_func(int level, const char *str)
+{
+ fprintf(stderr, "client|<%d>| %s", level, str);
+}
+
+
+static void client(int fd, const char *prio, int pipe)
+{
+ const char *name = "client";
+ int ret;
+ char foo;
+ char buffer[MAX_BUF + 1];
+ gnutls_certificate_credentials_t x509_cred;
+ gnutls_session_t session;
+
+ global_init();
+
+ if (debug) {
+ gnutls_global_set_log_function(client_log_func);
+ gnutls_global_set_log_level(7);
+ }
+
+ gnutls_certificate_allocate_credentials(&x509_cred);
+
+ gnutls_init(&session, GNUTLS_CLIENT);
+ gnutls_handshake_set_timeout(session, 0);
+
+ assert(gnutls_priority_set_direct(session, prio, NULL) >= 0);
+
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+
+ gnutls_transport_set_int(session, fd);
+
+ HANDSHAKE(session, name, ret);
+
+ CHECK_KTLS_ENABLED(session, ret)
+
+ // Test 0: Try sending/receiving data
+ RECV_MSG(session, name, buffer, MAX_BUF+1, ret)
+ SEND_MSG(session, name, ret)
+
+ CHECK_KTLS_ENABLED(session, ret)
+
+ // Test 1: Servers does key update
+ read(pipe, &foo, 1);
+ RECV_MSG(session, name, buffer, MAX_BUF+1, ret)
+ SEND_MSG(session, name, ret)
+
+ CHECK_KTLS_ENABLED(session, ret)
+
+ // Test 2: Does key update witch request
+ read(pipe, &foo, 1);
+ RECV_MSG(session, name, buffer, MAX_BUF+1, ret)
+ SEND_MSG(session, name, ret)
+
+ CHECK_KTLS_ENABLED(session, ret)
+
+ ret = gnutls_bye(session, GNUTLS_SHUT_RDWR);
+ if (ret < 0) {
+ fail("client: error in closing session: %s\n", gnutls_strerror(ret));
+ }
+
+ ret = 0;
+ end:
+
+ close(fd);
+
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(x509_cred);
+
+ gnutls_global_deinit();
+
+ if (ret != 0)
+ exit(1);
+}
+
+pid_t child;
+static void terminate(void)
+{
+ assert(child);
+ kill(child, SIGTERM);
+ exit(1);
+}
+
+static void server(int fd, const char *prio, int pipe)
+{
+ const char *name = "server";
+ int ret;
+ char bar = 0;
+ char buffer[MAX_BUF + 1];
+ gnutls_certificate_credentials_t x509_cred;
+ gnutls_session_t session;
+
+ global_init();
+
+ if (debug) {
+ gnutls_global_set_log_function(server_log_func);
+ gnutls_global_set_log_level(7);
+ }
+
+ gnutls_certificate_allocate_credentials(&x509_cred);
+ ret = gnutls_certificate_set_x509_key_mem(x509_cred, &server_cert,
+ &server_key,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ exit(1);
+
+ gnutls_init(&session, GNUTLS_SERVER);
+ gnutls_handshake_set_timeout(session, 0);
+
+ assert(gnutls_priority_set_direct(session, prio, NULL)>=0);
+
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+
+ gnutls_transport_set_int(session, fd);
+
+ HANDSHAKE(session, name, ret)
+
+ CHECK_KTLS_ENABLED(session, ret)
+
+ success("Test 0: sending/receiving data\n");
+ SEND_MSG(session, name, ret)
+ RECV_MSG(session, name, buffer, MAX_BUF+1, ret)
+
+ CHECK_KTLS_ENABLED(session, ret)
+
+ success("Test 1: server key update without request\n");
+ KEY_UPDATE(session, name, 0, ret)
+ write(pipe, &bar, 1);
+ SEND_MSG(session, name, ret)
+ RECV_MSG(session, name, buffer, MAX_BUF+1, ret)
+
+ CHECK_KTLS_ENABLED(session, ret)
+
+ success("Test 2: server key update with request\n");
+ KEY_UPDATE(session, name, GNUTLS_KU_PEER, ret)
+ write(pipe, &bar, 1);
+ SEND_MSG(session, name, ret)
+ RECV_MSG(session, name, buffer, MAX_BUF+1, ret)
+
+ CHECK_KTLS_ENABLED(session, ret)
+
+ ret = gnutls_bye(session, GNUTLS_SHUT_RDWR);
+ if (ret < 0) {
+ fail("server: error in closing session: %s\n", gnutls_strerror(ret));
+ }
+
+ ret = 0;
+end:
+ close(fd);
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(x509_cred);
+
+ gnutls_global_deinit();
+
+ if (ret){
+ terminate();
+ }
+
+ if (debug)
+ success("server: finished\n");
+}
+
+static void ch_handler(int sig)
+{
+ return;
+}
+
+static void run(const char *prio)
+{
+ int ret;
+ struct sockaddr_in saddr;
+ socklen_t addrlen;
+ int listener;
+ int fd;
+
+ int sync_pipe[2]; //used for synchronization
+ pipe(sync_pipe);
+
+ success("running ktls test with %s\n", prio);
+
+ signal(SIGCHLD, ch_handler);
+ signal(SIGPIPE, SIG_IGN);
+
+ listener = socket(AF_INET, SOCK_STREAM, 0);
+ if (listener == -1){
+ fail("error in listener(): %s\n", strerror(errno));
+ }
+
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ saddr.sin_port = 0;
+
+ ret = bind(listener, (struct sockaddr*)&saddr, sizeof(saddr));
+ if (ret == -1){
+ fail("error in bind(): %s\n", strerror(errno));
+ }
+
+ addrlen = sizeof(saddr);
+ ret = getsockname(listener, (struct sockaddr*)&saddr, &addrlen);
+ if (ret == -1){
+ fail("error in getsockname(): %s\n", strerror(errno));
+ }
+
+ child = fork();
+ if (child < 0) {
+ fail("error in fork(): %s\n", strerror(errno));
+ exit(1);
+ }
+
+ if (child) {
+ int status;
+ /* parent */
+ ret = listen(listener, 1);
+ if (ret == -1) {
+ fail("error in listen(): %s\n", strerror(errno));
+ }
+
+ fd = accept(listener, NULL, NULL);
+ if (fd == -1) {
+ fail("error in accept(): %s\n", strerror(errno));
+ }
+
+ close(sync_pipe[0]);
+ server(fd, prio, sync_pipe[1]);
+
+ wait(&status);
+ check_wait_status(status);
+ } else {
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (fd == -1){
+ fail("error in socket(): %s\n", strerror(errno));
+ exit(1);
+ }
+
+ usleep(1000000);
+ connect(fd, (struct sockaddr*)&saddr, addrlen);
+
+ close(sync_pipe[1]);
+ client(fd, prio, sync_pipe[0]);
+ exit(0);
+ }
+}
+
+void doit(void)
+{
+ run("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM");
+ run("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM");
+}
+
+#endif /* _WIN32 */
diff --git a/tests/ktls_keyupdate.sh b/tests/ktls_keyupdate.sh
new file mode 100755
index 000000000..d072acafc
--- /dev/null
+++ b/tests/ktls_keyupdate.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+# Copyright (C) 2022 Red Hat, Inc.
+#
+# Author: Daiki Ueno
+#
+# This file is part of GnuTLS.
+#
+# GnuTLS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3 of the License, or (at
+# your option) any later version.
+#
+# GnuTLS is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GnuTLS; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+: ${builddir=.}
+
+. "$srcdir/scripts/common.sh"
+
+if ! grep '^tls ' /proc/modules 2>&1 /dev/null; then
+ exit 77
+fi
+
+testdir=`create_testdir ktls_keyupdate`
+
+cfg="$testdir/config"
+
+cat <<EOF > "$cfg"
+[global]
+ktls = true
+EOF
+
+GNUTLS_SYSTEM_PRIORITY_FAIL_ON_INVALID=1 \
+GNUTLS_SYSTEM_PRIORITY_FILE="$cfg" \
+"$builddir/ktls_keyupdate" "$@"
+rc=$?
+
+rm -rf "$testdir"
+exit $rc
--
2.39.0
From 67843b3a8e28e4c74296caea2d1019065c87afb3 Mon Sep 17 00:00:00 2001
From: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
Date: Mon, 5 Sep 2022 13:05:17 +0200
Subject: [PATCH 7/7] KTLS: fallback to default
If an error occurs during setting of keys either initial or key update
then fallback to default mode of operation (disable ktls) and let the
user know
Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
---
lib/handshake.c | 7 ++++++-
lib/tls13/key_update.c | 23 +++++++++++++++++++----
2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/lib/handshake.c b/lib/handshake.c
index cb2bc3ae9..14bcdea56 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -2924,7 +2924,12 @@ int gnutls_handshake(gnutls_session_t session)
#ifdef ENABLE_KTLS
if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_DUPLEX)) {
- _gnutls_ktls_set_keys(session, GNUTLS_KTLS_DUPLEX);
+ ret = _gnutls_ktls_set_keys(session, GNUTLS_KTLS_DUPLEX);
+ if (ret < 0) {
+ session->internals.ktls_enabled = 0;
+ _gnutls_audit_log(session,
+ "disabling KTLS: failed to set keys\n");
+ }
}
#endif
diff --git a/lib/tls13/key_update.c b/lib/tls13/key_update.c
index 10c0a9110..acfda4129 100644
--- a/lib/tls13/key_update.c
+++ b/lib/tls13/key_update.c
@@ -32,6 +32,20 @@
#define KEY_UPDATES_WINDOW 1000
#define KEY_UPDATES_PER_WINDOW 8
+/*
+ * Sets kTLS keys if enabled.
+ * If this operation fails with GNUTLS_E_INTERNAL_ERROR, KTLS is disabled
+ * because KTLS most likely doesn't support key update.
+ */
+#define SET_KTLS_KEYS(session, interface)\
+{\
+ if(_gnutls_ktls_set_keys(session, interface) < 0) {\
+ session->internals.ktls_enabled = 0;\
+ _gnutls_audit_log(session, \
+ "disabling KTLS: couldn't update keys\n");\
+ }\
+}
+
static int update_keys(gnutls_session_t session, hs_stage_t stage)
{
int ret;
@@ -51,15 +65,16 @@ static int update_keys(gnutls_session_t session, hs_stage_t stage)
if (session->internals.recv_state == RECV_STATE_EARLY_START) {
ret = _tls13_write_connection_state_init(session, stage);
if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND))
- ret = _gnutls_ktls_set_keys(session, GNUTLS_KTLS_SEND);
+ SET_KTLS_KEYS(session, GNUTLS_KTLS_SEND)
} else {
ret = _tls13_connection_state_init(session, stage);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND) && stage == STAGE_UPD_OURS)
- ret = _gnutls_ktls_set_keys(session, GNUTLS_KTLS_SEND);
+ SET_KTLS_KEYS(session, GNUTLS_KTLS_SEND)
else if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_RECV) && stage == STAGE_UPD_PEERS)
- ret = _gnutls_ktls_set_keys(session, GNUTLS_KTLS_RECV);
-
+ SET_KTLS_KEYS(session, GNUTLS_KTLS_RECV)
}
if (ret < 0)
return gnutls_assert_val(ret);
--
2.39.0

View File

@ -0,0 +1,155 @@
From ccf4463f343a9394a22833ee1de7886e459d3c91 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Mon, 28 Nov 2022 12:17:12 +0900
Subject: [PATCH 1/3] includes: move KTLS function definition out of
<gnutls/socket.h>
<gnutls/socket.h> is meant for the functions that depend on
<sys/socket.h>, which is not available on Windows platforms.
As the KTLS API doesn't rely on <sys/socket.h>, move the function and
enum to <gnutls/gnutls.h>.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
lib/includes/gnutls/gnutls.h.in | 21 +++++++++++++++++++++
lib/includes/gnutls/socket.h | 21 ---------------------
2 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 394d465e3..830ce5f95 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -3421,6 +3421,27 @@ int gnutls_fips140_pop_context(void);
int gnutls_fips140_run_self_tests(void);
+/**
+ * gnutls_transport_ktls_enable_flags_t:
+ * @GNUTLS_KTLS_RECV: ktls enabled for recv function.
+ * @GNUTLS_KTLS_SEND: ktls enabled for send function.
+ * @GNUTLS_KTLS_DUPLEX: ktls enabled for both recv and send functions.
+ *
+ * Flag enumeration of ktls enable status for recv and send functions.
+ * This is used by gnutls_transport_is_ktls_enabled().
+ *
+ * Since: 3.7.3
+ */
+typedef enum {
+ GNUTLS_KTLS_RECV = 1 << 0,
+ GNUTLS_KTLS_SEND = 1 << 1,
+ GNUTLS_KTLS_DUPLEX = GNUTLS_KTLS_RECV | GNUTLS_KTLS_SEND,
+} gnutls_transport_ktls_enable_flags_t;
+
+
+gnutls_transport_ktls_enable_flags_t
+gnutls_transport_is_ktls_enabled(gnutls_session_t session);
+
/* Gnutls error codes. The mapping to a TLS alert is also shown in
* comments.
*/
diff --git a/lib/includes/gnutls/socket.h b/lib/includes/gnutls/socket.h
index 4df7bb2e0..64eb19f89 100644
--- a/lib/includes/gnutls/socket.h
+++ b/lib/includes/gnutls/socket.h
@@ -37,27 +37,6 @@ extern "C" {
#endif
/* *INDENT-ON* */
-/**
- * gnutls_transport_ktls_enable_flags_t:
- * @GNUTLS_KTLS_RECV: ktls enabled for recv function.
- * @GNUTLS_KTLS_SEND: ktls enabled for send function.
- * @GNUTLS_KTLS_DUPLEX: ktls enabled for both recv and send functions.
- *
- * Flag enumeration of ktls enable status for recv and send functions.
- * This is used by gnutls_transport_is_ktls_enabled().
- *
- * Since: 3.7.3
- */
-typedef enum {
- GNUTLS_KTLS_RECV = 1 << 0,
- GNUTLS_KTLS_SEND = 1 << 1,
- GNUTLS_KTLS_DUPLEX = GNUTLS_KTLS_RECV | GNUTLS_KTLS_SEND,
-} gnutls_transport_ktls_enable_flags_t;
-
-
-gnutls_transport_ktls_enable_flags_t
-gnutls_transport_is_ktls_enabled(gnutls_session_t session);
-
void gnutls_transport_set_fastopen(gnutls_session_t session,
int fd,
struct sockaddr *connect_addr,
--
2.38.1
From 90b036e82a95f9379d99d5cabd0e33905d1e3ddc Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Mon, 28 Nov 2022 12:13:31 +0900
Subject: [PATCH 2/3] src: print KTLS enablement status in
gnutls-serv/gnutls-cli
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
src/common.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/common.c b/src/common.c
index 6d2056f95..d357c7fb8 100644
--- a/src/common.c
+++ b/src/common.c
@@ -498,6 +498,7 @@ int print_info(gnutls_session_t session, int verbose, int flags)
gnutls_datum_t p;
char *desc;
gnutls_protocol_t version;
+ gnutls_transport_ktls_enable_flags_t ktls_flags;
int rc;
desc = gnutls_session_get_desc(session);
@@ -646,6 +647,15 @@ int print_info(gnutls_session_t session, int verbose, int flags)
print_channel_bindings(session, verbose);
+ ktls_flags = gnutls_transport_is_ktls_enabled(session);
+ if (ktls_flags != 0) {
+ log_msg(stdout, "- KTLS: %s\n",
+ (ktls_flags & GNUTLS_KTLS_DUPLEX) == GNUTLS_KTLS_DUPLEX ? "send, recv" :
+ (ktls_flags & GNUTLS_KTLS_SEND) == GNUTLS_KTLS_SEND ? "send" :
+ (ktls_flags & GNUTLS_KTLS_RECV) == GNUTLS_KTLS_RECV ? "recv" :
+ "unknown");
+ }
+
fflush(stdout);
return 0;
--
2.38.1
From aefd7319c0b7b2410d06238246b7755b289e4837 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Mon, 28 Nov 2022 12:15:26 +0900
Subject: [PATCH 3/3] priority: accept "ktls = false" in configuration file
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
lib/priority.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/priority.c b/lib/priority.c
index 97831e63b..6266bb571 100644
--- a/lib/priority.c
+++ b/lib/priority.c
@@ -1548,6 +1548,8 @@ static int global_ini_handler(void *ctx, const char *section, const char *name,
p = clear_spaces(value, str);
if (c_strcasecmp(p, "true") == 0) {
cfg->ktls_enabled = true;
+ } else if (c_strcasecmp(p, "false") == 0) {
+ cfg->ktls_enabled = false;
} else {
_gnutls_debug_log("cfg: unknown ktls mode %s\n",
p);
--
2.38.1

View File

@ -20,8 +20,13 @@ print(string.sub(hash, 0, 16))
Version: 3.7.8
Release: %{?autorelease}%{!?autorelease:1%{?dist}}
Patch: gnutls-3.7.8-gcc_analyzer-suppress_warnings.patch
Patch: gnutls-3.6.7-no-now-guile.patch
Patch: gnutls-3.2.7-rpath.patch
Patch: gnutls-3.6.7-no-now-guile.patch
Patch: gnutls-3.7.8-ktls_key_update.patch
Patch: gnutls-3.7.8-ktls_add_ciphersuites.patch
Patch: gnutls-3.7.8-ktls_minor_fixes.patch
Patch: gnutls-3.7.8-ktls_invalidate_session.patch
%bcond_without bootstrap
%bcond_without dane