Add helper functions for FreeBSD KTLS.

These are similar to the helpers added in 95badfeb60.  I've adjusted
the arguments passed to ktls_check_supported_cipher and
ktls_configure_crypto so that FreeBSD and Linux can both use the same
signature to avoid OS-specific #ifdef's in libssl.  This also required
moving the check on valid TLS versions into
ktls_check_supported_cipher for Linux.  This has largely removed
OS-specific code and OS-specific #ifdef's for KTLS outside of
<internal/ktls.h>.

Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12111)
This commit is contained in:
John Baldwin 2020-06-10 13:36:38 -07:00 committed by Matt Caswell
parent c34ca13a60
commit 3e5826061b
3 changed files with 135 additions and 69 deletions

View File

@ -32,10 +32,15 @@
# include <netinet/tcp.h>
# include <crypto/cryptodev.h>
# define OPENSSL_NO_KTLS_RX
# define OPENSSL_KTLS_AES_GCM_128
# define OPENSSL_KTLS_AES_GCM_256
/*
* Only used by the tests in sslapitest.c.
*/
# define TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE 8
# define TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE 8
typedef struct tls_enable ktls_crypto_info_t;
@ -121,6 +126,100 @@ static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off,
}
return sbytes;
}
# ifdef OSSL_SSL_LOCAL_H
/*-
* Check if a given cipher is supported by the KTLS interface.
* The kernel might still fail the setsockopt() if no suitable
* provider is found, but this checks if the socket option
* supports the cipher suite used at all.
*/
static ossl_inline int ktls_check_supported_cipher(const SSL *s,
const EVP_CIPHER *c,
const EVP_CIPHER_CTX *dd)
{
switch (s->version) {
case TLS1_VERSION:
case TLS1_1_VERSION:
case TLS1_2_VERSION:
break;
default:
return 0;
}
switch (s->s3.tmp.new_cipher->algorithm_enc) {
case SSL_AES128GCM:
case SSL_AES256GCM:
return 1;
case SSL_AES128:
case SSL_AES256:
if (s->ext.use_etm)
return 0;
switch (s->s3.tmp.new_cipher->algorithm_mac) {
case SSL_SHA1:
case SSL_SHA256:
case SSL_SHA384:
return 1;
default:
return 0;
}
default:
return 0;
}
}
/* Function to configure kernel TLS structure */
static ossl_inline int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c,
EVP_CIPHER_CTX *dd,
void *rl_sequence,
ktls_crypto_info_t *crypto_info,
unsigned char **rec_seq,
unsigned char *iv,
unsigned char *key,
unsigned char *mac_key,
size_t mac_secret_size)
{
memset(crypto_info, 0, sizeof(*crypto_info));
switch (s->s3.tmp.new_cipher->algorithm_enc) {
case SSL_AES128GCM:
case SSL_AES256GCM:
crypto_info->cipher_algorithm = CRYPTO_AES_NIST_GCM_16;
crypto_info->iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
break;
case SSL_AES128:
case SSL_AES256:
switch (s->s3.tmp.new_cipher->algorithm_mac) {
case SSL_SHA1:
crypto_info->auth_algorithm = CRYPTO_SHA1_HMAC;
break;
case SSL_SHA256:
crypto_info->auth_algorithm = CRYPTO_SHA2_256_HMAC;
break;
case SSL_SHA384:
crypto_info->auth_algorithm = CRYPTO_SHA2_384_HMAC;
break;
default:
return 0;
}
crypto_info->cipher_algorithm = CRYPTO_AES_CBC;
crypto_info->iv_len = EVP_CIPHER_iv_length(c);
crypto_info->auth_key = mac_key;
crypto_info->auth_key_len = mac_secret_size;
break;
default:
return 0;
}
crypto_info->cipher_key = key;
crypto_info->cipher_key_len = EVP_CIPHER_key_length(c);
crypto_info->iv = iv;
crypto_info->tls_vmajor = (s->version >> 8) & 0x000000ff;
crypto_info->tls_vminor = (s->version & 0x000000ff);
if (rec_seq != NULL)
*rec_seq = NULL;
return 1;
};
# endif /* OSSL_SSL_LOCAL_H */
# endif /* __FreeBSD__ */
# if defined(OPENSSL_SYS_LINUX)
@ -315,10 +414,20 @@ static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
# endif /* OPENSSL_NO_KTLS_RX */
# ifdef OSSL_SSL_LOCAL_H
/* Function to check supported ciphers in Linux */
static ossl_inline int ktls_check_supported_cipher(const EVP_CIPHER *c,
const EVP_CIPHER_CTX *dd)
static ossl_inline int ktls_check_supported_cipher(const SSL *s,
const EVP_CIPHER *c,
const EVP_CIPHER_CTX *dd)
{
switch (s->version) {
case TLS1_2_VERSION:
case TLS1_3_VERSION:
break;
default:
return 0;
}
/* check that cipher is AES_GCM_128, AES_GCM_256, AES_CCM_128 */
switch (EVP_CIPHER_nid(c))
{
@ -340,16 +449,20 @@ static ossl_inline int ktls_check_supported_cipher(const EVP_CIPHER *c,
}
/* 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)
static ossl_inline int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c,
EVP_CIPHER_CTX *dd,
void *rl_sequence,
ktls_crypto_info_t *crypto_info,
unsigned char **rec_seq,
unsigned char *iv,
unsigned char *key,
unsigned char *mac_key,
size_t mac_secret_size)
{
unsigned char geniv[12];
unsigned char *iiv = iv;
if (tls_version == TLS1_2_VERSION &&
if (s->version == TLS1_2_VERSION &&
EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) {
if (!EVP_CIPHER_CTX_get_iv_state(dd, geniv,
EVP_GCM_TLS_FIXED_IV_LEN
@ -364,7 +477,7 @@ static ossl_inline int ktls_configure_crypto(const EVP_CIPHER *c, int tls_versio
# 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->gcm128.info.version = s->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);
@ -379,7 +492,7 @@ static ossl_inline int ktls_configure_crypto(const EVP_CIPHER *c, int tls_versio
# 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->gcm256.info.version = s->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);
@ -394,7 +507,7 @@ static ossl_inline int ktls_configure_crypto(const EVP_CIPHER *c, int tls_versio
# 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->ccm128.info.version = s->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);
@ -411,6 +524,7 @@ static ossl_inline int ktls_configure_crypto(const EVP_CIPHER *c, int tls_versio
}
}
# endif /* OSSL_SSL_LOCAL_H */
# endif /* OPENSSL_SYS_LINUX */
# endif /* HEADER_INTERNAL_KTLS */

View File

@ -193,13 +193,11 @@ int tls1_change_cipher_state(SSL *s, int which)
int reuse_dd = 0;
#ifndef OPENSSL_NO_KTLS
ktls_crypto_info_t crypto_info;
# ifndef __FreeBSD__
unsigned char *rec_seq;
void *rl_sequence;
# ifndef OPENSSL_NO_KTLS_RX
# ifndef OPENSSL_NO_KTLS_RX
int count_unprocessed;
int bit;
# endif
# endif
BIO *bio;
#endif
@ -463,54 +461,10 @@ int tls1_change_cipher_state(SSL *s, int which)
if (ssl_get_max_send_fragment(s) != SSL3_RT_MAX_PLAIN_LENGTH)
goto skip_ktls;
# ifdef __FreeBSD__
memset(&crypto_info, 0, sizeof(crypto_info));
switch (s->s3.tmp.new_cipher->algorithm_enc) {
case SSL_AES128GCM:
case SSL_AES256GCM:
crypto_info.cipher_algorithm = CRYPTO_AES_NIST_GCM_16;
crypto_info.iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
break;
case SSL_AES128:
case SSL_AES256:
if (s->ext.use_etm)
goto skip_ktls;
switch (s->s3.tmp.new_cipher->algorithm_mac) {
case SSL_SHA1:
crypto_info.auth_algorithm = CRYPTO_SHA1_HMAC;
break;
case SSL_SHA256:
crypto_info.auth_algorithm = CRYPTO_SHA2_256_HMAC;
break;
case SSL_SHA384:
crypto_info.auth_algorithm = CRYPTO_SHA2_384_HMAC;
break;
default:
goto skip_ktls;
}
crypto_info.cipher_algorithm = CRYPTO_AES_CBC;
crypto_info.iv_len = EVP_CIPHER_iv_length(c);
crypto_info.auth_key = ms;
crypto_info.auth_key_len = *mac_secret_size;
break;
default:
goto skip_ktls;
}
crypto_info.cipher_key = key;
crypto_info.cipher_key_len = EVP_CIPHER_key_length(c);
crypto_info.iv = iv;
crypto_info.tls_vmajor = (s->version >> 8) & 0x000000ff;
crypto_info.tls_vminor = (s->version & 0x000000ff);
# else /* !defined(__FreeBSD__) */
/* check that cipher is supported */
if (!ktls_check_supported_cipher(c, dd))
if (!ktls_check_supported_cipher(s, c, dd))
goto skip_ktls;
/* check version */
if (s->version != TLS1_2_VERSION)
goto skip_ktls;
# endif
if (which & SSL3_CC_WRITE)
bio = s->wbio;
else
@ -536,18 +490,17 @@ int tls1_change_cipher_state(SSL *s, int which)
goto err;
}
# ifndef __FreeBSD__
if (which & SSL3_CC_WRITE)
rl_sequence = RECORD_LAYER_get_write_sequence(&s->rlayer);
else
rl_sequence = RECORD_LAYER_get_read_sequence(&s->rlayer);
if (!ktls_configure_crypto(c, s->version, dd, rl_sequence, &crypto_info,
&rec_seq, iv, key))
if (!ktls_configure_crypto(s, c, dd, rl_sequence, &crypto_info, &rec_seq,
iv, key, ms, *mac_secret_size))
goto skip_ktls;
if (which & SSL3_CC_READ) {
# ifndef OPENSSL_NO_KTLS_RX
# ifndef OPENSSL_NO_KTLS_RX
count_unprocessed = count_unprocessed_records(s);
if (count_unprocessed < 0)
goto skip_ktls;
@ -561,11 +514,10 @@ int tls1_change_cipher_state(SSL *s, int which)
}
count_unprocessed--;
}
# else
# else
goto skip_ktls;
# endif
# endif
}
# endif /* !__FreeBSD__ */
/* ktls works with user provided buffers directly */
if (BIO_set_ktls(bio, &crypto_info, which & SSL3_CC_WRITE)) {

View File

@ -798,7 +798,7 @@ int tls13_change_cipher_state(SSL *s, int which)
goto skip_ktls;
/* check that cipher is supported */
if (!ktls_check_supported_cipher(cipher, ciph_ctx))
if (!ktls_check_supported_cipher(s, cipher, ciph_ctx))
goto skip_ktls;
bio = s->wbio;
@ -814,9 +814,9 @@ int tls13_change_cipher_state(SSL *s, int which)
goto skip_ktls;
/* configure kernel crypto structure */
if (!ktls_configure_crypto(cipher, s->version, ciph_ctx,
if (!ktls_configure_crypto(s, cipher, ciph_ctx,
RECORD_LAYER_get_write_sequence(&s->rlayer),
&crypto_info, NULL, iv, key))
&crypto_info, NULL, iv, key, NULL, 0))
goto skip_ktls;
/* ktls works with user provided buffers directly */