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