kTLS: add Linux-specific kTLS helpers
authorVadim Fedorenko <vadimjunk@gmail.com>
Fri, 1 May 2020 20:56:48 +0000 (23:56 +0300)
committerMatt Caswell <matt@openssl.org>
Mon, 8 Jun 2020 10:13:52 +0000 (11:13 +0100)
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11589)

include/internal/ktls.h

index 4a640b769ad3a8f13852b6df28b2e40f5c3b02f0..093a6618438670b6c03928db2fab0dde0dd6ce29 100644 (file)
@@ -309,6 +309,103 @@ static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
 }
 
 #   endif /* OPENSSL_NO_KTLS_RX */
+
+/* Function to check supported ciphers in Linux */
+static ossl_inline int ktls_check_supported_cipher(const EVP_CIPHER *c,
+                                            const EVP_CIPHER_CTX *dd)
+{
+    /* check that cipher is AES_GCM_128, AES_GCM_256, AES_CCM_128 */
+    switch (EVP_CIPHER_nid(c))
+    {
+#  ifdef OPENSSL_KTLS_AES_CCM_128
+    case NID_aes_128_ccm:
+        if (EVP_CIPHER_CTX_tag_length(dd) != EVP_CCM_TLS_TAG_LEN)
+          return 0;
+#  endif
+#  ifdef OPENSSL_KTLS_AES_GCM_128
+    case NID_aes_128_gcm:
+#  endif
+#  ifdef OPENSSL_KTLS_AES_GCM_256
+    case NID_aes_256_gcm:
+#  endif
+        return 1;
+    default:
+        return 0;
+    }
+}
+
+/* Function to configure kernel TLS structure */
+static ossl_inline int ktls_configure_crypto(const EVP_CIPHER *c, int tls_version,
+                                EVP_CIPHER_CTX *dd, void *rl_sequence,
+                                struct tls_crypto_info_all *crypto_info,
+                                unsigned char **rec_seq, unsigned char *iv,
+                                unsigned char *key)
+{
+    unsigned char geniv[12];
+    unsigned char *iiv = iv;
+
+    if (tls_version == TLS1_2_VERSION &&
+        EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) {
+        EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GET_IV,
+                            EVP_GCM_TLS_FIXED_IV_LEN + EVP_GCM_TLS_EXPLICIT_IV_LEN,
+                            geniv);
+        iiv = geniv;
+    }
+
+    memset(crypto_info, 0, sizeof(*crypto_info));
+    switch (EVP_CIPHER_nid(c))
+    {
+#  ifdef OPENSSL_KTLS_AES_GCM_128
+    case NID_aes_128_gcm:
+        crypto_info->gcm128.info.cipher_type = TLS_CIPHER_AES_GCM_128;
+        crypto_info->gcm128.info.version = tls_version;
+        crypto_info->tls_crypto_info_len = sizeof(crypto_info->gcm128);
+        memcpy(crypto_info->gcm128.iv, iiv + EVP_GCM_TLS_FIXED_IV_LEN,
+                TLS_CIPHER_AES_GCM_128_IV_SIZE);
+        memcpy(crypto_info->gcm128.salt, iiv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
+        memcpy(crypto_info->gcm128.key, key, EVP_CIPHER_key_length(c));
+        memcpy(crypto_info->gcm128.rec_seq, rl_sequence,
+                TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
+        if (rec_seq != NULL)
+            *rec_seq = crypto_info->gcm128.rec_seq;
+        return 1;
+#  endif
+#  ifdef OPENSSL_KTLS_AES_GCM_256
+    case NID_aes_256_gcm:
+        crypto_info->gcm256.info.cipher_type = TLS_CIPHER_AES_GCM_256;
+        crypto_info->gcm256.info.version = tls_version;
+        crypto_info->tls_crypto_info_len = sizeof(crypto_info->gcm256);
+        memcpy(crypto_info->gcm256.iv, iiv + EVP_GCM_TLS_FIXED_IV_LEN,
+                TLS_CIPHER_AES_GCM_256_IV_SIZE);
+        memcpy(crypto_info->gcm256.salt, iiv, TLS_CIPHER_AES_GCM_256_SALT_SIZE);
+        memcpy(crypto_info->gcm256.key, key, EVP_CIPHER_key_length(c));
+        memcpy(crypto_info->gcm256.rec_seq, rl_sequence,
+                TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE);
+        if (rec_seq != NULL)
+            *rec_seq = crypto_info->gcm256.rec_seq;
+        return 1;
+#  endif
+#  ifdef OPENSSL_KTLS_AES_CCM_128
+    case NID_aes_128_ccm:
+        crypto_info->ccm128.info.cipher_type = TLS_CIPHER_AES_CCM_128;
+        crypto_info->ccm128.info.version = tls_version;
+        crypto_info->tls_crypto_info_len = sizeof(crypto_info->ccm128);
+        memcpy(crypto_info->ccm128.iv, iiv + EVP_CCM_TLS_FIXED_IV_LEN,
+                TLS_CIPHER_AES_CCM_128_IV_SIZE);
+        memcpy(crypto_info->ccm128.salt, iiv, TLS_CIPHER_AES_CCM_128_SALT_SIZE);
+        memcpy(crypto_info->ccm128.key, key, EVP_CIPHER_key_length(c));
+        memcpy(crypto_info->ccm128.rec_seq, rl_sequence,
+                TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE);
+        if (rec_seq != NULL)
+            *rec_seq = crypto_info->ccm128.rec_seq;
+        return 1;
+#  endif
+    default:
+        return 0;
+    }
+
+}
+
 #  endif /* OPENSSL_SYS_LINUX */
 # endif /* HEADER_INTERNAL_KTLS */
 #else /* defined(OPENSSL_NO_KTLS) */