From b8db73282a958fa6701b970e2904fff28898387c Mon Sep 17 00:00:00 2001 From: Frantisek Krenzelok Date: Fri, 15 Oct 2021 15:00:17 +0200 Subject: KTLS: API ktls is enabled by default, we can check if inicialization was succesfull with gnutls_transport_is_ktls_enabled Signed-off-by: Frantisek Krenzelok --- devel/libgnutls.abignore | 3 + devel/symbols.last | 1 + doc/Makefile.am | 2 + doc/manpages/Makefile.am | 1 + lib/alert.c | 2 +- lib/gnutls_int.h | 7 +- lib/handshake.c | 12 +- lib/includes/gnutls/socket.h | 2 + lib/libgnutls.map | 1 + lib/record.c | 8 +- lib/system/ktls.c | 339 +++++++++++++++++++++++-------------------- lib/system/ktls.h | 8 +- tests/gnutls_ktls.c | 97 ++++++++----- 13 files changed, 269 insertions(+), 214 deletions(-) diff --git a/devel/libgnutls.abignore b/devel/libgnutls.abignore index 8afa94148a..21d58a5299 100644 --- a/devel/libgnutls.abignore +++ b/devel/libgnutls.abignore @@ -71,3 +71,6 @@ name = gnutls_sign_set_secure [suppress_function] name = gnutls_sign_set_secure_for_certs + +[suppress_function] +name = gnutls_transport_is_ktls_enabled diff --git a/devel/symbols.last b/devel/symbols.last index 7bef666350..b17310dac3 100644 --- a/devel/symbols.last +++ b/devel/symbols.last @@ -881,6 +881,7 @@ gnutls_transport_get_int2@GNUTLS_3_4 gnutls_transport_get_int@GNUTLS_3_4 gnutls_transport_get_ptr2@GNUTLS_3_4 gnutls_transport_get_ptr@GNUTLS_3_4 +gnutls_transport_is_ktls_enabled@GNUTLS_3_7_2 gnutls_transport_set_errno@GNUTLS_3_4 gnutls_transport_set_errno_function@GNUTLS_3_4 gnutls_transport_set_fastopen@GNUTLS_3_4 diff --git a/doc/Makefile.am b/doc/Makefile.am index 4f25bf0d5e..03d73b81cc 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -2146,6 +2146,8 @@ FUNCS += functions/gnutls_transport_get_ptr FUNCS += functions/gnutls_transport_get_ptr.short FUNCS += functions/gnutls_transport_get_ptr2 FUNCS += functions/gnutls_transport_get_ptr2.short +FUNCS += functions/gnutls_transport_is_ktls_enabled +FUNCS += functions/gnutls_transport_is_ktls_enabled.short FUNCS += functions/gnutls_transport_set_errno FUNCS += functions/gnutls_transport_set_errno.short FUNCS += functions/gnutls_transport_set_errno_function diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am index 4f39adf0cc..b520bd1c68 100644 --- a/doc/manpages/Makefile.am +++ b/doc/manpages/Makefile.am @@ -875,6 +875,7 @@ APIMANS += gnutls_transport_get_int.3 APIMANS += gnutls_transport_get_int2.3 APIMANS += gnutls_transport_get_ptr.3 APIMANS += gnutls_transport_get_ptr2.3 +APIMANS += gnutls_transport_is_ktls_enabled.3 APIMANS += gnutls_transport_set_errno.3 APIMANS += gnutls_transport_set_errno_function.3 APIMANS += gnutls_transport_set_fastopen.3 diff --git a/lib/alert.c b/lib/alert.c index eda931a1c5..28ee91b13f 100644 --- a/lib/alert.c +++ b/lib/alert.c @@ -182,7 +182,7 @@ gnutls_alert_send(gnutls_session_t session, gnutls_alert_level_t level, return ret; } - if (IS_KTLS_ENABLED(session)) { + if (IS_KTLS_ENABLED(session, KTLS_SEND)) { ret = _gnutls_ktls_send_control_msg(session, GNUTLS_ALERT, data, 2); } else { diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 1dbe404857..a660828a57 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -176,7 +176,7 @@ typedef enum record_send_state_t { #define IS_DTLS(session) (session->internals.transport == GNUTLS_DGRAM) /* To check whether we have a KTLS enabled */ -#define IS_KTLS_ENABLED(session) (session->internals.ktls_enabled) +#define IS_KTLS_ENABLED(session, interface) (session->internals.ktls_enabled & interface) /* the maximum size of encrypted packets */ #define DEFAULT_MAX_RECORD_SIZE 16384 @@ -1495,10 +1495,7 @@ typedef struct { void *epoch_lock; /* indicates whether or not was KTLS initialized properly. */ - bool ktls_enabled; - int recv_fd; - int send_fd; - + int ktls_enabled; /* If you add anything here, check _gnutls_handshake_internal_state_clear(). */ } internals_st; diff --git a/lib/handshake.c b/lib/handshake.c index 9d36446e54..4ddfa66afe 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -2811,10 +2811,8 @@ int gnutls_handshake(gnutls_session_t session) int ret; #ifdef ENABLE_KTLS - int sockin, sockout; - gnutls_transport_get_int2(session, &sockin, &sockout); - _gnutls_ktls_enable(session, sockin, sockout); -#endif + _gnutls_ktls_enable(session); +#endif if (unlikely(session->internals.initial_negotiation_completed)) { if (vers->tls13_sem) { @@ -2912,10 +2910,8 @@ int gnutls_handshake(gnutls_session_t session) } #ifdef ENABLE_KTLS - if (IS_KTLS_ENABLED(session)) { - ret = _gnutls_ktls_set_keys(session); - if (ret < 0) - return ret; + if (IS_KTLS_ENABLED(session, KTLS_DUPLEX)) { + _gnutls_ktls_set_keys(session); } #endif diff --git a/lib/includes/gnutls/socket.h b/lib/includes/gnutls/socket.h index 64eb19f896..82f8d2f094 100644 --- a/lib/includes/gnutls/socket.h +++ b/lib/includes/gnutls/socket.h @@ -43,6 +43,8 @@ void gnutls_transport_set_fastopen(gnutls_session_t session, socklen_t connect_addrlen, unsigned int flags); +int gnutls_transport_is_ktls_enabled(gnutls_session_t session); + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/lib/libgnutls.map b/lib/libgnutls.map index dc50c6dba9..109837a5b5 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1363,6 +1363,7 @@ GNUTLS_3_7_3 gnutls_sign_set_secure_for_certs; gnutls_digest_set_secure; gnutls_protocol_set_enabled; + gnutls_transport_is_ktls_enabled; local: *; } GNUTLS_3_7_2; diff --git a/lib/record.c b/lib/record.c index ebc07d9e1c..d7f8724352 100644 --- a/lib/record.c +++ b/lib/record.c @@ -289,7 +289,7 @@ int gnutls_bye(gnutls_session_t session, gnutls_close_request_t how) switch (BYE_STATE) { case BYE_STATE0: - if (!IS_KTLS_ENABLED(session)) + if (!IS_KTLS_ENABLED(session, KTLS_SEND)) ret = _gnutls_io_write_flush(session); BYE_STATE = BYE_STATE0; if (ret < 0) { @@ -309,7 +309,7 @@ int gnutls_bye(gnutls_session_t session, gnutls_close_request_t how) case BYE_STATE2: BYE_STATE = BYE_STATE2; if (how == GNUTLS_SHUT_RDWR) { - if (IS_KTLS_ENABLED(session)){ + if (IS_KTLS_ENABLED(session, KTLS_SEND)){ do { ret = _gnutls_ktls_recv_int(session, GNUTLS_ALERT, NULL, 0); @@ -2035,7 +2035,7 @@ gnutls_record_send2(gnutls_session_t session, const void *data, switch(session->internals.rsend_state) { case RECORD_SEND_NORMAL: - if (IS_KTLS_ENABLED(session)) { + if (IS_KTLS_ENABLED(session, KTLS_SEND)) { return _gnutls_ktls_send(session, data, data_size); } else { return _gnutls_send_tlen_int(session, GNUTLS_APPLICATION_DATA, @@ -2306,7 +2306,7 @@ gnutls_record_recv(gnutls_session_t session, void *data, size_t data_size) return gnutls_assert_val(GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE); } - if (IS_KTLS_ENABLED(session)) { + if (IS_KTLS_ENABLED(session, KTLS_RECV)) { return _gnutls_ktls_recv(session, data, data_size); } else { return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA, diff --git a/lib/system/ktls.c b/lib/system/ktls.c index 7ab1d3215d..c54653b498 100644 --- a/lib/system/ktls.c +++ b/lib/system/ktls.c @@ -34,34 +34,37 @@ #include "ext/session_ticket.h" /** - * gnutls_transport_set_ktls: + * gnutls_transport_is_ktls_enabled: * @session: is a #gnutls_session_t type. - * @sockin: is a socket descriptor. - * @sockout: is a socket descriptor. * - * Enables Kernel TLS for the @session - * Requieres `tls` kernel module and - * gnutls configuration with `--enable-ktls` + * Checks if KTLS is now enabled and was properly inicialized. * - * Returns: 0 on success error otherwise + * Returns: 1 for enabled, 0 otherwise * * Since: 3.7.2 **/ -int _gnutls_ktls_enable(gnutls_session_t session, int sockin, int sockout) +int gnutls_transport_is_ktls_enabled(gnutls_session_t session){ + if (unlikely(!session->internals.initial_negotiation_completed)) + return gnutls_assert_val(GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE); + + return session->internals.ktls_enabled; +} + +int _gnutls_ktls_enable(gnutls_session_t session) { - if (setsockopt(sockin, SOL_TCP, TCP_ULP, "tls", sizeof ("tls")) < 0) - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + int sockin, sockout; + session->internals.ktls_enabled = 0; + gnutls_transport_get_int2(session, &sockin, &sockout); - session->internals.recv_fd = sockin; - session->internals.send_fd = sockin; + if (setsockopt(sockin, SOL_TCP, TCP_ULP, "tls", sizeof ("tls")) == 0) + session->internals.ktls_enabled |= KTLS_RECV; - if (sockin != sockout){ - if (setsockopt(sockout, SOL_TCP, TCP_ULP, "tls", sizeof ("tls")) < 0) - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); - session->internals.send_fd = sockout; - } + if (sockin != sockout) { + if (setsockopt(sockout, SOL_TCP, TCP_ULP, "tls", sizeof ("tls")) == 0) + session->internals.ktls_enabled |= KTLS_SEND; + } else + session->internals.ktls_enabled |= KTLS_SEND; - session->internals.ktls_enabled = 1; return 0; } @@ -72,9 +75,10 @@ int _gnutls_ktls_set_keys(gnutls_session_t session) gnutls_datum_t iv; gnutls_datum_t cipher_key; unsigned char seq_number[8]; + int sockin, sockout; int ret; - session->internals.ktls_enabled = 0; + gnutls_transport_get_int2(session, &sockin, &sockout); /* check whether or not cipher suite supports ktls */ @@ -85,164 +89,174 @@ int _gnutls_ktls_set_keys(gnutls_session_t session) return GNUTLS_E_UNIMPLEMENTED_FEATURE; } - version = (version == GNUTLS_TLS1_2) ? TLS_1_2_VERSION : TLS_1_3_VERSION; - ret = gnutls_record_get_state(session, 1, &mac_key, &iv, &cipher_key, seq_number); if (ret < 0) { return ret; } - switch (cipher) { - case GNUTLS_CIPHER_AES_128_GCM: - { - struct tls12_crypto_info_aes_gcm_128 crypto_info; - - crypto_info.info.version = version; - crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128; - - assert(cipher_key.size == TLS_CIPHER_AES_GCM_128_KEY_SIZE); - - /* for TLS 1.2 IV is generated in kernel */ - if (version == TLS_1_2_VERSION) { - assert(iv.size == TLS_CIPHER_AES_GCM_128_SALT_SIZE); - } else { - assert(iv.size == TLS_CIPHER_AES_GCM_128_SALT_SIZE - + TLS_CIPHER_AES_GCM_128_IV_SIZE); - - memcpy(crypto_info.iv, iv.data + - TLS_CIPHER_AES_GCM_128_SALT_SIZE, - TLS_CIPHER_AES_GCM_128_IV_SIZE); + if(session->internals.ktls_enabled & KTLS_RECV){ + switch (cipher) { + case GNUTLS_CIPHER_AES_128_GCM: + { + struct tls12_crypto_info_aes_gcm_128 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); + + /* 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_GCM_128_IV_SIZE); + } else { + crypto_info.info.version = TLS_1_3_VERSION; + assert(iv.size == TLS_CIPHER_AES_GCM_128_SALT_SIZE + + TLS_CIPHER_AES_GCM_128_IV_SIZE); + + memcpy(crypto_info.iv, iv.data + + TLS_CIPHER_AES_GCM_128_SALT_SIZE, + TLS_CIPHER_AES_GCM_128_IV_SIZE); + } + + memcpy(crypto_info.salt, iv.data, + TLS_CIPHER_AES_GCM_128_SALT_SIZE); + memcpy(crypto_info.rec_seq, seq_number, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + memcpy(crypto_info.key, cipher_key.data, + TLS_CIPHER_AES_GCM_128_KEY_SIZE); + + if (setsockopt (sockin, SOL_TLS, TLS_RX, + &crypto_info, sizeof (crypto_info))) { + session->internals.ktls_enabled ^= KTLS_RECV; + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } } - - memcpy(crypto_info.salt, iv.data, - TLS_CIPHER_AES_GCM_128_SALT_SIZE); - memcpy(crypto_info.rec_seq, seq_number, - TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); - memcpy(crypto_info.key, cipher_key.data, - TLS_CIPHER_AES_GCM_128_KEY_SIZE); - - if (setsockopt(session->internals.recv_fd, SOL_TLS, TLS_RX, - &crypto_info, sizeof (crypto_info))) { - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); - } - } - break; - case GNUTLS_CIPHER_AES_256_GCM: - { - struct tls12_crypto_info_aes_gcm_256 crypto_info; - - crypto_info.info.version = version; - crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_256; - - assert(cipher_key.size == TLS_CIPHER_AES_GCM_256_KEY_SIZE); - - /* for TLS 1.2 IV is generated in kernel */ - if (version == TLS_1_2_VERSION) { - assert(iv.size == TLS_CIPHER_AES_GCM_256_SALT_SIZE); - } else { - assert(iv.size == TLS_CIPHER_AES_GCM_256_SALT_SIZE - + TLS_CIPHER_AES_GCM_256_IV_SIZE); - - memcpy(crypto_info.iv, iv.data + TLS_CIPHER_AES_GCM_256_SALT_SIZE, - TLS_CIPHER_AES_GCM_256_IV_SIZE); - } - - memcpy(crypto_info.salt, iv.data, - TLS_CIPHER_AES_GCM_256_SALT_SIZE); - memcpy(crypto_info.rec_seq, seq_number, - TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE); - memcpy(crypto_info.key, cipher_key.data, - TLS_CIPHER_AES_GCM_256_KEY_SIZE); - - if (setsockopt(session->internals.recv_fd, SOL_TLS, TLS_RX, - &crypto_info, sizeof(crypto_info))) { - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + break; + case GNUTLS_CIPHER_AES_256_GCM: + { + struct tls12_crypto_info_aes_gcm_256 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); + + /* 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_GCM_256_IV_SIZE); + } else { + crypto_info.info.version = TLS_1_3_VERSION; + assert (iv.size == TLS_CIPHER_AES_GCM_256_SALT_SIZE + + TLS_CIPHER_AES_GCM_256_IV_SIZE); + + memcpy(crypto_info.iv, iv.data + TLS_CIPHER_AES_GCM_256_SALT_SIZE, + TLS_CIPHER_AES_GCM_256_IV_SIZE); + } + + memcpy (crypto_info.salt, iv.data, + TLS_CIPHER_AES_GCM_256_SALT_SIZE); + memcpy (crypto_info.rec_seq, seq_number, + TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE); + memcpy (crypto_info.key, cipher_key.data, + TLS_CIPHER_AES_GCM_256_KEY_SIZE); + + if (setsockopt (sockin, SOL_TLS, TLS_RX, + &crypto_info, sizeof (crypto_info))) { + session->internals.ktls_enabled ^= KTLS_RECV; + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } } + break; + default: + assert(0); } - break; - default: - assert(0); } - ret = gnutls_record_get_state(session, 0, &mac_key, &iv, &cipher_key, + ret = gnutls_record_get_state (session, 0, &mac_key, &iv, &cipher_key, seq_number); if (ret < 0) { return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); } - switch (cipher) { - case GNUTLS_CIPHER_AES_128_GCM: - { - struct tls12_crypto_info_aes_gcm_128 crypto_info; + if(session->internals.ktls_enabled & KTLS_SEND){ + switch (cipher) { + case GNUTLS_CIPHER_AES_128_GCM: + { + struct tls12_crypto_info_aes_gcm_128 crypto_info; + memset(&crypto_info, 0, sizeof(crypto_info)); - crypto_info.info.version = version; - crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128; + crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128; - assert(cipher_key.size == TLS_CIPHER_AES_GCM_128_KEY_SIZE); + assert (cipher_key.size == TLS_CIPHER_AES_GCM_128_KEY_SIZE); - /* for TLS 1.2 IV is generated in kernel */ - if (version == TLS_1_2_VERSION) { - assert(iv.size == TLS_CIPHER_AES_GCM_128_SALT_SIZE); - } else { - assert(iv.size == TLS_CIPHER_AES_GCM_128_SALT_SIZE - + TLS_CIPHER_AES_GCM_128_IV_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_GCM_128_IV_SIZE); + } else { + crypto_info.info.version = TLS_1_3_VERSION; + assert (iv.size == TLS_CIPHER_AES_GCM_128_SALT_SIZE + + TLS_CIPHER_AES_GCM_128_IV_SIZE); - memcpy(crypto_info.iv, iv.data + TLS_CIPHER_AES_GCM_128_SALT_SIZE, - TLS_CIPHER_AES_GCM_128_IV_SIZE); - } - - memcpy(crypto_info.salt, iv.data, - TLS_CIPHER_AES_GCM_128_SALT_SIZE); - memcpy(crypto_info.rec_seq, seq_number, - TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); - memcpy(crypto_info.key, cipher_key.data, - TLS_CIPHER_AES_GCM_128_KEY_SIZE); - - if (setsockopt(session->internals.send_fd, SOL_TLS, TLS_TX, - &crypto_info, sizeof(crypto_info))) { - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); - } - } - break; - case GNUTLS_CIPHER_AES_256_GCM: - { - struct tls12_crypto_info_aes_gcm_256 crypto_info; - - crypto_info.info.version = version; - crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_256; - assert(cipher_key.size == TLS_CIPHER_AES_GCM_256_KEY_SIZE); - - /* for TLS 1.2 IV is generated in kernel */ - if (version == TLS_1_2_VERSION) { - assert(iv.size == TLS_CIPHER_AES_GCM_256_SALT_SIZE); - } else { - assert(iv.size == TLS_CIPHER_AES_GCM_256_SALT_SIZE + - TLS_CIPHER_AES_GCM_256_IV_SIZE); - - memcpy(crypto_info.iv, iv.data + TLS_CIPHER_AES_GCM_256_SALT_SIZE, - TLS_CIPHER_AES_GCM_256_IV_SIZE); + memcpy (crypto_info.iv, iv.data + TLS_CIPHER_AES_GCM_128_SALT_SIZE, + TLS_CIPHER_AES_GCM_128_IV_SIZE); + } + + memcpy (crypto_info.salt, iv.data, + TLS_CIPHER_AES_GCM_128_SALT_SIZE); + memcpy (crypto_info.rec_seq, seq_number, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + memcpy (crypto_info.key, cipher_key.data, + TLS_CIPHER_AES_GCM_128_KEY_SIZE); + + if (setsockopt (sockout, SOL_TLS, TLS_TX, + &crypto_info, sizeof (crypto_info))) { + session->internals.ktls_enabled ^= KTLS_SEND; + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } } - - memcpy(crypto_info.salt, iv.data, - TLS_CIPHER_AES_GCM_256_SALT_SIZE); - memcpy(crypto_info.rec_seq, seq_number, - TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE); - memcpy(crypto_info.key, cipher_key.data, - TLS_CIPHER_AES_GCM_256_KEY_SIZE); - - if (setsockopt(session->internals.send_fd, SOL_TLS, TLS_TX, - &crypto_info, sizeof(crypto_info))) { - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + break; + case GNUTLS_CIPHER_AES_256_GCM: + { + struct tls12_crypto_info_aes_gcm_256 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); + + /* 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_GCM_256_IV_SIZE); + } else { + crypto_info.info.version = TLS_1_3_VERSION; + assert (iv.size == TLS_CIPHER_AES_GCM_256_SALT_SIZE + + TLS_CIPHER_AES_GCM_256_IV_SIZE); + + memcpy (crypto_info.iv, iv.data + TLS_CIPHER_AES_GCM_256_SALT_SIZE, + TLS_CIPHER_AES_GCM_256_IV_SIZE); + } + + memcpy (crypto_info.salt, iv.data, + TLS_CIPHER_AES_GCM_256_SALT_SIZE); + memcpy (crypto_info.rec_seq, seq_number, + TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE); + memcpy (crypto_info.key, cipher_key.data, + TLS_CIPHER_AES_GCM_256_KEY_SIZE); + + if (setsockopt (sockout, SOL_TLS, TLS_TX, + &crypto_info, sizeof (crypto_info))) { + session->internals.ktls_enabled ^= KTLS_SEND; + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } } + break; + default: + assert(0); } - break; - default: - assert(0); - } - session->internals.ktls_enabled = 1; return 0; } @@ -251,8 +265,11 @@ int _gnutls_ktls_send_control_msg(gnutls_session_t session, { const char *buf = data; ssize_t ret; + int sockin, sockout; - assert(session != NULL); + assert (session != NULL); + + gnutls_transport_get_int2(session, &sockin, &sockout); while (data_size > 0) { char cmsg[CMSG_SPACE(sizeof (unsigned char))]; @@ -278,7 +295,7 @@ int _gnutls_ktls_send_control_msg(gnutls_session_t session, msg.msg_iov = &msg_iov; msg.msg_iovlen = 1; - ret = sendmsg(session->internals.send_fd, &msg, MSG_DONTWAIT); + ret = sendmsg(sockout, &msg, MSG_DONTWAIT); if (ret == -1) { switch (errno) { @@ -299,17 +316,20 @@ int _gnutls_ktls_send_control_msg(gnutls_session_t session, } int _gnutls_ktls_recv_control_msg(gnutls_session_t session, - unsigned char *record_type, void *data, size_t data_size) + unsigned char *record_type, void *data, size_t data_size) { char *buf = data; ssize_t ret; + int sockin, sockout; char cmsg[CMSG_SPACE(sizeof (unsigned char))]; struct msghdr msg = { 0 }; struct iovec msg_iov; struct cmsghdr *hdr; - assert(session != NULL); + assert (session != NULL); + + gnutls_transport_get_int2(session, &sockin, &sockout); if (session->internals.read_eof != 0) { return 0; @@ -327,7 +347,7 @@ int _gnutls_ktls_recv_control_msg(gnutls_session_t session, msg.msg_iov = &msg_iov; msg.msg_iovlen = 1; - ret = recvmsg(session->internals.recv_fd, &msg, MSG_DONTWAIT); + ret = recvmsg(sockin, &msg, MSG_DONTWAIT); if (ret == -1){ switch(errno){ @@ -399,8 +419,11 @@ int _gnutls_ktls_recv_int(gnutls_session_t session, content_type_t type, } #else //ENABLE_KTLS +int gnutls_transport_is_ktls_enabled(gnutls_session_t session){ + return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); +} -int _gnutls_ktls_enable(gnutls_session_t session, int sockin, int sockout){ +int _gnutls_ktls_enable(gnutls_session_t session){ return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); } diff --git a/lib/system/ktls.h b/lib/system/ktls.h index 3955052f58..829799e212 100644 --- a/lib/system/ktls.h +++ b/lib/system/ktls.h @@ -3,7 +3,13 @@ #include "gnutls_int.h" -int _gnutls_ktls_enable(gnutls_session_t session, int sockin, int sockout); +enum{ + KTLS_RECV = 1, + KTLS_SEND, + KTLS_DUPLEX, +}; + +int _gnutls_ktls_enable(gnutls_session_t session); int _gnutls_ktls_set_keys(gnutls_session_t session); int _gnutls_ktls_send_control_msg(gnutls_session_t session, unsigned char record_type, const void *data, size_t data_size); diff --git a/tests/gnutls_ktls.c b/tests/gnutls_ktls.c index 9482e22b31..364f010d04 100644 --- a/tests/gnutls_ktls.c +++ b/tests/gnutls_ktls.c @@ -43,7 +43,7 @@ static void client_log_func(int level, const char *str) } #define MAX_BUF 1024 -#define MSG "Hello world!" +#define MSG "Hello world!\0" static void client(int fd, const char *prio) @@ -63,12 +63,13 @@ static void client(int fd, const char *prio) gnutls_certificate_allocate_credentials(&x509_cred); gnutls_init(&session, GNUTLS_CLIENT); - gnutls_handshake_set_timeout(session, get_timeout()); + 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); - if (ret < 0) - fail("client: error in enabling KTLS: %s\n", gnutls_strerror(ret)); do { ret = gnutls_handshake(session); @@ -77,28 +78,22 @@ static void client(int fd, const char *prio) if (ret < 0) { fail("client: Handshake failed\n"); - close(fd); - gnutls_deinit(session); - exit(1); + goto end; } if (debug) success("client: Handshake was completed\n"); + ret = gnutls_transport_is_ktls_enabled(session); + if (ret != 3){ + fail("client: KTLS was not properly inicialized\n"); + goto end; + } + /* server send message via gnutls_record_send */ - int i = 0; do{ - memset(buffer, 0, MAX_BUF + 1); - do{ - ret = gnutls_record_recv(session, buffer, sizeof(buffer)); - } - while(ret == GNUTLS_E_AGAIN); - - if(strncmp(buffer, MSG+i*MAX_BUF, MAX_BUF)) - fail("client: Message doesn't match\n"); - } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); - - if (debug) - success ("client: messages received\n"); + ret = gnutls_record_recv(session, buffer, sizeof(buffer)); + } + while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); if (ret == 0) { success @@ -106,13 +101,24 @@ static void client(int fd, const char *prio) goto end; } else if (ret < 0) { fail("client: Error: %s\n", gnutls_strerror(ret)); - exit(1); + goto end; + } + + if(strncmp(buffer, MSG, ret)){ + fail("client: Message doesn't match\n"); + goto end; } + if (debug) + success ("client: messages received\n"); + + 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); @@ -122,11 +128,15 @@ static void client(int fd, const char *prio) 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); } @@ -152,7 +162,7 @@ static void server(int fd, const char *prio) exit(1); gnutls_init(&session, GNUTLS_SERVER); - gnutls_handshake_set_timeout(session, get_timeout()); + gnutls_handshake_set_timeout(session, 0); assert(gnutls_priority_set_direct(session, prio, NULL)>=0); @@ -166,33 +176,34 @@ static void server(int fd, const char *prio) while (ret < 0 && gnutls_error_is_fatal(ret) == 0); if (ret < 0) { - close(fd); - gnutls_deinit(session); fail("server: Handshake has failed (%s)\n\n", gnutls_strerror(ret)); - terminate(); + goto end; } if (debug) success("server: Handshake was completed\n"); + ret = gnutls_transport_is_ktls_enabled(session); + if (ret != 3){ + fail("server: KTLS was not properly inicialized\n"); + goto end; + } do { - ret = gnutls_record_send(session, MSG, strlen(MSG)); + ret = gnutls_record_send(session, MSG, strlen(MSG)+1); } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); if (ret < 0) { - close(fd); - gnutls_deinit(session); - gnutls_certificate_free_credentials(x509_cred); - gnutls_global_deinit(); fail("server: data sending has failed (%s)\n\n", gnutls_strerror(ret)); - terminate(); + goto end; } 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); @@ -200,11 +211,20 @@ static void server(int fd, const char *prio) 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; @@ -215,7 +235,7 @@ static void run(const char *prio) success("running ktls test with %s\n", prio); - signal(SIGCHLD, SIG_IGN); + signal(SIGCHLD, ch_handler); signal(SIGPIPE, SIG_IGN); listener = socket(AF_INET, SOCK_STREAM, 0); @@ -246,6 +266,7 @@ static void run(const char *prio) } if (child) { + int status; /* parent */ ret = listen(listener, 1); if (ret == -1) { @@ -257,7 +278,9 @@ static void run(const char *prio) fail("error in accept(): %s\n", strerror(errno)); } server(fd, prio); - kill(child, SIGTERM); + + wait(&status); + check_wait_status(status); } else { fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1){ @@ -273,10 +296,10 @@ static void run(const char *prio) void doit(void) { - run("NORMAL:-VERS-ALL:+VERS-TLS1.2:+AES-128-GCM"); - run("NORMAL:-VERS-ALL:+VERS-TLS1.2:+AES-256-GCM"); - run("NORMAL:-VERS-ALL:+VERS-TLS1.3:+AES-128-GCM"); - run("NORMAL:-VERS-ALL:+VERS-TLS1.3:+AES-256-GCM"); + 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.3:-CIPHER-ALL:+AES-128-GCM"); + run("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM"); } #endif /* _WIN32 */ -- cgit v1.2.1