diff options
Diffstat (limited to 'net/tls/tls_main.c')
-rw-r--r-- | net/tls/tls_main.c | 153 |
1 files changed, 103 insertions, 50 deletions
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 78cb4a584080..df921a2904b9 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c | |||
@@ -61,6 +61,8 @@ static LIST_HEAD(device_list); | |||
61 | static DEFINE_SPINLOCK(device_spinlock); | 61 | static DEFINE_SPINLOCK(device_spinlock); |
62 | static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG][TLS_NUM_CONFIG]; | 62 | static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG][TLS_NUM_CONFIG]; |
63 | static struct proto_ops tls_sw_proto_ops; | 63 | static struct proto_ops tls_sw_proto_ops; |
64 | static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG], | ||
65 | struct proto *base); | ||
64 | 66 | ||
65 | static void update_sk_prot(struct sock *sk, struct tls_context *ctx) | 67 | static void update_sk_prot(struct sock *sk, struct tls_context *ctx) |
66 | { | 68 | { |
@@ -144,7 +146,6 @@ retry: | |||
144 | } | 146 | } |
145 | 147 | ||
146 | ctx->in_tcp_sendpages = false; | 148 | ctx->in_tcp_sendpages = false; |
147 | ctx->sk_write_space(sk); | ||
148 | 149 | ||
149 | return 0; | 150 | return 0; |
150 | } | 151 | } |
@@ -207,23 +208,9 @@ int tls_push_partial_record(struct sock *sk, struct tls_context *ctx, | |||
207 | return tls_push_sg(sk, ctx, sg, offset, flags); | 208 | return tls_push_sg(sk, ctx, sg, offset, flags); |
208 | } | 209 | } |
209 | 210 | ||
210 | int tls_push_pending_closed_record(struct sock *sk, | ||
211 | struct tls_context *tls_ctx, | ||
212 | int flags, long *timeo) | ||
213 | { | ||
214 | struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); | ||
215 | |||
216 | if (tls_is_partially_sent_record(tls_ctx) || | ||
217 | !list_empty(&ctx->tx_list)) | ||
218 | return tls_tx_records(sk, flags); | ||
219 | else | ||
220 | return tls_ctx->push_pending_record(sk, flags); | ||
221 | } | ||
222 | |||
223 | static void tls_write_space(struct sock *sk) | 211 | static void tls_write_space(struct sock *sk) |
224 | { | 212 | { |
225 | struct tls_context *ctx = tls_get_ctx(sk); | 213 | struct tls_context *ctx = tls_get_ctx(sk); |
226 | struct tls_sw_context_tx *tx_ctx = tls_sw_ctx_tx(ctx); | ||
227 | 214 | ||
228 | /* If in_tcp_sendpages call lower protocol write space handler | 215 | /* If in_tcp_sendpages call lower protocol write space handler |
229 | * to ensure we wake up any waiting operations there. For example | 216 | * to ensure we wake up any waiting operations there. For example |
@@ -234,12 +221,12 @@ static void tls_write_space(struct sock *sk) | |||
234 | return; | 221 | return; |
235 | } | 222 | } |
236 | 223 | ||
237 | /* Schedule the transmission if tx list is ready */ | 224 | #ifdef CONFIG_TLS_DEVICE |
238 | if (is_tx_ready(tx_ctx) && !sk->sk_write_pending) { | 225 | if (ctx->tx_conf == TLS_HW) |
239 | /* Schedule the transmission */ | 226 | tls_device_write_space(sk, ctx); |
240 | if (!test_and_set_bit(BIT_TX_SCHEDULED, &tx_ctx->tx_bitmask)) | 227 | else |
241 | schedule_delayed_work(&tx_ctx->tx_work.work, 0); | 228 | #endif |
242 | } | 229 | tls_sw_write_space(sk, ctx); |
243 | 230 | ||
244 | ctx->sk_write_space(sk); | 231 | ctx->sk_write_space(sk); |
245 | } | 232 | } |
@@ -264,8 +251,10 @@ static void tls_sk_proto_close(struct sock *sk, long timeout) | |||
264 | lock_sock(sk); | 251 | lock_sock(sk); |
265 | sk_proto_close = ctx->sk_proto_close; | 252 | sk_proto_close = ctx->sk_proto_close; |
266 | 253 | ||
267 | if ((ctx->tx_conf == TLS_HW_RECORD && ctx->rx_conf == TLS_HW_RECORD) || | 254 | if (ctx->tx_conf == TLS_HW_RECORD && ctx->rx_conf == TLS_HW_RECORD) |
268 | (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE)) { | 255 | goto skip_tx_cleanup; |
256 | |||
257 | if (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE) { | ||
269 | free_ctx = true; | 258 | free_ctx = true; |
270 | goto skip_tx_cleanup; | 259 | goto skip_tx_cleanup; |
271 | } | 260 | } |
@@ -368,6 +357,30 @@ static int do_tls_getsockopt_tx(struct sock *sk, char __user *optval, | |||
368 | rc = -EFAULT; | 357 | rc = -EFAULT; |
369 | break; | 358 | break; |
370 | } | 359 | } |
360 | case TLS_CIPHER_AES_GCM_256: { | ||
361 | struct tls12_crypto_info_aes_gcm_256 * | ||
362 | crypto_info_aes_gcm_256 = | ||
363 | container_of(crypto_info, | ||
364 | struct tls12_crypto_info_aes_gcm_256, | ||
365 | info); | ||
366 | |||
367 | if (len != sizeof(*crypto_info_aes_gcm_256)) { | ||
368 | rc = -EINVAL; | ||
369 | goto out; | ||
370 | } | ||
371 | lock_sock(sk); | ||
372 | memcpy(crypto_info_aes_gcm_256->iv, | ||
373 | ctx->tx.iv + TLS_CIPHER_AES_GCM_256_SALT_SIZE, | ||
374 | TLS_CIPHER_AES_GCM_256_IV_SIZE); | ||
375 | memcpy(crypto_info_aes_gcm_256->rec_seq, ctx->tx.rec_seq, | ||
376 | TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE); | ||
377 | release_sock(sk); | ||
378 | if (copy_to_user(optval, | ||
379 | crypto_info_aes_gcm_256, | ||
380 | sizeof(*crypto_info_aes_gcm_256))) | ||
381 | rc = -EFAULT; | ||
382 | break; | ||
383 | } | ||
371 | default: | 384 | default: |
372 | rc = -EINVAL; | 385 | rc = -EINVAL; |
373 | } | 386 | } |
@@ -407,7 +420,9 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | |||
407 | unsigned int optlen, int tx) | 420 | unsigned int optlen, int tx) |
408 | { | 421 | { |
409 | struct tls_crypto_info *crypto_info; | 422 | struct tls_crypto_info *crypto_info; |
423 | struct tls_crypto_info *alt_crypto_info; | ||
410 | struct tls_context *ctx = tls_get_ctx(sk); | 424 | struct tls_context *ctx = tls_get_ctx(sk); |
425 | size_t optsize; | ||
411 | int rc = 0; | 426 | int rc = 0; |
412 | int conf; | 427 | int conf; |
413 | 428 | ||
@@ -416,10 +431,13 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | |||
416 | goto out; | 431 | goto out; |
417 | } | 432 | } |
418 | 433 | ||
419 | if (tx) | 434 | if (tx) { |
420 | crypto_info = &ctx->crypto_send.info; | 435 | crypto_info = &ctx->crypto_send.info; |
421 | else | 436 | alt_crypto_info = &ctx->crypto_recv.info; |
437 | } else { | ||
422 | crypto_info = &ctx->crypto_recv.info; | 438 | crypto_info = &ctx->crypto_recv.info; |
439 | alt_crypto_info = &ctx->crypto_send.info; | ||
440 | } | ||
423 | 441 | ||
424 | /* Currently we don't support set crypto info more than one time */ | 442 | /* Currently we don't support set crypto info more than one time */ |
425 | if (TLS_CRYPTO_INFO_READY(crypto_info)) { | 443 | if (TLS_CRYPTO_INFO_READY(crypto_info)) { |
@@ -434,14 +452,28 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | |||
434 | } | 452 | } |
435 | 453 | ||
436 | /* check version */ | 454 | /* check version */ |
437 | if (crypto_info->version != TLS_1_2_VERSION) { | 455 | if (crypto_info->version != TLS_1_2_VERSION && |
456 | crypto_info->version != TLS_1_3_VERSION) { | ||
438 | rc = -ENOTSUPP; | 457 | rc = -ENOTSUPP; |
439 | goto err_crypto_info; | 458 | goto err_crypto_info; |
440 | } | 459 | } |
441 | 460 | ||
461 | /* Ensure that TLS version and ciphers are same in both directions */ | ||
462 | if (TLS_CRYPTO_INFO_READY(alt_crypto_info)) { | ||
463 | if (alt_crypto_info->version != crypto_info->version || | ||
464 | alt_crypto_info->cipher_type != crypto_info->cipher_type) { | ||
465 | rc = -EINVAL; | ||
466 | goto err_crypto_info; | ||
467 | } | ||
468 | } | ||
469 | |||
442 | switch (crypto_info->cipher_type) { | 470 | switch (crypto_info->cipher_type) { |
443 | case TLS_CIPHER_AES_GCM_128: { | 471 | case TLS_CIPHER_AES_GCM_128: |
444 | if (optlen != sizeof(struct tls12_crypto_info_aes_gcm_128)) { | 472 | case TLS_CIPHER_AES_GCM_256: { |
473 | optsize = crypto_info->cipher_type == TLS_CIPHER_AES_GCM_128 ? | ||
474 | sizeof(struct tls12_crypto_info_aes_gcm_128) : | ||
475 | sizeof(struct tls12_crypto_info_aes_gcm_256); | ||
476 | if (optlen != optsize) { | ||
445 | rc = -EINVAL; | 477 | rc = -EINVAL; |
446 | goto err_crypto_info; | 478 | goto err_crypto_info; |
447 | } | 479 | } |
@@ -551,6 +583,43 @@ static struct tls_context *create_ctx(struct sock *sk) | |||
551 | return ctx; | 583 | return ctx; |
552 | } | 584 | } |
553 | 585 | ||
586 | static void tls_build_proto(struct sock *sk) | ||
587 | { | ||
588 | int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4; | ||
589 | |||
590 | /* Build IPv6 TLS whenever the address of tcpv6 _prot changes */ | ||
591 | if (ip_ver == TLSV6 && | ||
592 | unlikely(sk->sk_prot != smp_load_acquire(&saved_tcpv6_prot))) { | ||
593 | mutex_lock(&tcpv6_prot_mutex); | ||
594 | if (likely(sk->sk_prot != saved_tcpv6_prot)) { | ||
595 | build_protos(tls_prots[TLSV6], sk->sk_prot); | ||
596 | smp_store_release(&saved_tcpv6_prot, sk->sk_prot); | ||
597 | } | ||
598 | mutex_unlock(&tcpv6_prot_mutex); | ||
599 | } | ||
600 | |||
601 | if (ip_ver == TLSV4 && | ||
602 | unlikely(sk->sk_prot != smp_load_acquire(&saved_tcpv4_prot))) { | ||
603 | mutex_lock(&tcpv4_prot_mutex); | ||
604 | if (likely(sk->sk_prot != saved_tcpv4_prot)) { | ||
605 | build_protos(tls_prots[TLSV4], sk->sk_prot); | ||
606 | smp_store_release(&saved_tcpv4_prot, sk->sk_prot); | ||
607 | } | ||
608 | mutex_unlock(&tcpv4_prot_mutex); | ||
609 | } | ||
610 | } | ||
611 | |||
612 | static void tls_hw_sk_destruct(struct sock *sk) | ||
613 | { | ||
614 | struct tls_context *ctx = tls_get_ctx(sk); | ||
615 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
616 | |||
617 | ctx->sk_destruct(sk); | ||
618 | /* Free ctx */ | ||
619 | kfree(ctx); | ||
620 | icsk->icsk_ulp_data = NULL; | ||
621 | } | ||
622 | |||
554 | static int tls_hw_prot(struct sock *sk) | 623 | static int tls_hw_prot(struct sock *sk) |
555 | { | 624 | { |
556 | struct tls_context *ctx; | 625 | struct tls_context *ctx; |
@@ -564,12 +633,17 @@ static int tls_hw_prot(struct sock *sk) | |||
564 | if (!ctx) | 633 | if (!ctx) |
565 | goto out; | 634 | goto out; |
566 | 635 | ||
636 | spin_unlock_bh(&device_spinlock); | ||
637 | tls_build_proto(sk); | ||
567 | ctx->hash = sk->sk_prot->hash; | 638 | ctx->hash = sk->sk_prot->hash; |
568 | ctx->unhash = sk->sk_prot->unhash; | 639 | ctx->unhash = sk->sk_prot->unhash; |
569 | ctx->sk_proto_close = sk->sk_prot->close; | 640 | ctx->sk_proto_close = sk->sk_prot->close; |
641 | ctx->sk_destruct = sk->sk_destruct; | ||
642 | sk->sk_destruct = tls_hw_sk_destruct; | ||
570 | ctx->rx_conf = TLS_HW_RECORD; | 643 | ctx->rx_conf = TLS_HW_RECORD; |
571 | ctx->tx_conf = TLS_HW_RECORD; | 644 | ctx->tx_conf = TLS_HW_RECORD; |
572 | update_sk_prot(sk, ctx); | 645 | update_sk_prot(sk, ctx); |
646 | spin_lock_bh(&device_spinlock); | ||
573 | rc = 1; | 647 | rc = 1; |
574 | break; | 648 | break; |
575 | } | 649 | } |
@@ -668,7 +742,6 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG], | |||
668 | 742 | ||
669 | static int tls_init(struct sock *sk) | 743 | static int tls_init(struct sock *sk) |
670 | { | 744 | { |
671 | int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4; | ||
672 | struct tls_context *ctx; | 745 | struct tls_context *ctx; |
673 | int rc = 0; | 746 | int rc = 0; |
674 | 747 | ||
@@ -691,27 +764,7 @@ static int tls_init(struct sock *sk) | |||
691 | goto out; | 764 | goto out; |
692 | } | 765 | } |
693 | 766 | ||
694 | /* Build IPv6 TLS whenever the address of tcpv6 _prot changes */ | 767 | tls_build_proto(sk); |
695 | if (ip_ver == TLSV6 && | ||
696 | unlikely(sk->sk_prot != smp_load_acquire(&saved_tcpv6_prot))) { | ||
697 | mutex_lock(&tcpv6_prot_mutex); | ||
698 | if (likely(sk->sk_prot != saved_tcpv6_prot)) { | ||
699 | build_protos(tls_prots[TLSV6], sk->sk_prot); | ||
700 | smp_store_release(&saved_tcpv6_prot, sk->sk_prot); | ||
701 | } | ||
702 | mutex_unlock(&tcpv6_prot_mutex); | ||
703 | } | ||
704 | |||
705 | if (ip_ver == TLSV4 && | ||
706 | unlikely(sk->sk_prot != smp_load_acquire(&saved_tcpv4_prot))) { | ||
707 | mutex_lock(&tcpv4_prot_mutex); | ||
708 | if (likely(sk->sk_prot != saved_tcpv4_prot)) { | ||
709 | build_protos(tls_prots[TLSV4], sk->sk_prot); | ||
710 | smp_store_release(&saved_tcpv4_prot, sk->sk_prot); | ||
711 | } | ||
712 | mutex_unlock(&tcpv4_prot_mutex); | ||
713 | } | ||
714 | |||
715 | ctx->tx_conf = TLS_BASE; | 768 | ctx->tx_conf = TLS_BASE; |
716 | ctx->rx_conf = TLS_BASE; | 769 | ctx->rx_conf = TLS_BASE; |
717 | update_sk_prot(sk, ctx); | 770 | update_sk_prot(sk, ctx); |