diff options
Diffstat (limited to 'net/tls/tls_main.c')
-rw-r--r-- | net/tls/tls_main.c | 99 |
1 files changed, 62 insertions, 37 deletions
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 4674e57e66b0..43252a801c3f 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c | |||
@@ -261,24 +261,9 @@ void tls_ctx_free(struct tls_context *ctx) | |||
261 | kfree(ctx); | 261 | kfree(ctx); |
262 | } | 262 | } |
263 | 263 | ||
264 | static void tls_sk_proto_close(struct sock *sk, long timeout) | 264 | static void tls_sk_proto_cleanup(struct sock *sk, |
265 | struct tls_context *ctx, long timeo) | ||
265 | { | 266 | { |
266 | struct tls_context *ctx = tls_get_ctx(sk); | ||
267 | long timeo = sock_sndtimeo(sk, 0); | ||
268 | void (*sk_proto_close)(struct sock *sk, long timeout); | ||
269 | bool free_ctx = false; | ||
270 | |||
271 | lock_sock(sk); | ||
272 | sk_proto_close = ctx->sk_proto_close; | ||
273 | |||
274 | if (ctx->tx_conf == TLS_HW_RECORD && ctx->rx_conf == TLS_HW_RECORD) | ||
275 | goto skip_tx_cleanup; | ||
276 | |||
277 | if (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE) { | ||
278 | free_ctx = true; | ||
279 | goto skip_tx_cleanup; | ||
280 | } | ||
281 | |||
282 | if (unlikely(sk->sk_write_pending) && | 267 | if (unlikely(sk->sk_write_pending) && |
283 | !wait_on_pending_writer(sk, &timeo)) | 268 | !wait_on_pending_writer(sk, &timeo)) |
284 | tls_handle_open_record(sk, 0); | 269 | tls_handle_open_record(sk, 0); |
@@ -287,7 +272,7 @@ static void tls_sk_proto_close(struct sock *sk, long timeout) | |||
287 | if (ctx->tx_conf == TLS_SW) { | 272 | if (ctx->tx_conf == TLS_SW) { |
288 | kfree(ctx->tx.rec_seq); | 273 | kfree(ctx->tx.rec_seq); |
289 | kfree(ctx->tx.iv); | 274 | kfree(ctx->tx.iv); |
290 | tls_sw_free_resources_tx(sk); | 275 | tls_sw_release_resources_tx(sk); |
291 | #ifdef CONFIG_TLS_DEVICE | 276 | #ifdef CONFIG_TLS_DEVICE |
292 | } else if (ctx->tx_conf == TLS_HW) { | 277 | } else if (ctx->tx_conf == TLS_HW) { |
293 | tls_device_free_resources_tx(sk); | 278 | tls_device_free_resources_tx(sk); |
@@ -295,26 +280,46 @@ static void tls_sk_proto_close(struct sock *sk, long timeout) | |||
295 | } | 280 | } |
296 | 281 | ||
297 | if (ctx->rx_conf == TLS_SW) | 282 | if (ctx->rx_conf == TLS_SW) |
298 | tls_sw_free_resources_rx(sk); | 283 | tls_sw_release_resources_rx(sk); |
299 | 284 | ||
300 | #ifdef CONFIG_TLS_DEVICE | 285 | #ifdef CONFIG_TLS_DEVICE |
301 | if (ctx->rx_conf == TLS_HW) | 286 | if (ctx->rx_conf == TLS_HW) |
302 | tls_device_offload_cleanup_rx(sk); | 287 | tls_device_offload_cleanup_rx(sk); |
303 | |||
304 | if (ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW) { | ||
305 | #else | ||
306 | { | ||
307 | #endif | 288 | #endif |
308 | tls_ctx_free(ctx); | 289 | } |
309 | ctx = NULL; | ||
310 | } | ||
311 | 290 | ||
312 | skip_tx_cleanup: | 291 | static void tls_sk_proto_close(struct sock *sk, long timeout) |
292 | { | ||
293 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
294 | struct tls_context *ctx = tls_get_ctx(sk); | ||
295 | long timeo = sock_sndtimeo(sk, 0); | ||
296 | bool free_ctx; | ||
297 | |||
298 | if (ctx->tx_conf == TLS_SW) | ||
299 | tls_sw_cancel_work_tx(ctx); | ||
300 | |||
301 | lock_sock(sk); | ||
302 | free_ctx = ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW; | ||
303 | |||
304 | if (ctx->tx_conf != TLS_BASE || ctx->rx_conf != TLS_BASE) | ||
305 | tls_sk_proto_cleanup(sk, ctx, timeo); | ||
306 | |||
307 | write_lock_bh(&sk->sk_callback_lock); | ||
308 | if (free_ctx) | ||
309 | icsk->icsk_ulp_data = NULL; | ||
310 | sk->sk_prot = ctx->sk_proto; | ||
311 | if (sk->sk_write_space == tls_write_space) | ||
312 | sk->sk_write_space = ctx->sk_write_space; | ||
313 | write_unlock_bh(&sk->sk_callback_lock); | ||
313 | release_sock(sk); | 314 | release_sock(sk); |
314 | sk_proto_close(sk, timeout); | 315 | if (ctx->tx_conf == TLS_SW) |
315 | /* free ctx for TLS_HW_RECORD, used by tcp_set_state | 316 | tls_sw_free_ctx_tx(ctx); |
316 | * for sk->sk_prot->unhash [tls_hw_unhash] | 317 | if (ctx->rx_conf == TLS_SW || ctx->rx_conf == TLS_HW) |
317 | */ | 318 | tls_sw_strparser_done(ctx); |
319 | if (ctx->rx_conf == TLS_SW) | ||
320 | tls_sw_free_ctx_rx(ctx); | ||
321 | ctx->sk_proto_close(sk, timeout); | ||
322 | |||
318 | if (free_ctx) | 323 | if (free_ctx) |
319 | tls_ctx_free(ctx); | 324 | tls_ctx_free(ctx); |
320 | } | 325 | } |
@@ -526,6 +531,8 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | |||
526 | { | 531 | { |
527 | #endif | 532 | #endif |
528 | rc = tls_set_sw_offload(sk, ctx, 1); | 533 | rc = tls_set_sw_offload(sk, ctx, 1); |
534 | if (rc) | ||
535 | goto err_crypto_info; | ||
529 | conf = TLS_SW; | 536 | conf = TLS_SW; |
530 | } | 537 | } |
531 | } else { | 538 | } else { |
@@ -537,13 +544,13 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | |||
537 | { | 544 | { |
538 | #endif | 545 | #endif |
539 | rc = tls_set_sw_offload(sk, ctx, 0); | 546 | rc = tls_set_sw_offload(sk, ctx, 0); |
547 | if (rc) | ||
548 | goto err_crypto_info; | ||
540 | conf = TLS_SW; | 549 | conf = TLS_SW; |
541 | } | 550 | } |
551 | tls_sw_strparser_arm(sk, ctx); | ||
542 | } | 552 | } |
543 | 553 | ||
544 | if (rc) | ||
545 | goto err_crypto_info; | ||
546 | |||
547 | if (tx) | 554 | if (tx) |
548 | ctx->tx_conf = conf; | 555 | ctx->tx_conf = conf; |
549 | else | 556 | else |
@@ -607,6 +614,7 @@ static struct tls_context *create_ctx(struct sock *sk) | |||
607 | ctx->setsockopt = sk->sk_prot->setsockopt; | 614 | ctx->setsockopt = sk->sk_prot->setsockopt; |
608 | ctx->getsockopt = sk->sk_prot->getsockopt; | 615 | ctx->getsockopt = sk->sk_prot->getsockopt; |
609 | ctx->sk_proto_close = sk->sk_prot->close; | 616 | ctx->sk_proto_close = sk->sk_prot->close; |
617 | ctx->unhash = sk->sk_prot->unhash; | ||
610 | return ctx; | 618 | return ctx; |
611 | } | 619 | } |
612 | 620 | ||
@@ -764,7 +772,6 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG], | |||
764 | prot[TLS_HW_RECORD][TLS_HW_RECORD] = *base; | 772 | prot[TLS_HW_RECORD][TLS_HW_RECORD] = *base; |
765 | prot[TLS_HW_RECORD][TLS_HW_RECORD].hash = tls_hw_hash; | 773 | prot[TLS_HW_RECORD][TLS_HW_RECORD].hash = tls_hw_hash; |
766 | prot[TLS_HW_RECORD][TLS_HW_RECORD].unhash = tls_hw_unhash; | 774 | prot[TLS_HW_RECORD][TLS_HW_RECORD].unhash = tls_hw_unhash; |
767 | prot[TLS_HW_RECORD][TLS_HW_RECORD].close = tls_sk_proto_close; | ||
768 | } | 775 | } |
769 | 776 | ||
770 | static int tls_init(struct sock *sk) | 777 | static int tls_init(struct sock *sk) |
@@ -773,7 +780,7 @@ static int tls_init(struct sock *sk) | |||
773 | int rc = 0; | 780 | int rc = 0; |
774 | 781 | ||
775 | if (tls_hw_prot(sk)) | 782 | if (tls_hw_prot(sk)) |
776 | goto out; | 783 | return 0; |
777 | 784 | ||
778 | /* The TLS ulp is currently supported only for TCP sockets | 785 | /* The TLS ulp is currently supported only for TCP sockets |
779 | * in ESTABLISHED state. | 786 | * in ESTABLISHED state. |
@@ -784,21 +791,38 @@ static int tls_init(struct sock *sk) | |||
784 | if (sk->sk_state != TCP_ESTABLISHED) | 791 | if (sk->sk_state != TCP_ESTABLISHED) |
785 | return -ENOTSUPP; | 792 | return -ENOTSUPP; |
786 | 793 | ||
794 | tls_build_proto(sk); | ||
795 | |||
787 | /* allocate tls context */ | 796 | /* allocate tls context */ |
797 | write_lock_bh(&sk->sk_callback_lock); | ||
788 | ctx = create_ctx(sk); | 798 | ctx = create_ctx(sk); |
789 | if (!ctx) { | 799 | if (!ctx) { |
790 | rc = -ENOMEM; | 800 | rc = -ENOMEM; |
791 | goto out; | 801 | goto out; |
792 | } | 802 | } |
793 | 803 | ||
794 | tls_build_proto(sk); | ||
795 | ctx->tx_conf = TLS_BASE; | 804 | ctx->tx_conf = TLS_BASE; |
796 | ctx->rx_conf = TLS_BASE; | 805 | ctx->rx_conf = TLS_BASE; |
806 | ctx->sk_proto = sk->sk_prot; | ||
797 | update_sk_prot(sk, ctx); | 807 | update_sk_prot(sk, ctx); |
798 | out: | 808 | out: |
809 | write_unlock_bh(&sk->sk_callback_lock); | ||
799 | return rc; | 810 | return rc; |
800 | } | 811 | } |
801 | 812 | ||
813 | static void tls_update(struct sock *sk, struct proto *p) | ||
814 | { | ||
815 | struct tls_context *ctx; | ||
816 | |||
817 | ctx = tls_get_ctx(sk); | ||
818 | if (likely(ctx)) { | ||
819 | ctx->sk_proto_close = p->close; | ||
820 | ctx->sk_proto = p; | ||
821 | } else { | ||
822 | sk->sk_prot = p; | ||
823 | } | ||
824 | } | ||
825 | |||
802 | void tls_register_device(struct tls_device *device) | 826 | void tls_register_device(struct tls_device *device) |
803 | { | 827 | { |
804 | spin_lock_bh(&device_spinlock); | 828 | spin_lock_bh(&device_spinlock); |
@@ -819,6 +843,7 @@ static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = { | |||
819 | .name = "tls", | 843 | .name = "tls", |
820 | .owner = THIS_MODULE, | 844 | .owner = THIS_MODULE, |
821 | .init = tls_init, | 845 | .init = tls_init, |
846 | .update = tls_update, | ||
822 | }; | 847 | }; |
823 | 848 | ||
824 | static int __init tls_register(void) | 849 | static int __init tls_register(void) |