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