Ensure that the struct msghdr is properly zeroed.
[openssl.git] / include / internal / ktls.h
1 /*
2  * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #ifndef OPENSSL_NO_KTLS
11 # ifndef HEADER_INTERNAL_KTLS
12 #  define HEADER_INTERNAL_KTLS
13
14 #  if defined(OPENSSL_SYS_LINUX)
15 #   include <linux/version.h>
16
17 #   define K_MAJ   4
18 #   define K_MIN1  13
19 #   define K_MIN2  0
20 #   if LINUX_VERSION_CODE < KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2)
21
22 #    ifndef PEDANTIC
23 #     warning "KTLS requires Kernel Headers >= 4.13.0"
24 #     warning "Skipping Compilation of KTLS data path"
25 #    endif
26
27 #    define TLS_TX                  1
28
29 #    define TLS_CIPHER_AES_GCM_128                          51
30 #    define TLS_CIPHER_AES_GCM_128_IV_SIZE                  8
31 #    define TLS_CIPHER_AES_GCM_128_KEY_SIZE                 16
32 #    define TLS_CIPHER_AES_GCM_128_SALT_SIZE                4
33 #    define TLS_CIPHER_AES_GCM_128_TAG_SIZE                 16
34 #    define TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE             8
35
36 #    define TLS_SET_RECORD_TYPE     1
37
38 struct tls_crypto_info {
39     unsigned short version;
40     unsigned short cipher_type;
41 };
42
43 struct tls12_crypto_info_aes_gcm_128 {
44     struct tls_crypto_info info;
45     unsigned char iv[TLS_CIPHER_AES_GCM_128_IV_SIZE];
46     unsigned char key[TLS_CIPHER_AES_GCM_128_KEY_SIZE];
47     unsigned char salt[TLS_CIPHER_AES_GCM_128_SALT_SIZE];
48     unsigned char rec_seq[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE];
49 };
50
51 /* Dummy functions here */
52 static ossl_inline int ktls_enable(int fd)
53 {
54     return 0;
55 }
56
57 static ossl_inline int ktls_start(int fd,
58                                   struct tls12_crypto_info_aes_gcm_128
59                                   *crypto_info, size_t len, int is_tx)
60 {
61     return 0;
62 }
63
64 static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type,
65                                               const void *data, size_t length)
66 {
67     return -1;
68 }
69
70 #   else                        /* KERNEL_VERSION */
71
72 #    include <netinet/tcp.h>
73 #    include <linux/tls.h>
74 #    include <linux/socket.h>
75
76 #    ifndef SOL_TLS
77 #     define SOL_TLS 282
78 #    endif
79
80 #    ifndef TCP_ULP
81 #     define TCP_ULP 31
82 #    endif
83
84 /*
85  * When successful, this socket option doesn't change the behaviour of the
86  * TCP socket, except changing the TCP setsockopt handler to enable the
87  * processing of SOL_TLS socket options. All other functionality remains the
88  * same.
89  */
90 static ossl_inline int ktls_enable(int fd)
91 {
92     return setsockopt(fd, SOL_TCP, TCP_ULP, "tls", sizeof("tls")) ? 0 : 1;
93 }
94
95 /*
96  * The TLS_TX socket option changes the send/sendmsg handlers of the TCP socket.
97  * If successful, then data sent using this socket will be encrypted and
98  * encapsulated in TLS records using the crypto_info provided here.
99  */
100 static ossl_inline int ktls_start(int fd,
101                                   struct tls12_crypto_info_aes_gcm_128
102                                   *crypto_info, size_t len, int is_tx)
103 {
104     if (is_tx)
105         return setsockopt(fd, SOL_TLS, TLS_TX, crypto_info,
106                           sizeof(*crypto_info)) ? 0 : 1;
107     else
108         return 0;
109 }
110
111 /*
112  * Send a TLS record using the crypto_info provided in ktls_start and use
113  * record_type instead of the default SSL3_RT_APPLICATION_DATA.
114  * When the socket is non-blocking, then this call either returns EAGAIN or
115  * the entire record is pushed to TCP. It is impossible to send a partial
116  * record using this control message.
117  */
118 static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type,
119                                               const void *data, size_t length)
120 {
121     struct msghdr msg;
122     int cmsg_len = sizeof(record_type);
123     struct cmsghdr *cmsg;
124     char buf[CMSG_SPACE(cmsg_len)];
125     struct iovec msg_iov;       /* Vector of data to send/receive into */
126
127     memset(&msg, 0, sizeof(msg));
128     msg.msg_control = buf;
129     msg.msg_controllen = sizeof(buf);
130     cmsg = CMSG_FIRSTHDR(&msg);
131     cmsg->cmsg_level = SOL_TLS;
132     cmsg->cmsg_type = TLS_SET_RECORD_TYPE;
133     cmsg->cmsg_len = CMSG_LEN(cmsg_len);
134     *((unsigned char *)CMSG_DATA(cmsg)) = record_type;
135     msg.msg_controllen = cmsg->cmsg_len;
136
137     msg_iov.iov_base = (void *)data;
138     msg_iov.iov_len = length;
139     msg.msg_iov = &msg_iov;
140     msg.msg_iovlen = 1;
141
142     return sendmsg(fd, &msg, 0);
143 }
144
145 #   endif                       /* KERNEL_VERSION */
146 #  endif                        /* OPENSSL_SYS_LINUX */
147 # endif                         /* HEADER_INTERNAL_KTLS */
148 #endif                          /* OPENSSL_NO_KTLS */