Home | History | Annotate | Line # | Download | only in internal
      1  1.1  christos /*
      2  1.1  christos  * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
      3  1.1  christos  *
      4  1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6  1.1  christos  * in the file LICENSE in the source distribution or at
      7  1.1  christos  * https://www.openssl.org/source/license.html
      8  1.1  christos  */
      9  1.1  christos 
     10  1.1  christos #if defined(OPENSSL_SYS_LINUX)
     11  1.1  christos # ifndef OPENSSL_NO_KTLS
     12  1.1  christos #  include <linux/version.h>
     13  1.1  christos #  if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
     14  1.1  christos #   define OPENSSL_NO_KTLS
     15  1.1  christos #   ifndef PEDANTIC
     16  1.1  christos #    warning "KTLS requires Kernel Headers >= 4.13.0"
     17  1.1  christos #    warning "Skipping Compilation of KTLS"
     18  1.1  christos #   endif
     19  1.1  christos #  endif
     20  1.1  christos # endif
     21  1.1  christos #endif
     22  1.1  christos 
     23  1.1  christos #ifndef HEADER_INTERNAL_KTLS
     24  1.1  christos # define HEADER_INTERNAL_KTLS
     25  1.1  christos # pragma once
     26  1.1  christos 
     27  1.1  christos # ifndef OPENSSL_NO_KTLS
     28  1.1  christos 
     29  1.1  christos #  if defined(__FreeBSD__)
     30  1.1  christos #   include <sys/types.h>
     31  1.1  christos #   include <sys/socket.h>
     32  1.1  christos #   include <sys/ktls.h>
     33  1.1  christos #   include <netinet/in.h>
     34  1.1  christos #   include <netinet/tcp.h>
     35  1.1  christos #   include <openssl/ssl3.h>
     36  1.1  christos 
     37  1.1  christos #   ifndef TCP_RXTLS_ENABLE
     38  1.1  christos #    define OPENSSL_NO_KTLS_RX
     39  1.1  christos #   endif
     40  1.1  christos #   define OPENSSL_KTLS_AES_GCM_128
     41  1.1  christos #   define OPENSSL_KTLS_AES_GCM_256
     42  1.1  christos #   define OPENSSL_KTLS_TLS13
     43  1.1  christos 
     44  1.1  christos typedef struct tls_enable ktls_crypto_info_t;
     45  1.1  christos 
     46  1.1  christos /*
     47  1.1  christos  * FreeBSD does not require any additional steps to enable KTLS before
     48  1.1  christos  * setting keys.
     49  1.1  christos  */
     50  1.1  christos static ossl_inline int ktls_enable(int fd)
     51  1.1  christos {
     52  1.1  christos     return 1;
     53  1.1  christos }
     54  1.1  christos 
     55  1.1  christos /*
     56  1.1  christos  * The TCP_TXTLS_ENABLE socket option marks the outgoing socket buffer
     57  1.1  christos  * as using TLS.  If successful, then data sent using this socket will
     58  1.1  christos  * be encrypted and encapsulated in TLS records using the tls_en
     59  1.1  christos  * provided here.
     60  1.1  christos  *
     61  1.1  christos  * The TCP_RXTLS_ENABLE socket option marks the incoming socket buffer
     62  1.1  christos  * as using TLS.  If successful, then data received for this socket will
     63  1.1  christos  * be authenticated and decrypted using the tls_en provided here.
     64  1.1  christos  */
     65  1.1  christos static ossl_inline int ktls_start(int fd, ktls_crypto_info_t *tls_en, int is_tx)
     66  1.1  christos {
     67  1.1  christos     if (is_tx)
     68  1.1  christos         return setsockopt(fd, IPPROTO_TCP, TCP_TXTLS_ENABLE,
     69  1.1  christos                           tls_en, sizeof(*tls_en)) ? 0 : 1;
     70  1.1  christos #   ifndef OPENSSL_NO_KTLS_RX
     71  1.1  christos     return setsockopt(fd, IPPROTO_TCP, TCP_RXTLS_ENABLE, tls_en,
     72  1.1  christos                       sizeof(*tls_en)) ? 0 : 1;
     73  1.1  christos #   else
     74  1.1  christos     return 0;
     75  1.1  christos #   endif
     76  1.1  christos }
     77  1.1  christos 
     78  1.1  christos /*
     79  1.1  christos  * Send a TLS record using the tls_en provided in ktls_start and use
     80  1.1  christos  * record_type instead of the default SSL3_RT_APPLICATION_DATA.
     81  1.1  christos  * When the socket is non-blocking, then this call either returns EAGAIN or
     82  1.1  christos  * the entire record is pushed to TCP. It is impossible to send a partial
     83  1.1  christos  * record using this control message.
     84  1.1  christos  */
     85  1.1  christos static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type,
     86  1.1  christos                                               const void *data, size_t length)
     87  1.1  christos {
     88  1.1  christos     struct msghdr msg = { 0 };
     89  1.1  christos     int cmsg_len = sizeof(record_type);
     90  1.1  christos     struct cmsghdr *cmsg;
     91  1.1  christos     char buf[CMSG_SPACE(cmsg_len)];
     92  1.1  christos     struct iovec msg_iov;   /* Vector of data to send/receive into */
     93  1.1  christos 
     94  1.1  christos     msg.msg_control = buf;
     95  1.1  christos     msg.msg_controllen = sizeof(buf);
     96  1.1  christos     cmsg = CMSG_FIRSTHDR(&msg);
     97  1.1  christos     cmsg->cmsg_level = IPPROTO_TCP;
     98  1.1  christos     cmsg->cmsg_type = TLS_SET_RECORD_TYPE;
     99  1.1  christos     cmsg->cmsg_len = CMSG_LEN(cmsg_len);
    100  1.1  christos     *((unsigned char *)CMSG_DATA(cmsg)) = record_type;
    101  1.1  christos     msg.msg_controllen = cmsg->cmsg_len;
    102  1.1  christos 
    103  1.1  christos     msg_iov.iov_base = (void *)data;
    104  1.1  christos     msg_iov.iov_len = length;
    105  1.1  christos     msg.msg_iov = &msg_iov;
    106  1.1  christos     msg.msg_iovlen = 1;
    107  1.1  christos 
    108  1.1  christos     return sendmsg(fd, &msg, 0);
    109  1.1  christos }
    110  1.1  christos 
    111  1.1  christos #   ifdef OPENSSL_NO_KTLS_RX
    112  1.1  christos 
    113  1.1  christos static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
    114  1.1  christos {
    115  1.1  christos     return -1;
    116  1.1  christos }
    117  1.1  christos 
    118  1.1  christos #   else /* !defined(OPENSSL_NO_KTLS_RX) */
    119  1.1  christos 
    120  1.1  christos /*
    121  1.1  christos  * Receive a TLS record using the tls_en provided in ktls_start.  The
    122  1.1  christos  * kernel strips any explicit IV and authentication tag, but provides
    123  1.1  christos  * the TLS record header via a control message.  If there is an error
    124  1.1  christos  * with the TLS record such as an invalid header, invalid padding, or
    125  1.1  christos  * authentication failure recvmsg() will fail with an error.
    126  1.1  christos  */
    127  1.1  christos static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
    128  1.1  christos {
    129  1.1  christos     struct msghdr msg = { 0 };
    130  1.1  christos     int cmsg_len = sizeof(struct tls_get_record);
    131  1.1  christos     struct tls_get_record *tgr;
    132  1.1  christos     struct cmsghdr *cmsg;
    133  1.1  christos     char buf[CMSG_SPACE(cmsg_len)];
    134  1.1  christos     struct iovec msg_iov;   /* Vector of data to send/receive into */
    135  1.1  christos     int ret;
    136  1.1  christos     unsigned char *p = data;
    137  1.1  christos     const size_t prepend_length = SSL3_RT_HEADER_LENGTH;
    138  1.1  christos 
    139  1.1  christos     if (length <= prepend_length) {
    140  1.1  christos         errno = EINVAL;
    141  1.1  christos         return -1;
    142  1.1  christos     }
    143  1.1  christos 
    144  1.1  christos     msg.msg_control = buf;
    145  1.1  christos     msg.msg_controllen = sizeof(buf);
    146  1.1  christos 
    147  1.1  christos     msg_iov.iov_base = p + prepend_length;
    148  1.1  christos     msg_iov.iov_len = length - prepend_length;
    149  1.1  christos     msg.msg_iov = &msg_iov;
    150  1.1  christos     msg.msg_iovlen = 1;
    151  1.1  christos 
    152  1.1  christos     ret = recvmsg(fd, &msg, 0);
    153  1.1  christos     if (ret <= 0)
    154  1.1  christos         return ret;
    155  1.1  christos 
    156  1.1  christos     if ((msg.msg_flags & (MSG_EOR | MSG_CTRUNC)) != MSG_EOR) {
    157  1.1  christos         errno = EMSGSIZE;
    158  1.1  christos         return -1;
    159  1.1  christos     }
    160  1.1  christos 
    161  1.1  christos     if (msg.msg_controllen == 0) {
    162  1.1  christos         errno = EBADMSG;
    163  1.1  christos         return -1;
    164  1.1  christos     }
    165  1.1  christos 
    166  1.1  christos     cmsg = CMSG_FIRSTHDR(&msg);
    167  1.1  christos     if (cmsg->cmsg_level != IPPROTO_TCP || cmsg->cmsg_type != TLS_GET_RECORD
    168  1.1  christos         || cmsg->cmsg_len != CMSG_LEN(cmsg_len)) {
    169  1.1  christos         errno = EBADMSG;
    170  1.1  christos         return -1;
    171  1.1  christos     }
    172  1.1  christos 
    173  1.1  christos     tgr = (struct tls_get_record *)CMSG_DATA(cmsg);
    174  1.1  christos     p[0] = tgr->tls_type;
    175  1.1  christos     p[1] = tgr->tls_vmajor;
    176  1.1  christos     p[2] = tgr->tls_vminor;
    177  1.1  christos     *(uint16_t *)(p + 3) = htons(ret);
    178  1.1  christos 
    179  1.1  christos     return ret + prepend_length;
    180  1.1  christos }
    181  1.1  christos 
    182  1.1  christos #   endif /* OPENSSL_NO_KTLS_RX */
    183  1.1  christos 
    184  1.1  christos /*
    185  1.1  christos  * KTLS enables the sendfile system call to send data from a file over
    186  1.1  christos  * TLS.
    187  1.1  christos  */
    188  1.1  christos static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off,
    189  1.1  christos                                               size_t size, int flags)
    190  1.1  christos {
    191  1.1  christos     off_t sbytes = 0;
    192  1.1  christos     int ret;
    193  1.1  christos 
    194  1.1  christos     ret = sendfile(fd, s, off, size, NULL, &sbytes, flags);
    195  1.1  christos     if (ret == -1 && sbytes == 0)
    196  1.1  christos         return -1;
    197  1.1  christos     return sbytes;
    198  1.1  christos }
    199  1.1  christos 
    200  1.1  christos #  endif                         /* __FreeBSD__ */
    201  1.1  christos 
    202  1.1  christos #  if defined(OPENSSL_SYS_LINUX)
    203  1.1  christos 
    204  1.1  christos #   include <linux/tls.h>
    205  1.1  christos #   if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)
    206  1.1  christos #    define OPENSSL_NO_KTLS_RX
    207  1.1  christos #    ifndef PEDANTIC
    208  1.1  christos #     warning "KTLS requires Kernel Headers >= 4.17.0 for receiving"
    209  1.1  christos #     warning "Skipping Compilation of KTLS receive data path"
    210  1.1  christos #    endif
    211  1.1  christos #   endif
    212  1.1  christos #   define OPENSSL_KTLS_AES_GCM_128
    213  1.1  christos #   if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
    214  1.1  christos #    define OPENSSL_KTLS_AES_GCM_256
    215  1.1  christos #    define OPENSSL_KTLS_TLS13
    216  1.1  christos #    if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
    217  1.1  christos #     define OPENSSL_KTLS_AES_CCM_128
    218  1.1  christos #     if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
    219  1.1  christos #      ifndef OPENSSL_NO_CHACHA
    220  1.1  christos #       define OPENSSL_KTLS_CHACHA20_POLY1305
    221  1.1  christos #      endif
    222  1.1  christos #     endif
    223  1.1  christos #    endif
    224  1.1  christos #   endif
    225  1.1  christos 
    226  1.1  christos #   include <sys/sendfile.h>
    227  1.1  christos #   include <netinet/tcp.h>
    228  1.1  christos #   include <linux/socket.h>
    229  1.1  christos #   include <openssl/ssl3.h>
    230  1.1  christos #   include <openssl/tls1.h>
    231  1.1  christos #   include <openssl/evp.h>
    232  1.1  christos 
    233  1.1  christos #   ifndef SOL_TLS
    234  1.1  christos #    define SOL_TLS 282
    235  1.1  christos #   endif
    236  1.1  christos 
    237  1.1  christos #   ifndef TCP_ULP
    238  1.1  christos #    define TCP_ULP 31
    239  1.1  christos #   endif
    240  1.1  christos 
    241  1.1  christos #   ifndef TLS_RX
    242  1.1  christos #    define TLS_RX                  2
    243  1.1  christos #   endif
    244  1.1  christos 
    245  1.1  christos struct tls_crypto_info_all {
    246  1.1  christos     union {
    247  1.1  christos #   ifdef OPENSSL_KTLS_AES_GCM_128
    248  1.1  christos         struct tls12_crypto_info_aes_gcm_128 gcm128;
    249  1.1  christos #   endif
    250  1.1  christos #   ifdef OPENSSL_KTLS_AES_GCM_256
    251  1.1  christos         struct tls12_crypto_info_aes_gcm_256 gcm256;
    252  1.1  christos #   endif
    253  1.1  christos #   ifdef OPENSSL_KTLS_AES_CCM_128
    254  1.1  christos         struct tls12_crypto_info_aes_ccm_128 ccm128;
    255  1.1  christos #   endif
    256  1.1  christos #   ifdef OPENSSL_KTLS_CHACHA20_POLY1305
    257  1.1  christos         struct tls12_crypto_info_chacha20_poly1305 chacha20poly1305;
    258  1.1  christos #   endif
    259  1.1  christos     };
    260  1.1  christos     size_t tls_crypto_info_len;
    261  1.1  christos };
    262  1.1  christos 
    263  1.1  christos typedef struct tls_crypto_info_all ktls_crypto_info_t;
    264  1.1  christos 
    265  1.1  christos /*
    266  1.1  christos  * When successful, this socket option doesn't change the behaviour of the
    267  1.1  christos  * TCP socket, except changing the TCP setsockopt handler to enable the
    268  1.1  christos  * processing of SOL_TLS socket options. All other functionality remains the
    269  1.1  christos  * same.
    270  1.1  christos  */
    271  1.1  christos static ossl_inline int ktls_enable(int fd)
    272  1.1  christos {
    273  1.1  christos     return setsockopt(fd, SOL_TCP, TCP_ULP, "tls", sizeof("tls")) ? 0 : 1;
    274  1.1  christos }
    275  1.1  christos 
    276  1.1  christos /*
    277  1.1  christos  * The TLS_TX socket option changes the send/sendmsg handlers of the TCP socket.
    278  1.1  christos  * If successful, then data sent using this socket will be encrypted and
    279  1.1  christos  * encapsulated in TLS records using the crypto_info provided here.
    280  1.1  christos  * The TLS_RX socket option changes the recv/recvmsg handlers of the TCP socket.
    281  1.1  christos  * If successful, then data received using this socket will be decrypted,
    282  1.1  christos  * authenticated and decapsulated using the crypto_info provided here.
    283  1.1  christos  */
    284  1.1  christos static ossl_inline int ktls_start(int fd, ktls_crypto_info_t *crypto_info,
    285  1.1  christos                                   int is_tx)
    286  1.1  christos {
    287  1.1  christos     return setsockopt(fd, SOL_TLS, is_tx ? TLS_TX : TLS_RX,
    288  1.1  christos                       crypto_info, crypto_info->tls_crypto_info_len) ? 0 : 1;
    289  1.1  christos }
    290  1.1  christos 
    291  1.1  christos /*
    292  1.1  christos  * Send a TLS record using the crypto_info provided in ktls_start and use
    293  1.1  christos  * record_type instead of the default SSL3_RT_APPLICATION_DATA.
    294  1.1  christos  * When the socket is non-blocking, then this call either returns EAGAIN or
    295  1.1  christos  * the entire record is pushed to TCP. It is impossible to send a partial
    296  1.1  christos  * record using this control message.
    297  1.1  christos  */
    298  1.1  christos static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type,
    299  1.1  christos                                               const void *data, size_t length)
    300  1.1  christos {
    301  1.1  christos     struct msghdr msg;
    302  1.1  christos     int cmsg_len = sizeof(record_type);
    303  1.1  christos     struct cmsghdr *cmsg;
    304  1.1  christos     union {
    305  1.1  christos         struct cmsghdr hdr;
    306  1.1  christos         char buf[CMSG_SPACE(sizeof(unsigned char))];
    307  1.1  christos     } cmsgbuf;
    308  1.1  christos     struct iovec msg_iov;       /* Vector of data to send/receive into */
    309  1.1  christos 
    310  1.1  christos     memset(&msg, 0, sizeof(msg));
    311  1.1  christos     msg.msg_control = cmsgbuf.buf;
    312  1.1  christos     msg.msg_controllen = sizeof(cmsgbuf.buf);
    313  1.1  christos     cmsg = CMSG_FIRSTHDR(&msg);
    314  1.1  christos     cmsg->cmsg_level = SOL_TLS;
    315  1.1  christos     cmsg->cmsg_type = TLS_SET_RECORD_TYPE;
    316  1.1  christos     cmsg->cmsg_len = CMSG_LEN(cmsg_len);
    317  1.1  christos     *((unsigned char *)CMSG_DATA(cmsg)) = record_type;
    318  1.1  christos     msg.msg_controllen = cmsg->cmsg_len;
    319  1.1  christos 
    320  1.1  christos     msg_iov.iov_base = (void *)data;
    321  1.1  christos     msg_iov.iov_len = length;
    322  1.1  christos     msg.msg_iov = &msg_iov;
    323  1.1  christos     msg.msg_iovlen = 1;
    324  1.1  christos 
    325  1.1  christos     return sendmsg(fd, &msg, 0);
    326  1.1  christos }
    327  1.1  christos 
    328  1.1  christos /*
    329  1.1  christos  * KTLS enables the sendfile system call to send data from a file over TLS.
    330  1.1  christos  * @flags are ignored on Linux. (placeholder for FreeBSD sendfile)
    331  1.1  christos  * */
    332  1.1  christos static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off, size_t size, int flags)
    333  1.1  christos {
    334  1.1  christos     return sendfile(s, fd, &off, size);
    335  1.1  christos }
    336  1.1  christos 
    337  1.1  christos #   ifdef OPENSSL_NO_KTLS_RX
    338  1.1  christos 
    339  1.1  christos 
    340  1.1  christos static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
    341  1.1  christos {
    342  1.1  christos     return -1;
    343  1.1  christos }
    344  1.1  christos 
    345  1.1  christos #   else /* !defined(OPENSSL_NO_KTLS_RX) */
    346  1.1  christos 
    347  1.1  christos /*
    348  1.1  christos  * Receive a TLS record using the crypto_info provided in ktls_start.
    349  1.1  christos  * The kernel strips the TLS record header, IV and authentication tag,
    350  1.1  christos  * returning only the plaintext data or an error on failure.
    351  1.1  christos  * We add the TLS record header here to satisfy routines in rec_layer_s3.c
    352  1.1  christos  */
    353  1.1  christos static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
    354  1.1  christos {
    355  1.1  christos     struct msghdr msg;
    356  1.1  christos     struct cmsghdr *cmsg;
    357  1.1  christos     union {
    358  1.1  christos         struct cmsghdr hdr;
    359  1.1  christos         char buf[CMSG_SPACE(sizeof(unsigned char))];
    360  1.1  christos     } cmsgbuf;
    361  1.1  christos     struct iovec msg_iov;
    362  1.1  christos     int ret;
    363  1.1  christos     unsigned char *p = data;
    364  1.1  christos     const size_t prepend_length = SSL3_RT_HEADER_LENGTH;
    365  1.1  christos 
    366  1.1  christos     if (length < prepend_length + EVP_GCM_TLS_TAG_LEN) {
    367  1.1  christos         errno = EINVAL;
    368  1.1  christos         return -1;
    369  1.1  christos     }
    370  1.1  christos 
    371  1.1  christos     memset(&msg, 0, sizeof(msg));
    372  1.1  christos     msg.msg_control = cmsgbuf.buf;
    373  1.1  christos     msg.msg_controllen = sizeof(cmsgbuf.buf);
    374  1.1  christos 
    375  1.1  christos     msg_iov.iov_base = p + prepend_length;
    376  1.1  christos     msg_iov.iov_len = length - prepend_length - EVP_GCM_TLS_TAG_LEN;
    377  1.1  christos     msg.msg_iov = &msg_iov;
    378  1.1  christos     msg.msg_iovlen = 1;
    379  1.1  christos 
    380  1.1  christos     ret = recvmsg(fd, &msg, 0);
    381  1.1  christos     if (ret < 0)
    382  1.1  christos         return ret;
    383  1.1  christos 
    384  1.1  christos     if (msg.msg_controllen > 0) {
    385  1.1  christos         cmsg = CMSG_FIRSTHDR(&msg);
    386  1.1  christos         if (cmsg->cmsg_type == TLS_GET_RECORD_TYPE) {
    387  1.1  christos             p[0] = *((unsigned char *)CMSG_DATA(cmsg));
    388  1.1  christos             p[1] = TLS1_2_VERSION_MAJOR;
    389  1.1  christos             p[2] = TLS1_2_VERSION_MINOR;
    390  1.1  christos             /* returned length is limited to msg_iov.iov_len above */
    391  1.1  christos             p[3] = (ret >> 8) & 0xff;
    392  1.1  christos             p[4] = ret & 0xff;
    393  1.1  christos             ret += prepend_length;
    394  1.1  christos         }
    395  1.1  christos     }
    396  1.1  christos 
    397  1.1  christos     return ret;
    398  1.1  christos }
    399  1.1  christos 
    400  1.1  christos #   endif /* OPENSSL_NO_KTLS_RX */
    401  1.1  christos 
    402  1.1  christos #  endif /* OPENSSL_SYS_LINUX */
    403  1.1  christos # endif /* OPENSSL_NO_KTLS */
    404  1.1  christos #endif /* HEADER_INTERNAL_KTLS */
    405