Enable RX support for kTLS.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 17 May 2018 20:13:55 +0000 (22:13 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 17 May 2018 20:15:09 +0000 (22:15 +0200)
This bumps the TLS requirement to >= 4.17 (tested with 4.17.0-rc4),
and doesn't really help all that much (neither in performance nor
complexity), but there's no point in supporting a separate non-RX-capable
path for 4.13 through 4.16.

Includes updating tlse.c to the latest version.

cubemap.config.sample
server.cpp
server.h
tlse/ktls.h
tlse/tlse.c

index e7119ff..51c46d3 100644 (file)
@@ -11,8 +11,8 @@ num_servers 1
 #
 # You may specify multiple input ports; save for TLS settings (TLS is automatically
 # enabled for a port if you give a key pair), they are treated exactly the same.
-# “port N” is equivalent to “listen [::]:N”. TLS requires kTLS support (Linux >= 4.13,
-# CONFIG_TLS enabled).
+# “port N” is equivalent to “listen [::]:N”. TLS requires kTLS support with both
+# RX and TX (Linux >= 4.17, CONFIG_TLS enabled).
 #
 port 9094
 # listen 127.0.0.1:9095
index c12bc8d..61bdb3f 100644 (file)
@@ -525,7 +525,7 @@ void Server::process_client(Client *client)
 {
        switch (client->state) {
        case Client::READING_REQUEST: {
-               if (client->tls_context != nullptr) {
+               if (client->tls_context != nullptr && !client->in_ktls_mode) {
                        if (send_pending_tls_data(client)) {
                                // send_pending_tls_data() hit postconditions #1 or #4.
                                return;
@@ -536,10 +536,10 @@ read_request_again:
                // Try to read more of the request.
                char buf[1024];
                int ret;
-               if (client->tls_context == nullptr) {
-                       ret = read_nontls_data(client, buf, sizeof(buf));
+               if (client->tls_context == nullptr || client->in_ktls_mode) {
+                       ret = read_plain_data(client, buf, sizeof(buf));
                        if (ret == -1) {
-                               // read_nontls_data() hit postconditions #1 or #2.
+                               // read_plain_data() hit postconditions #1 or #2.
                                return;
                        }
                } else {
@@ -571,22 +571,6 @@ read_request_again:
 
                assert(status == RP_FINISHED);
 
-               if (client->tls_context && !client->in_ktls_mode && tls_established(client->tls_context)) {
-                       // We're ready to enter kTLS mode, unless we still have some
-                       // handshake data to send (which then must be sent as non-kTLS).
-                       if (send_pending_tls_data(client)) {
-                               // send_pending_tls_data() hit postconditions #1 or #4.
-                               return;
-                       }
-                       ret = tls_make_ktls(client->tls_context, client->sock);
-                       if (ret < 0) {
-                               log_tls_error("tls_make_ktls", ret);
-                               close_client(client);
-                               return;
-                       }
-                       client->in_ktls_mode = true;
-               }
-
                int error_code = parse_request(client);
                if (error_code == 200) {
                        if (client->serving_hls_playlist) {
@@ -886,7 +870,7 @@ send_data_again:
        goto send_data_again;
 }
 
-int Server::read_nontls_data(Client *client, char *buf, size_t max_size)
+int Server::read_plain_data(Client *client, char *buf, size_t max_size)
 {
        int ret;
        do {
@@ -915,6 +899,8 @@ int Server::read_nontls_data(Client *client, char *buf, size_t max_size)
 int Server::read_tls_data(Client *client, char *buf, size_t max_size)
 {
 read_again:
+       assert(!client->in_ktls_mode);
+
        int ret;
        do {
                ret = read(client->sock, buf, max_size);
@@ -965,6 +951,22 @@ read_again:
                return -1;
        }
 
+       if (tls_established(client->tls_context)) {
+               // We're ready to enter kTLS mode, unless we still have some
+               // handshake data to send (which then must be sent as non-kTLS).
+               if (send_pending_tls_data(client)) {
+                       // send_pending_tls_data() hit postconditions #1 or #4.
+                       return -1;
+               }
+               int err = tls_make_ktls(client->tls_context, client->sock);  // Don't overwrite ret.
+               if (err < 0) {
+                       log_tls_error("tls_make_ktls", ret);
+                       close_client(client);
+                       return -1;
+               }
+               client->in_ktls_mode = true;
+       }
+
        assert(ret > 0);
        return ret;
 }
index 3727997..d6e6e61 100644 (file)
--- a/server.h
+++ b/server.h
@@ -190,7 +190,7 @@ private:
        // Reads regular data fro ma socket. Returns -1 if the processing
        // should go to sleep (an error, or no data available yet), otherwise
        // the number of bytes read.
-       int read_nontls_data(Client *client, char *buf, size_t max_size);
+       int read_plain_data(Client *client, char *buf, size_t max_size);
 
        // Reads (decrypted) data from a TLS socket. Returns -1 if the processing
        // should go to sleep (an error, or no data available yet), otherwise
index bbcc4f3..7ed59c4 100644 (file)
@@ -38,6 +38,7 @@
 
 /* TLS socket options */
 #define TLS_TX                 1       /* Set transmit parameters */
+#define TLS_RX                 2       /* Set receive parameters */
 
 /* Supported versions */
 #define TLS_VERSION_MINOR(ver) ((ver) & 0xFF)
index dac0263..9b70bc1 100644 (file)
@@ -8187,6 +8187,15 @@ int tls_unmake_ktls(struct TLSContext *context, int socket) {
     }\r
     memcpy(crypto_info.rec_seq, &context->local_sequence_number, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);\r
     context->local_sequence_number = ntohll(context->local_sequence_number);\r
+#ifdef TLS_RX\r
+    crypt_info_size = sizeof(crypto_info);\r
+    if (getsockopt(socket, SOL_TLS, TLS_RX, &crypto_info, &crypt_info_size)) {\r
+        DEBUG_PRINT("ERROR IN getsockopt\n");\r
+        return TLS_GENERIC_ERROR;\r
+    }\r
+    memcpy(crypto_info.rec_seq, &context->remote_sequence_number, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);\r
+    context->remote_sequence_number = ntohll(context->remote_sequence_number);\r
+#endif\r
     return 0;\r
 #endif\r
     DEBUG_PRINT("TLSe COMPILED WITHOUT kTLS SUPPORT\n");\r
@@ -8217,7 +8226,7 @@ int tls_make_ktls(struct TLSContext *context, int socket) {
             return TLS_FEATURE_NOT_SUPPORTED;\r
     }\r
 #ifdef WITH_KTLS\r
-    if (context->exportable_size < TLS_CIPHER_AES_GCM_128_KEY_SIZE) {\r
+    if (context->exportable_size < TLS_CIPHER_AES_GCM_128_KEY_SIZE * 2) {\r
         DEBUG_PRINT("INVALID KEY SIZE\n");\r
         return TLS_GENERIC_ERROR;\r
     }\r
@@ -8231,7 +8240,26 @@ int tls_make_ktls(struct TLSContext *context, int socket) {
     memcpy(crypto_info.rec_seq, &local_sequence_number, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);\r
     memcpy(crypto_info.key, context->exportable_keys, TLS_CIPHER_AES_GCM_128_KEY_SIZE);\r
     memcpy(crypto_info.salt, context->crypto.ctx_local_mac.local_aead_iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);\r
+\r
     setsockopt(socket, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));\r
+\r
+#ifdef TLS_RX\r
+    // kernel 4.17 adds TLS_RX support\r
+    struct tls12_crypto_info_aes_gcm_128 crypto_info_read;\r
+\r
+    crypto_info_read.info.version = TLS_1_2_VERSION;\r
+    crypto_info_read.info.cipher_type = TLS_CIPHER_AES_GCM_128;\r
+\r
+    uint64_t remote_sequence_number = htonll(context->remote_sequence_number);\r
+    memcpy(crypto_info_read.iv, &remote_sequence_number, TLS_CIPHER_AES_GCM_128_IV_SIZE);\r
+    memcpy(crypto_info_read.rec_seq, &remote_sequence_number, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);\r
+    memcpy(crypto_info_read.key, context->exportable_keys + TLS_CIPHER_AES_GCM_128_KEY_SIZE, TLS_CIPHER_AES_GCM_128_KEY_SIZE);\r
+    memcpy(crypto_info_read.salt, context->crypto.ctx_remote_mac.remote_aead_iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);\r
+\r
+    int err = setsockopt(socket, SOL_TLS, TLS_RX, &crypto_info_read, sizeof(crypto_info_read));\r
+    if (err)\r
+        return err;\r
+#endif\r
     return setsockopt(socket, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info));\r
 #else\r
     DEBUG_PRINT("TLSe COMPILED WITHOUT kTLS SUPPORT\n");\r