aboutsummaryrefslogtreecommitdiffstats
path: root/net/tls/tls_main.c
diff options
context:
space:
mode:
authorDave Watson <davejwatson@fb.com>2017-06-14 14:37:39 -0400
committerDavid S. Miller <davem@davemloft.net>2017-06-15 12:12:40 -0400
commit3c4d7559159bfe1e3b94df3a657b2cda3a34e218 (patch)
tree57a99de1db4ac5bb65ea9cf2ee6e7156d6c64d6d /net/tls/tls_main.c
parente3b5616a347603a521fe3ac46f3194a60900e3a7 (diff)
tls: kernel TLS support
Software implementation of transport layer security, implemented using ULP infrastructure. tcp proto_ops are replaced with tls equivalents of sendmsg and sendpage. Only symmetric crypto is done in the kernel, keys are passed by setsockopt after the handshake is complete. All control messages are supported via CMSG data - the actual symmetric encryption is the same, just the message type needs to be passed separately. For user API, please see Documentation patch. Pieces that can be shared between hw and sw implementation are in tls_main.c Signed-off-by: Boris Pismenny <borisp@mellanox.com> Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com> Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com> Signed-off-by: Dave Watson <davejwatson@fb.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tls/tls_main.c')
-rw-r--r--net/tls/tls_main.c487
1 files changed, 487 insertions, 0 deletions
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
new file mode 100644
index 000000000000..2ebc328bda96
--- /dev/null
+++ b/net/tls/tls_main.c
@@ -0,0 +1,487 @@
1/*
2 * Copyright (c) 2016-2017, Mellanox Technologies. All rights reserved.
3 * Copyright (c) 2016-2017, Dave Watson <davejwatson@fb.com>. All rights reserved.
4 *
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34#include <linux/module.h>
35
36#include <net/tcp.h>
37#include <net/inet_common.h>
38#include <linux/highmem.h>
39#include <linux/netdevice.h>
40#include <linux/sched/signal.h>
41
42#include <net/tls.h>
43
44MODULE_AUTHOR("Mellanox Technologies");
45MODULE_DESCRIPTION("Transport Layer Security Support");
46MODULE_LICENSE("Dual BSD/GPL");
47
48static struct proto tls_base_prot;
49static struct proto tls_sw_prot;
50
51int wait_on_pending_writer(struct sock *sk, long *timeo)
52{
53 int rc = 0;
54 DEFINE_WAIT_FUNC(wait, woken_wake_function);
55
56 add_wait_queue(sk_sleep(sk), &wait);
57 while (1) {
58 if (!*timeo) {
59 rc = -EAGAIN;
60 break;
61 }
62
63 if (signal_pending(current)) {
64 rc = sock_intr_errno(*timeo);
65 break;
66 }
67
68 if (sk_wait_event(sk, timeo, !sk->sk_write_pending, &wait))
69 break;
70 }
71 remove_wait_queue(sk_sleep(sk), &wait);
72 return rc;
73}
74
75int tls_push_sg(struct sock *sk,
76 struct tls_context *ctx,
77 struct scatterlist *sg,
78 u16 first_offset,
79 int flags)
80{
81 int sendpage_flags = flags | MSG_SENDPAGE_NOTLAST;
82 int ret = 0;
83 struct page *p;
84 size_t size;
85 int offset = first_offset;
86
87 size = sg->length - offset;
88 offset += sg->offset;
89
90 while (1) {
91 if (sg_is_last(sg))
92 sendpage_flags = flags;
93
94 /* is sending application-limited? */
95 tcp_rate_check_app_limited(sk);
96 p = sg_page(sg);
97retry:
98 ret = do_tcp_sendpages(sk, p, offset, size, sendpage_flags);
99
100 if (ret != size) {
101 if (ret > 0) {
102 offset += ret;
103 size -= ret;
104 goto retry;
105 }
106
107 offset -= sg->offset;
108 ctx->partially_sent_offset = offset;
109 ctx->partially_sent_record = (void *)sg;
110 return ret;
111 }
112
113 put_page(p);
114 sk_mem_uncharge(sk, sg->length);
115 sg = sg_next(sg);
116 if (!sg)
117 break;
118
119 offset = sg->offset;
120 size = sg->length;
121 }
122
123 clear_bit(TLS_PENDING_CLOSED_RECORD, &ctx->flags);
124
125 return 0;
126}
127
128static int tls_handle_open_record(struct sock *sk, int flags)
129{
130 struct tls_context *ctx = tls_get_ctx(sk);
131
132 if (tls_is_pending_open_record(ctx))
133 return ctx->push_pending_record(sk, flags);
134
135 return 0;
136}
137
138int tls_proccess_cmsg(struct sock *sk, struct msghdr *msg,
139 unsigned char *record_type)
140{
141 struct cmsghdr *cmsg;
142 int rc = -EINVAL;
143
144 for_each_cmsghdr(cmsg, msg) {
145 if (!CMSG_OK(msg, cmsg))
146 return -EINVAL;
147 if (cmsg->cmsg_level != SOL_TLS)
148 continue;
149
150 switch (cmsg->cmsg_type) {
151 case TLS_SET_RECORD_TYPE:
152 if (cmsg->cmsg_len < CMSG_LEN(sizeof(*record_type)))
153 return -EINVAL;
154
155 if (msg->msg_flags & MSG_MORE)
156 return -EINVAL;
157
158 rc = tls_handle_open_record(sk, msg->msg_flags);
159 if (rc)
160 return rc;
161
162 *record_type = *(unsigned char *)CMSG_DATA(cmsg);
163 rc = 0;
164 break;
165 default:
166 return -EINVAL;
167 }
168 }
169
170 return rc;
171}
172
173int tls_push_pending_closed_record(struct sock *sk, struct tls_context *ctx,
174 int flags, long *timeo)
175{
176 struct scatterlist *sg;
177 u16 offset;
178
179 if (!tls_is_partially_sent_record(ctx))
180 return ctx->push_pending_record(sk, flags);
181
182 sg = ctx->partially_sent_record;
183 offset = ctx->partially_sent_offset;
184
185 ctx->partially_sent_record = NULL;
186 return tls_push_sg(sk, ctx, sg, offset, flags);
187}
188
189static void tls_write_space(struct sock *sk)
190{
191 struct tls_context *ctx = tls_get_ctx(sk);
192
193 if (!sk->sk_write_pending && tls_is_pending_closed_record(ctx)) {
194 gfp_t sk_allocation = sk->sk_allocation;
195 int rc;
196 long timeo = 0;
197
198 sk->sk_allocation = GFP_ATOMIC;
199 rc = tls_push_pending_closed_record(sk, ctx,
200 MSG_DONTWAIT |
201 MSG_NOSIGNAL,
202 &timeo);
203 sk->sk_allocation = sk_allocation;
204
205 if (rc < 0)
206 return;
207 }
208
209 ctx->sk_write_space(sk);
210}
211
212static void tls_sk_proto_close(struct sock *sk, long timeout)
213{
214 struct tls_context *ctx = tls_get_ctx(sk);
215 long timeo = sock_sndtimeo(sk, 0);
216 void (*sk_proto_close)(struct sock *sk, long timeout);
217
218 lock_sock(sk);
219
220 if (!tls_complete_pending_work(sk, ctx, 0, &timeo))
221 tls_handle_open_record(sk, 0);
222
223 if (ctx->partially_sent_record) {
224 struct scatterlist *sg = ctx->partially_sent_record;
225
226 while (1) {
227 put_page(sg_page(sg));
228 sk_mem_uncharge(sk, sg->length);
229
230 if (sg_is_last(sg))
231 break;
232 sg++;
233 }
234 }
235 ctx->free_resources(sk);
236 kfree(ctx->rec_seq);
237 kfree(ctx->iv);
238
239 sk_proto_close = ctx->sk_proto_close;
240 kfree(ctx);
241
242 release_sock(sk);
243 sk_proto_close(sk, timeout);
244}
245
246static int do_tls_getsockopt_tx(struct sock *sk, char __user *optval,
247 int __user *optlen)
248{
249 int rc = 0;
250 struct tls_context *ctx = tls_get_ctx(sk);
251 struct tls_crypto_info *crypto_info;
252 int len;
253
254 if (get_user(len, optlen))
255 return -EFAULT;
256
257 if (!optval || (len < sizeof(*crypto_info))) {
258 rc = -EINVAL;
259 goto out;
260 }
261
262 if (!ctx) {
263 rc = -EBUSY;
264 goto out;
265 }
266
267 /* get user crypto info */
268 crypto_info = &ctx->crypto_send;
269
270 if (!TLS_CRYPTO_INFO_READY(crypto_info)) {
271 rc = -EBUSY;
272 goto out;
273 }
274
275 if (len == sizeof(crypto_info)) {
276 rc = copy_to_user(optval, crypto_info, sizeof(*crypto_info));
277 goto out;
278 }
279
280 switch (crypto_info->cipher_type) {
281 case TLS_CIPHER_AES_GCM_128: {
282 struct tls12_crypto_info_aes_gcm_128 *
283 crypto_info_aes_gcm_128 =
284 container_of(crypto_info,
285 struct tls12_crypto_info_aes_gcm_128,
286 info);
287
288 if (len != sizeof(*crypto_info_aes_gcm_128)) {
289 rc = -EINVAL;
290 goto out;
291 }
292 lock_sock(sk);
293 memcpy(crypto_info_aes_gcm_128->iv, ctx->iv,
294 TLS_CIPHER_AES_GCM_128_IV_SIZE);
295 release_sock(sk);
296 rc = copy_to_user(optval,
297 crypto_info_aes_gcm_128,
298 sizeof(*crypto_info_aes_gcm_128));
299 break;
300 }
301 default:
302 rc = -EINVAL;
303 }
304
305out:
306 return rc;
307}
308
309static int do_tls_getsockopt(struct sock *sk, int optname,
310 char __user *optval, int __user *optlen)
311{
312 int rc = 0;
313
314 switch (optname) {
315 case TLS_TX:
316 rc = do_tls_getsockopt_tx(sk, optval, optlen);
317 break;
318 default:
319 rc = -ENOPROTOOPT;
320 break;
321 }
322 return rc;
323}
324
325static int tls_getsockopt(struct sock *sk, int level, int optname,
326 char __user *optval, int __user *optlen)
327{
328 struct tls_context *ctx = tls_get_ctx(sk);
329
330 if (level != SOL_TLS)
331 return ctx->getsockopt(sk, level, optname, optval, optlen);
332
333 return do_tls_getsockopt(sk, optname, optval, optlen);
334}
335
336static int do_tls_setsockopt_tx(struct sock *sk, char __user *optval,
337 unsigned int optlen)
338{
339 struct tls_crypto_info *crypto_info, tmp_crypto_info;
340 struct tls_context *ctx = tls_get_ctx(sk);
341 struct proto *prot = NULL;
342 int rc = 0;
343
344 if (!optval || (optlen < sizeof(*crypto_info))) {
345 rc = -EINVAL;
346 goto out;
347 }
348
349 rc = copy_from_user(&tmp_crypto_info, optval, sizeof(*crypto_info));
350 if (rc) {
351 rc = -EFAULT;
352 goto out;
353 }
354
355 /* check version */
356 if (tmp_crypto_info.version != TLS_1_2_VERSION) {
357 rc = -ENOTSUPP;
358 goto out;
359 }
360
361 /* get user crypto info */
362 crypto_info = &ctx->crypto_send;
363
364 /* Currently we don't support set crypto info more than one time */
365 if (TLS_CRYPTO_INFO_READY(crypto_info))
366 goto out;
367
368 switch (tmp_crypto_info.cipher_type) {
369 case TLS_CIPHER_AES_GCM_128: {
370 if (optlen != sizeof(struct tls12_crypto_info_aes_gcm_128)) {
371 rc = -EINVAL;
372 goto out;
373 }
374 rc = copy_from_user(
375 crypto_info,
376 optval,
377 sizeof(struct tls12_crypto_info_aes_gcm_128));
378
379 if (rc) {
380 rc = -EFAULT;
381 goto err_crypto_info;
382 }
383 break;
384 }
385 default:
386 rc = -EINVAL;
387 goto out;
388 }
389
390 ctx->sk_write_space = sk->sk_write_space;
391 sk->sk_write_space = tls_write_space;
392
393 ctx->sk_proto_close = sk->sk_prot->close;
394
395 /* currently SW is default, we will have ethtool in future */
396 rc = tls_set_sw_offload(sk, ctx);
397 prot = &tls_sw_prot;
398 if (rc)
399 goto err_crypto_info;
400
401 sk->sk_prot = prot;
402 goto out;
403
404err_crypto_info:
405 memset(crypto_info, 0, sizeof(*crypto_info));
406out:
407 return rc;
408}
409
410static int do_tls_setsockopt(struct sock *sk, int optname,
411 char __user *optval, unsigned int optlen)
412{
413 int rc = 0;
414
415 switch (optname) {
416 case TLS_TX:
417 lock_sock(sk);
418 rc = do_tls_setsockopt_tx(sk, optval, optlen);
419 release_sock(sk);
420 break;
421 default:
422 rc = -ENOPROTOOPT;
423 break;
424 }
425 return rc;
426}
427
428static int tls_setsockopt(struct sock *sk, int level, int optname,
429 char __user *optval, unsigned int optlen)
430{
431 struct tls_context *ctx = tls_get_ctx(sk);
432
433 if (level != SOL_TLS)
434 return ctx->setsockopt(sk, level, optname, optval, optlen);
435
436 return do_tls_setsockopt(sk, optname, optval, optlen);
437}
438
439static int tls_init(struct sock *sk)
440{
441 struct inet_connection_sock *icsk = inet_csk(sk);
442 struct tls_context *ctx;
443 int rc = 0;
444
445 /* allocate tls context */
446 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
447 if (!ctx) {
448 rc = -ENOMEM;
449 goto out;
450 }
451 icsk->icsk_ulp_data = ctx;
452 ctx->setsockopt = sk->sk_prot->setsockopt;
453 ctx->getsockopt = sk->sk_prot->getsockopt;
454 sk->sk_prot = &tls_base_prot;
455out:
456 return rc;
457}
458
459static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {
460 .name = "tls",
461 .owner = THIS_MODULE,
462 .init = tls_init,
463};
464
465static int __init tls_register(void)
466{
467 tls_base_prot = tcp_prot;
468 tls_base_prot.setsockopt = tls_setsockopt;
469 tls_base_prot.getsockopt = tls_getsockopt;
470
471 tls_sw_prot = tls_base_prot;
472 tls_sw_prot.sendmsg = tls_sw_sendmsg;
473 tls_sw_prot.sendpage = tls_sw_sendpage;
474 tls_sw_prot.close = tls_sk_proto_close;
475
476 tcp_register_ulp(&tcp_tls_ulp_ops);
477
478 return 0;
479}
480
481static void __exit tls_unregister(void)
482{
483 tcp_unregister_ulp(&tcp_tls_ulp_ops);
484}
485
486module_init(tls_register);
487module_exit(tls_unregister);