mirror of
https://github.com/openssl/openssl.git
synced 2025-01-30 14:01:55 +08:00
Add support for in-kernel TLS (KTLS) on FreeBSD.
- Check for the <sys/ktls.h> header to determine if KTLS support is available. - Populate a tls_enable structure with session key material for supported algorithms. At present, AES-GCM128/256 and AES-CBC128/256 with SHA1 and SHA2-256 HMACs are supported. For AES-CBC, only MtE is supported. Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/10045)
This commit is contained in:
parent
181ea366f6
commit
2111f5c283
@ -1586,8 +1586,14 @@ unless ($disabled{ktls}) {
|
||||
if ($verstr[2] < $minver) {
|
||||
disable('too-old-kernel', 'ktls');
|
||||
}
|
||||
} elsif ($target =~ m/^BSD/) {
|
||||
my $cc = $config{CROSS_COMPILE}.$config{CC};
|
||||
system("printf '#include <sys/types.h>\n#include <sys/ktls.h>' | $cc -E - >/dev/null 2>&1");
|
||||
if ($? != 0) {
|
||||
disable('too-old-freebsd', 'ktls');
|
||||
}
|
||||
} else {
|
||||
disable('not-linux', 'ktls');
|
||||
disable('not-linux-or-freebsd', 'ktls');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,11 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
long ret = 1;
|
||||
int *ip;
|
||||
# ifndef OPENSSL_NO_KTLS
|
||||
# ifdef __FreeBSD__
|
||||
struct tls_enable *crypto_info;
|
||||
# else
|
||||
struct tls12_crypto_info_aes_gcm_128 *crypto_info;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
switch (cmd) {
|
||||
@ -183,7 +187,11 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
break;
|
||||
# ifndef OPENSSL_NO_KTLS
|
||||
case BIO_CTRL_SET_KTLS:
|
||||
# ifdef __FreeBSD__
|
||||
crypto_info = (struct tls_enable *)ptr;
|
||||
# else
|
||||
crypto_info = (struct tls12_crypto_info_aes_gcm_128 *)ptr;
|
||||
# endif
|
||||
ret = ktls_start(b->num, crypto_info, sizeof(*crypto_info), num);
|
||||
if (ret)
|
||||
BIO_set_ktls_flag(b, num);
|
||||
|
@ -11,6 +11,103 @@
|
||||
# ifndef HEADER_INTERNAL_KTLS
|
||||
# define HEADER_INTERNAL_KTLS
|
||||
|
||||
# if defined(__FreeBSD__)
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <sys/ktls.h>
|
||||
# include <netinet/in.h>
|
||||
# include <netinet/tcp.h>
|
||||
# include <crypto/cryptodev.h>
|
||||
|
||||
/*
|
||||
* Only used by the tests in sslapitest.c.
|
||||
*/
|
||||
# define TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE 8
|
||||
|
||||
/*
|
||||
* FreeBSD does not require any additional steps to enable KTLS before
|
||||
* setting keys.
|
||||
*/
|
||||
static ossl_inline int ktls_enable(int fd)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The TCP_TXTLS_ENABLE socket option marks the outgoing socket buffer
|
||||
* as using TLS. If successful, then data sent using this socket will
|
||||
* be encrypted and encapsulated in TLS records using the tls_en.
|
||||
* provided here.
|
||||
*/
|
||||
static ossl_inline int ktls_start(int fd,
|
||||
struct tls_enable *tls_en,
|
||||
size_t len, int is_tx)
|
||||
{
|
||||
if (is_tx)
|
||||
return setsockopt(fd, IPPROTO_TCP, TCP_TXTLS_ENABLE,
|
||||
tls_en, sizeof(*tls_en)) ? 0 : 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a TLS record using the tls_en provided in ktls_start and use
|
||||
* record_type instead of the default SSL3_RT_APPLICATION_DATA.
|
||||
* When the socket is non-blocking, then this call either returns EAGAIN or
|
||||
* the entire record is pushed to TCP. It is impossible to send a partial
|
||||
* record using this control message.
|
||||
*/
|
||||
static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type,
|
||||
const void *data, size_t length)
|
||||
{
|
||||
struct msghdr msg = { 0 };
|
||||
int cmsg_len = sizeof(record_type);
|
||||
struct cmsghdr *cmsg;
|
||||
char buf[CMSG_SPACE(cmsg_len)];
|
||||
struct iovec msg_iov; /* Vector of data to send/receive into */
|
||||
|
||||
msg.msg_control = buf;
|
||||
msg.msg_controllen = sizeof(buf);
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = IPPROTO_TCP;
|
||||
cmsg->cmsg_type = TLS_SET_RECORD_TYPE;
|
||||
cmsg->cmsg_len = CMSG_LEN(cmsg_len);
|
||||
*((unsigned char *)CMSG_DATA(cmsg)) = record_type;
|
||||
msg.msg_controllen = cmsg->cmsg_len;
|
||||
|
||||
msg_iov.iov_base = (void *)data;
|
||||
msg_iov.iov_len = length;
|
||||
msg.msg_iov = &msg_iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
return sendmsg(fd, &msg, 0);
|
||||
}
|
||||
|
||||
static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* KTLS enables the sendfile system call to send data from a file over
|
||||
* TLS.
|
||||
*/
|
||||
static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off,
|
||||
size_t size, int flags)
|
||||
{
|
||||
off_t sbytes;
|
||||
int ret;
|
||||
|
||||
ret = sendfile(fd, s, off, size, NULL, &sbytes, flags);
|
||||
if (ret == -1) {
|
||||
if (errno == EAGAIN && sbytes != 0)
|
||||
return sbytes;
|
||||
return -1;
|
||||
}
|
||||
return sbytes;
|
||||
}
|
||||
# endif /* __FreeBSD__ */
|
||||
|
||||
# if defined(OPENSSL_SYS_LINUX)
|
||||
# include <linux/version.h>
|
||||
|
||||
|
45
ssl/t1_enc.c
45
ssl/t1_enc.c
@ -151,11 +151,15 @@ int tls1_change_cipher_state(SSL *s, int which)
|
||||
size_t n, i, j, k, cl;
|
||||
int reuse_dd = 0;
|
||||
#ifndef OPENSSL_NO_KTLS
|
||||
# ifdef __FreeBSD__
|
||||
struct tls_enable crypto_info;
|
||||
# else
|
||||
struct tls12_crypto_info_aes_gcm_128 crypto_info;
|
||||
BIO *bio;
|
||||
unsigned char geniv[12];
|
||||
int count_unprocessed;
|
||||
int bit;
|
||||
# endif
|
||||
BIO *bio;
|
||||
#endif
|
||||
|
||||
c = s->s3.tmp.new_sym_enc;
|
||||
@ -387,6 +391,42 @@ 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;
|
||||
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
|
||||
/* check that cipher is AES_GCM_128 */
|
||||
if (EVP_CIPHER_nid(c) != NID_aes_128_gcm
|
||||
|| EVP_CIPHER_mode(c) != EVP_CIPH_GCM_MODE
|
||||
@ -396,6 +436,7 @@ int tls1_change_cipher_state(SSL *s, int which)
|
||||
/* check version is 1.2 */
|
||||
if (s->version != TLS1_2_VERSION)
|
||||
goto skip_ktls;
|
||||
# endif
|
||||
|
||||
if (which & SSL3_CC_WRITE)
|
||||
bio = s->wbio;
|
||||
@ -422,6 +463,7 @@ int tls1_change_cipher_state(SSL *s, int which)
|
||||
goto err;
|
||||
}
|
||||
|
||||
# ifndef __FreeBSD__
|
||||
memset(&crypto_info, 0, sizeof(crypto_info));
|
||||
crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
|
||||
crypto_info.info.version = s->version;
|
||||
@ -455,6 +497,7 @@ int tls1_change_cipher_state(SSL *s, int which)
|
||||
count_unprocessed--;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
/* ktls works with user provided buffers directly */
|
||||
if (BIO_set_ktls(bio, &crypto_info, which & SSL3_CC_WRITE)) {
|
||||
|
Loading…
Reference in New Issue
Block a user