diff mbox series

[net-next,v2,3/3] net: tls: export protocol version, cipher, tx_conf/rx_conf to socket diag

Message ID 22da29aa0d0c683afeba7549cabc64c5e073d308.1567095873.git.dcaratti@redhat.com
State Superseded
Delegated to: David Miller
Headers show
Series net: tls: add socket diag | expand

Commit Message

Davide Caratti Aug. 29, 2019, 4:48 p.m. UTC
When an application configures kernel TLS on top of a TCP socket, it's
now possible for inet_diag_handler() to collect information regarding the
protocol version, the cipher type and TX / RX configuration, in case
INET_DIAG_INFO is requested.

Signed-off-by: Davide Caratti <dcaratti@redhat.com>
---
 include/net/tls.h              | 19 ++++++++++
 include/uapi/linux/inet_diag.h |  1 +
 include/uapi/linux/tls.h       | 15 ++++++++
 net/tls/tls_main.c             | 64 ++++++++++++++++++++++++++++++++++
 4 files changed, 99 insertions(+)

Comments

Jakub Kicinski Aug. 29, 2019, 9:56 p.m. UTC | #1
On Thu, 29 Aug 2019 18:48:04 +0200, Davide Caratti wrote:
> When an application configures kernel TLS on top of a TCP socket, it's
> now possible for inet_diag_handler() to collect information regarding the
> protocol version, the cipher type and TX / RX configuration, in case
> INET_DIAG_INFO is requested.
> 
> Signed-off-by: Davide Caratti <dcaratti@redhat.com>

> diff --git a/include/net/tls.h b/include/net/tls.h
> index 4997742475cd..990f1d9182a3 100644
> --- a/include/net/tls.h
> +++ b/include/net/tls.h
> @@ -431,6 +431,25 @@ static inline bool is_tx_ready(struct tls_sw_context_tx *ctx)
>  	return READ_ONCE(rec->tx_ready);
>  }
>  
> +static inline u16 tls_user_config(struct tls_context *ctx, bool tx)
> +{
> +	u16 config = tx ? ctx->tx_conf : ctx->rx_conf;
> +
> +	switch (config) {
> +	case TLS_BASE:
> +		return TLS_CONF_BASE;
> +	case TLS_SW:
> +		return TLS_CONF_SW;
> +#ifdef CONFIG_TLS_DEVICE

Recently the TLS_HW define was taken out of the ifdef, so the ifdef
around this is no longer necessary.

> +	case TLS_HW:
> +		return TLS_CONF_HW;
> +#endif
> +	case TLS_HW_RECORD:
> +		return TLS_CONF_HW_RECORD;
> +	}
> +	return 0;
> +}
> +
>  struct sk_buff *
>  tls_validate_xmit_skb(struct sock *sk, struct net_device *dev,
>  		      struct sk_buff *skb);

> diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
> index f8f2d2c3d627..3351a2ace369 100644
> --- a/net/tls/tls_main.c
> +++ b/net/tls/tls_main.c
> @@ -39,6 +39,7 @@
>  #include <linux/netdevice.h>
>  #include <linux/sched/signal.h>
>  #include <linux/inetdevice.h>
> +#include <linux/inet_diag.h>
>  
>  #include <net/tls.h>
>  
> @@ -835,6 +836,67 @@ static void tls_update(struct sock *sk, struct proto *p)
>  	}
>  }
>  
> +static int tls_get_info(const struct sock *sk, struct sk_buff *skb)
> +{
> +	struct tls_context *ctx;
> +	u16 version, cipher_type;

Unfortunately revere christmas tree will be needed :(

> +	struct nlattr *start;
> +	int err;
Davide Caratti Aug. 30, 2019, 8:56 a.m. UTC | #2
On Thu, 2019-08-29 at 14:56 -0700, Jakub Kicinski wrote:
> On Thu, 29 Aug 2019 18:48:04 +0200, Davide Caratti wrote:

[...]
> > @@ -431,6 +431,25 @@ static inline bool is_tx_ready(struct tls_sw_context_tx *ctx)
> >  	return READ_ONCE(rec->tx_ready);
> >  }
> >  
> > +static inline u16 tls_user_config(struct tls_context *ctx, bool tx)
> > +{
> > +	u16 config = tx ? ctx->tx_conf : ctx->rx_conf;
> > +
> > +	switch (config) {
> > +	case TLS_BASE:
> > +		return TLS_CONF_BASE;
> > +	case TLS_SW:
> > +		return TLS_CONF_SW;
> > +#ifdef CONFIG_TLS_DEVICE
> 
> Recently the TLS_HW define was taken out of the ifdef, so the ifdef
> around this is no longer necessary.

since the value of 'ctx->tx_conf' is always assigned/compared to 'TLS_HW'
under #ifdef CONFIG_TLS_DEVICE, the diag code will never reach that label 
when CONFIG_TLS_DEVICE is unset.
On the other hand, I'm ok for avoiding the #ifdefs unless they are really 
needed _ and probably IS_ENABLED() won't improve anything here, so I will 
just remove the #ifdef in series v3.

[...]

> > @@ -835,6 +836,67 @@ static void tls_update(struct sock *sk, struct proto *p)
> >  	}
> >  }
> >  
> > +static int tls_get_info(const struct sock *sk, struct sk_buff *skb)
> > +{
> > +	struct tls_context *ctx;
> > +	u16 version, cipher_type;
> 
> Unfortunately revere christmas tree will be needed :(

that's due :) I will fix in series v3.

thanks!
diff mbox series

Patch

diff --git a/include/net/tls.h b/include/net/tls.h
index 4997742475cd..990f1d9182a3 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -431,6 +431,25 @@  static inline bool is_tx_ready(struct tls_sw_context_tx *ctx)
 	return READ_ONCE(rec->tx_ready);
 }
 
+static inline u16 tls_user_config(struct tls_context *ctx, bool tx)
+{
+	u16 config = tx ? ctx->tx_conf : ctx->rx_conf;
+
+	switch (config) {
+	case TLS_BASE:
+		return TLS_CONF_BASE;
+	case TLS_SW:
+		return TLS_CONF_SW;
+#ifdef CONFIG_TLS_DEVICE
+	case TLS_HW:
+		return TLS_CONF_HW;
+#endif
+	case TLS_HW_RECORD:
+		return TLS_CONF_HW_RECORD;
+	}
+	return 0;
+}
+
 struct sk_buff *
 tls_validate_xmit_skb(struct sock *sk, struct net_device *dev,
 		      struct sk_buff *skb);
diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h
index e2c6273274f3..a1ff345b3f33 100644
--- a/include/uapi/linux/inet_diag.h
+++ b/include/uapi/linux/inet_diag.h
@@ -162,6 +162,7 @@  enum {
 enum {
 	INET_ULP_INFO_UNSPEC,
 	INET_ULP_INFO_NAME,
+	INET_ULP_INFO_TLS,
 	__INET_ULP_INFO_MAX,
 };
 #define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1)
diff --git a/include/uapi/linux/tls.h b/include/uapi/linux/tls.h
index 5b9c26753e46..bcd2869ed472 100644
--- a/include/uapi/linux/tls.h
+++ b/include/uapi/linux/tls.h
@@ -109,4 +109,19 @@  struct tls12_crypto_info_aes_ccm_128 {
 	unsigned char rec_seq[TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE];
 };
 
+enum {
+	TLS_INFO_UNSPEC,
+	TLS_INFO_VERSION,
+	TLS_INFO_CIPHER,
+	TLS_INFO_TXCONF,
+	TLS_INFO_RXCONF,
+	__TLS_INFO_MAX,
+};
+#define TLS_INFO_MAX (__TLS_INFO_MAX - 1)
+
+#define TLS_CONF_BASE 1
+#define TLS_CONF_SW 2
+#define TLS_CONF_HW 3
+#define TLS_CONF_HW_RECORD 4
+
 #endif /* _UAPI_LINUX_TLS_H */
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index f8f2d2c3d627..3351a2ace369 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -39,6 +39,7 @@ 
 #include <linux/netdevice.h>
 #include <linux/sched/signal.h>
 #include <linux/inetdevice.h>
+#include <linux/inet_diag.h>
 
 #include <net/tls.h>
 
@@ -835,6 +836,67 @@  static void tls_update(struct sock *sk, struct proto *p)
 	}
 }
 
+static int tls_get_info(const struct sock *sk, struct sk_buff *skb)
+{
+	struct tls_context *ctx;
+	u16 version, cipher_type;
+	struct nlattr *start;
+	int err;
+
+	start = nla_nest_start_noflag(skb, INET_ULP_INFO_TLS);
+	if (!start)
+		return -EMSGSIZE;
+
+	rcu_read_lock();
+	ctx = rcu_dereference(inet_csk(sk)->icsk_ulp_data);
+	if (!ctx) {
+		err = 0;
+		goto nla_failure;
+	}
+	version = ctx->prot_info.version;
+	if (version) {
+		err = nla_put_u16(skb, TLS_INFO_VERSION, version);
+		if (err)
+			goto nla_failure;
+	}
+	cipher_type = ctx->prot_info.cipher_type;
+	if (cipher_type) {
+		err = nla_put_u16(skb, TLS_INFO_CIPHER, cipher_type);
+		if (err)
+			goto nla_failure;
+	}
+	err = nla_put_u16(skb, TLS_INFO_TXCONF, tls_user_config(ctx, true));
+	if (err)
+		goto nla_failure;
+
+	err = nla_put_u16(skb, TLS_INFO_RXCONF, tls_user_config(ctx, false));
+	if (err)
+		goto nla_failure;
+
+	rcu_read_unlock();
+	nla_nest_end(skb, start);
+	return 0;
+
+nla_failure:
+	rcu_read_unlock();
+	nla_nest_cancel(skb, start);
+	return err;
+}
+
+static size_t tls_get_info_size(const struct sock *sk)
+{
+	size_t size = 0;
+
+	size += nla_total_size(0) +		/* INET_ULP_INFO_TLS */
+		nla_total_size(sizeof(u16)) +	/* TLS_INFO_VERSION */
+		nla_total_size(sizeof(u16)) +	/* TLS_INFO_CIPHER */
+		nla_total_size(sizeof(u16)) +	/* TLS_INFO_RXCONF */
+		nla_total_size(sizeof(u16)) +	/* TLS_INFO_TXCONF */
+		0;
+
+	return size;
+}
+
 void tls_register_device(struct tls_device *device)
 {
 	spin_lock_bh(&device_spinlock);
@@ -856,6 +918,8 @@  static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {
 	.owner			= THIS_MODULE,
 	.init			= tls_init,
 	.update			= tls_update,
+	.get_info		= tls_get_info,
+	.get_info_size		= tls_get_info_size,
 };
 
 static int __init tls_register(void)