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