diff options
-rw-r--r-- | include/net/tls.h | 32 | ||||
-rw-r--r-- | net/tls/tls_main.c | 114 |
2 files changed, 142 insertions, 4 deletions
diff --git a/include/net/tls.h b/include/net/tls.h index 437a746300bf..3da8e13a6d96 100644 --- a/include/net/tls.h +++ b/include/net/tls.h | |||
@@ -56,6 +56,32 @@ | |||
56 | #define TLS_RECORD_TYPE_DATA 0x17 | 56 | #define TLS_RECORD_TYPE_DATA 0x17 |
57 | 57 | ||
58 | #define TLS_AAD_SPACE_SIZE 13 | 58 | #define TLS_AAD_SPACE_SIZE 13 |
59 | #define TLS_DEVICE_NAME_MAX 32 | ||
60 | |||
61 | /* | ||
62 | * This structure defines the routines for Inline TLS driver. | ||
63 | * The following routines are optional and filled with a | ||
64 | * null pointer if not defined. | ||
65 | * | ||
66 | * @name: Its the name of registered Inline tls device | ||
67 | * @dev_list: Inline tls device list | ||
68 | * int (*feature)(struct tls_device *device); | ||
69 | * Called to return Inline TLS driver capability | ||
70 | * | ||
71 | * int (*hash)(struct tls_device *device, struct sock *sk); | ||
72 | * This function sets Inline driver for listen and program | ||
73 | * device specific functioanlity as required | ||
74 | * | ||
75 | * void (*unhash)(struct tls_device *device, struct sock *sk); | ||
76 | * This function cleans listen state set by Inline TLS driver | ||
77 | */ | ||
78 | struct tls_device { | ||
79 | char name[TLS_DEVICE_NAME_MAX]; | ||
80 | struct list_head dev_list; | ||
81 | int (*feature)(struct tls_device *device); | ||
82 | int (*hash)(struct tls_device *device, struct sock *sk); | ||
83 | void (*unhash)(struct tls_device *device, struct sock *sk); | ||
84 | }; | ||
59 | 85 | ||
60 | struct tls_sw_context { | 86 | struct tls_sw_context { |
61 | struct crypto_aead *aead_send; | 87 | struct crypto_aead *aead_send; |
@@ -114,7 +140,7 @@ struct tls_context { | |||
114 | 140 | ||
115 | void *priv_ctx; | 141 | void *priv_ctx; |
116 | 142 | ||
117 | u8 conf:2; | 143 | u8 conf:3; |
118 | 144 | ||
119 | struct cipher_context tx; | 145 | struct cipher_context tx; |
120 | struct cipher_context rx; | 146 | struct cipher_context rx; |
@@ -135,6 +161,8 @@ struct tls_context { | |||
135 | int (*getsockopt)(struct sock *sk, int level, | 161 | int (*getsockopt)(struct sock *sk, int level, |
136 | int optname, char __user *optval, | 162 | int optname, char __user *optval, |
137 | int __user *optlen); | 163 | int __user *optlen); |
164 | int (*hash)(struct sock *sk); | ||
165 | void (*unhash)(struct sock *sk); | ||
138 | }; | 166 | }; |
139 | 167 | ||
140 | int wait_on_pending_writer(struct sock *sk, long *timeo); | 168 | int wait_on_pending_writer(struct sock *sk, long *timeo); |
@@ -283,5 +311,7 @@ static inline struct tls_offload_context *tls_offload_ctx( | |||
283 | 311 | ||
284 | int tls_proccess_cmsg(struct sock *sk, struct msghdr *msg, | 312 | int tls_proccess_cmsg(struct sock *sk, struct msghdr *msg, |
285 | unsigned char *record_type); | 313 | unsigned char *record_type); |
314 | void tls_register_device(struct tls_device *device); | ||
315 | void tls_unregister_device(struct tls_device *device); | ||
286 | 316 | ||
287 | #endif /* _TLS_OFFLOAD_H */ | 317 | #endif /* _TLS_OFFLOAD_H */ |
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 6f5c1146da4a..0d379970960e 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/highmem.h> | 38 | #include <linux/highmem.h> |
39 | #include <linux/netdevice.h> | 39 | #include <linux/netdevice.h> |
40 | #include <linux/sched/signal.h> | 40 | #include <linux/sched/signal.h> |
41 | #include <linux/inetdevice.h> | ||
41 | 42 | ||
42 | #include <net/tls.h> | 43 | #include <net/tls.h> |
43 | 44 | ||
@@ -56,11 +57,14 @@ enum { | |||
56 | TLS_SW_TX, | 57 | TLS_SW_TX, |
57 | TLS_SW_RX, | 58 | TLS_SW_RX, |
58 | TLS_SW_RXTX, | 59 | TLS_SW_RXTX, |
60 | TLS_HW_RECORD, | ||
59 | TLS_NUM_CONFIG, | 61 | TLS_NUM_CONFIG, |
60 | }; | 62 | }; |
61 | 63 | ||
62 | static struct proto *saved_tcpv6_prot; | 64 | static struct proto *saved_tcpv6_prot; |
63 | static DEFINE_MUTEX(tcpv6_prot_mutex); | 65 | static DEFINE_MUTEX(tcpv6_prot_mutex); |
66 | static LIST_HEAD(device_list); | ||
67 | static DEFINE_MUTEX(device_mutex); | ||
64 | static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG]; | 68 | static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG]; |
65 | static struct proto_ops tls_sw_proto_ops; | 69 | static struct proto_ops tls_sw_proto_ops; |
66 | 70 | ||
@@ -241,8 +245,12 @@ static void tls_sk_proto_close(struct sock *sk, long timeout) | |||
241 | lock_sock(sk); | 245 | lock_sock(sk); |
242 | sk_proto_close = ctx->sk_proto_close; | 246 | sk_proto_close = ctx->sk_proto_close; |
243 | 247 | ||
248 | if (ctx->conf == TLS_HW_RECORD) | ||
249 | goto skip_tx_cleanup; | ||
250 | |||
244 | if (ctx->conf == TLS_BASE) { | 251 | if (ctx->conf == TLS_BASE) { |
245 | kfree(ctx); | 252 | kfree(ctx); |
253 | ctx = NULL; | ||
246 | goto skip_tx_cleanup; | 254 | goto skip_tx_cleanup; |
247 | } | 255 | } |
248 | 256 | ||
@@ -276,6 +284,11 @@ static void tls_sk_proto_close(struct sock *sk, long timeout) | |||
276 | skip_tx_cleanup: | 284 | skip_tx_cleanup: |
277 | release_sock(sk); | 285 | release_sock(sk); |
278 | sk_proto_close(sk, timeout); | 286 | sk_proto_close(sk, timeout); |
287 | /* free ctx for TLS_HW_RECORD, used by tcp_set_state | ||
288 | * for sk->sk_prot->unhash [tls_hw_unhash] | ||
289 | */ | ||
290 | if (ctx && ctx->conf == TLS_HW_RECORD) | ||
291 | kfree(ctx); | ||
279 | } | 292 | } |
280 | 293 | ||
281 | static int do_tls_getsockopt_tx(struct sock *sk, char __user *optval, | 294 | static int do_tls_getsockopt_tx(struct sock *sk, char __user *optval, |
@@ -493,6 +506,79 @@ static int tls_setsockopt(struct sock *sk, int level, int optname, | |||
493 | return do_tls_setsockopt(sk, optname, optval, optlen); | 506 | return do_tls_setsockopt(sk, optname, optval, optlen); |
494 | } | 507 | } |
495 | 508 | ||
509 | static struct tls_context *create_ctx(struct sock *sk) | ||
510 | { | ||
511 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
512 | struct tls_context *ctx; | ||
513 | |||
514 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | ||
515 | if (!ctx) | ||
516 | return NULL; | ||
517 | |||
518 | icsk->icsk_ulp_data = ctx; | ||
519 | return ctx; | ||
520 | } | ||
521 | |||
522 | static int tls_hw_prot(struct sock *sk) | ||
523 | { | ||
524 | struct tls_context *ctx; | ||
525 | struct tls_device *dev; | ||
526 | int rc = 0; | ||
527 | |||
528 | mutex_lock(&device_mutex); | ||
529 | list_for_each_entry(dev, &device_list, dev_list) { | ||
530 | if (dev->feature && dev->feature(dev)) { | ||
531 | ctx = create_ctx(sk); | ||
532 | if (!ctx) | ||
533 | goto out; | ||
534 | |||
535 | ctx->hash = sk->sk_prot->hash; | ||
536 | ctx->unhash = sk->sk_prot->unhash; | ||
537 | ctx->sk_proto_close = sk->sk_prot->close; | ||
538 | ctx->conf = TLS_HW_RECORD; | ||
539 | update_sk_prot(sk, ctx); | ||
540 | rc = 1; | ||
541 | break; | ||
542 | } | ||
543 | } | ||
544 | out: | ||
545 | mutex_unlock(&device_mutex); | ||
546 | return rc; | ||
547 | } | ||
548 | |||
549 | static void tls_hw_unhash(struct sock *sk) | ||
550 | { | ||
551 | struct tls_context *ctx = tls_get_ctx(sk); | ||
552 | struct tls_device *dev; | ||
553 | |||
554 | mutex_lock(&device_mutex); | ||
555 | list_for_each_entry(dev, &device_list, dev_list) { | ||
556 | if (dev->unhash) | ||
557 | dev->unhash(dev, sk); | ||
558 | } | ||
559 | mutex_unlock(&device_mutex); | ||
560 | ctx->unhash(sk); | ||
561 | } | ||
562 | |||
563 | static int tls_hw_hash(struct sock *sk) | ||
564 | { | ||
565 | struct tls_context *ctx = tls_get_ctx(sk); | ||
566 | struct tls_device *dev; | ||
567 | int err; | ||
568 | |||
569 | err = ctx->hash(sk); | ||
570 | mutex_lock(&device_mutex); | ||
571 | list_for_each_entry(dev, &device_list, dev_list) { | ||
572 | if (dev->hash) | ||
573 | err |= dev->hash(dev, sk); | ||
574 | } | ||
575 | mutex_unlock(&device_mutex); | ||
576 | |||
577 | if (err) | ||
578 | tls_hw_unhash(sk); | ||
579 | return err; | ||
580 | } | ||
581 | |||
496 | static void build_protos(struct proto *prot, struct proto *base) | 582 | static void build_protos(struct proto *prot, struct proto *base) |
497 | { | 583 | { |
498 | prot[TLS_BASE] = *base; | 584 | prot[TLS_BASE] = *base; |
@@ -511,15 +597,22 @@ static void build_protos(struct proto *prot, struct proto *base) | |||
511 | prot[TLS_SW_RXTX] = prot[TLS_SW_TX]; | 597 | prot[TLS_SW_RXTX] = prot[TLS_SW_TX]; |
512 | prot[TLS_SW_RXTX].recvmsg = tls_sw_recvmsg; | 598 | prot[TLS_SW_RXTX].recvmsg = tls_sw_recvmsg; |
513 | prot[TLS_SW_RXTX].close = tls_sk_proto_close; | 599 | prot[TLS_SW_RXTX].close = tls_sk_proto_close; |
600 | |||
601 | prot[TLS_HW_RECORD] = *base; | ||
602 | prot[TLS_HW_RECORD].hash = tls_hw_hash; | ||
603 | prot[TLS_HW_RECORD].unhash = tls_hw_unhash; | ||
604 | prot[TLS_HW_RECORD].close = tls_sk_proto_close; | ||
514 | } | 605 | } |
515 | 606 | ||
516 | static int tls_init(struct sock *sk) | 607 | static int tls_init(struct sock *sk) |
517 | { | 608 | { |
518 | int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4; | 609 | int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4; |
519 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
520 | struct tls_context *ctx; | 610 | struct tls_context *ctx; |
521 | int rc = 0; | 611 | int rc = 0; |
522 | 612 | ||
613 | if (tls_hw_prot(sk)) | ||
614 | goto out; | ||
615 | |||
523 | /* The TLS ulp is currently supported only for TCP sockets | 616 | /* The TLS ulp is currently supported only for TCP sockets |
524 | * in ESTABLISHED state. | 617 | * in ESTABLISHED state. |
525 | * Supporting sockets in LISTEN state will require us | 618 | * Supporting sockets in LISTEN state will require us |
@@ -530,12 +623,11 @@ static int tls_init(struct sock *sk) | |||
530 | return -ENOTSUPP; | 623 | return -ENOTSUPP; |
531 | 624 | ||
532 | /* allocate tls context */ | 625 | /* allocate tls context */ |
533 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | 626 | ctx = create_ctx(sk); |
534 | if (!ctx) { | 627 | if (!ctx) { |
535 | rc = -ENOMEM; | 628 | rc = -ENOMEM; |
536 | goto out; | 629 | goto out; |
537 | } | 630 | } |
538 | icsk->icsk_ulp_data = ctx; | ||
539 | ctx->setsockopt = sk->sk_prot->setsockopt; | 631 | ctx->setsockopt = sk->sk_prot->setsockopt; |
540 | ctx->getsockopt = sk->sk_prot->getsockopt; | 632 | ctx->getsockopt = sk->sk_prot->getsockopt; |
541 | ctx->sk_proto_close = sk->sk_prot->close; | 633 | ctx->sk_proto_close = sk->sk_prot->close; |
@@ -557,6 +649,22 @@ out: | |||
557 | return rc; | 649 | return rc; |
558 | } | 650 | } |
559 | 651 | ||
652 | void tls_register_device(struct tls_device *device) | ||
653 | { | ||
654 | mutex_lock(&device_mutex); | ||
655 | list_add_tail(&device->dev_list, &device_list); | ||
656 | mutex_unlock(&device_mutex); | ||
657 | } | ||
658 | EXPORT_SYMBOL(tls_register_device); | ||
659 | |||
660 | void tls_unregister_device(struct tls_device *device) | ||
661 | { | ||
662 | mutex_lock(&device_mutex); | ||
663 | list_del(&device->dev_list); | ||
664 | mutex_unlock(&device_mutex); | ||
665 | } | ||
666 | EXPORT_SYMBOL(tls_unregister_device); | ||
667 | |||
560 | static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = { | 668 | static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = { |
561 | .name = "tls", | 669 | .name = "tls", |
562 | .uid = TCP_ULP_TLS, | 670 | .uid = TCP_ULP_TLS, |