diff options
Diffstat (limited to 'net/tls/tls_main.c')
| -rw-r--r-- | net/tls/tls_main.c | 59 | 
1 files changed, 42 insertions, 17 deletions
| diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index b0d5fcea47e7..d824d548447e 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -46,16 +46,26 @@ MODULE_DESCRIPTION("Transport Layer Security Support");  MODULE_LICENSE("Dual BSD/GPL");  enum { +	TLSV4, +	TLSV6, +	TLS_NUM_PROTS, +}; + +enum {  	TLS_BASE_TX,  	TLS_SW_TX,  	TLS_NUM_CONFIG,  }; -static struct proto tls_prots[TLS_NUM_CONFIG]; +static struct proto *saved_tcpv6_prot; +static DEFINE_MUTEX(tcpv6_prot_mutex); +static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG];  static inline void update_sk_prot(struct sock *sk, struct tls_context *ctx)  { -	sk->sk_prot = &tls_prots[ctx->tx_conf]; +	int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4; + +	sk->sk_prot = &tls_prots[ip_ver][ctx->tx_conf];  }  int wait_on_pending_writer(struct sock *sk, long *timeo) @@ -308,8 +318,11 @@ static int do_tls_getsockopt_tx(struct sock *sk, char __user *optval,  			goto out;  		}  		lock_sock(sk); -		memcpy(crypto_info_aes_gcm_128->iv, ctx->iv, +		memcpy(crypto_info_aes_gcm_128->iv, +		       ctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,  		       TLS_CIPHER_AES_GCM_128_IV_SIZE); +		memcpy(crypto_info_aes_gcm_128->rec_seq, ctx->rec_seq, +		       TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);  		release_sock(sk);  		if (copy_to_user(optval,  				 crypto_info_aes_gcm_128, @@ -375,7 +388,7 @@ static int do_tls_setsockopt_tx(struct sock *sk, char __user *optval,  	rc = copy_from_user(crypto_info, optval, sizeof(*crypto_info));  	if (rc) {  		rc = -EFAULT; -		goto out; +		goto err_crypto_info;  	}  	/* check version */ @@ -450,8 +463,21 @@ static int tls_setsockopt(struct sock *sk, int level, int optname,  	return do_tls_setsockopt(sk, optname, optval, optlen);  } +static void build_protos(struct proto *prot, struct proto *base) +{ +	prot[TLS_BASE_TX] = *base; +	prot[TLS_BASE_TX].setsockopt	= tls_setsockopt; +	prot[TLS_BASE_TX].getsockopt	= tls_getsockopt; +	prot[TLS_BASE_TX].close		= tls_sk_proto_close; + +	prot[TLS_SW_TX] = prot[TLS_BASE_TX]; +	prot[TLS_SW_TX].sendmsg		= tls_sw_sendmsg; +	prot[TLS_SW_TX].sendpage	= tls_sw_sendpage; +} +  static int tls_init(struct sock *sk)  { +	int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4;  	struct inet_connection_sock *icsk = inet_csk(sk);  	struct tls_context *ctx;  	int rc = 0; @@ -476,6 +502,17 @@ static int tls_init(struct sock *sk)  	ctx->getsockopt = sk->sk_prot->getsockopt;  	ctx->sk_proto_close = sk->sk_prot->close; +	/* Build IPv6 TLS whenever the address of tcpv6_prot changes */ +	if (ip_ver == TLSV6 && +	    unlikely(sk->sk_prot != smp_load_acquire(&saved_tcpv6_prot))) { +		mutex_lock(&tcpv6_prot_mutex); +		if (likely(sk->sk_prot != saved_tcpv6_prot)) { +			build_protos(tls_prots[TLSV6], sk->sk_prot); +			smp_store_release(&saved_tcpv6_prot, sk->sk_prot); +		} +		mutex_unlock(&tcpv6_prot_mutex); +	} +  	ctx->tx_conf = TLS_BASE_TX;  	update_sk_prot(sk, ctx);  out: @@ -490,21 +527,9 @@ static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {  	.init			= tls_init,  }; -static void build_protos(struct proto *prot, struct proto *base) -{ -	prot[TLS_BASE_TX] = *base; -	prot[TLS_BASE_TX].setsockopt	= tls_setsockopt; -	prot[TLS_BASE_TX].getsockopt	= tls_getsockopt; -	prot[TLS_BASE_TX].close		= tls_sk_proto_close; - -	prot[TLS_SW_TX] = prot[TLS_BASE_TX]; -	prot[TLS_SW_TX].sendmsg		= tls_sw_sendmsg; -	prot[TLS_SW_TX].sendpage	= tls_sw_sendpage; -} -  static int __init tls_register(void)  { -	build_protos(tls_prots, &tcp_prot); +	build_protos(tls_prots[TLSV4], &tcp_prot);  	tcp_register_ulp(&tcp_tls_ulp_ops); | 

