Skip to content

Commit

Permalink
net/tls: Move protocol constants from cipher context to tls context
Browse files Browse the repository at this point in the history
Each tls context maintains two cipher contexts (one each for tx and rx
directions). For each tls session, the constants such as protocol
version, ciphersuite, iv size, associated data size etc are same for
both the directions and need to be stored only once per tls context.
Hence these are moved from 'struct cipher_context' to 'struct
tls_prot_info' and stored only once in 'struct tls_context'.

Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
nxa22042 authored and davem330 committed Feb 19, 2019
1 parent c9b747d commit 4509de1
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 110 deletions.
46 changes: 29 additions & 17 deletions include/net/tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,15 +199,8 @@ enum {
};

struct cipher_context {
u16 prepend_size;
u16 tag_size;
u16 overhead_size;
u16 iv_size;
char *iv;
u16 rec_seq_size;
char *rec_seq;
u16 aad_size;
u16 tail_size;
};

union tls_crypto_context {
Expand All @@ -218,7 +211,21 @@ union tls_crypto_context {
};
};

struct tls_prot_info {
u16 version;
u16 cipher_type;
u16 prepend_size;
u16 tag_size;
u16 overhead_size;
u16 iv_size;
u16 rec_seq_size;
u16 aad_size;
u16 tail_size;
};

struct tls_context {
struct tls_prot_info prot_info;

union tls_crypto_context crypto_send;
union tls_crypto_context crypto_recv;

Expand Down Expand Up @@ -401,16 +408,26 @@ static inline bool tls_bigint_increment(unsigned char *seq, int len)
return (i == -1);
}

static inline struct tls_context *tls_get_ctx(const struct sock *sk)
{
struct inet_connection_sock *icsk = inet_csk(sk);

return icsk->icsk_ulp_data;
}

static inline void tls_advance_record_sn(struct sock *sk,
struct cipher_context *ctx,
int version)
{
if (tls_bigint_increment(ctx->rec_seq, ctx->rec_seq_size))
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_prot_info *prot = &tls_ctx->prot_info;

if (tls_bigint_increment(ctx->rec_seq, prot->rec_seq_size))
tls_err_abort(sk, EBADMSG);

if (version != TLS_1_3_VERSION) {
tls_bigint_increment(ctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
ctx->iv_size);
prot->iv_size);
}
}

Expand All @@ -420,9 +437,10 @@ static inline void tls_fill_prepend(struct tls_context *ctx,
unsigned char record_type,
int version)
{
size_t pkt_len, iv_size = ctx->tx.iv_size;
struct tls_prot_info *prot = &ctx->prot_info;
size_t pkt_len, iv_size = prot->iv_size;

pkt_len = plaintext_len + ctx->tx.tag_size;
pkt_len = plaintext_len + prot->tag_size;
if (version != TLS_1_3_VERSION) {
pkt_len += iv_size;

Expand Down Expand Up @@ -475,12 +493,6 @@ static inline void xor_iv_with_seq(int version, char *iv, char *seq)
}
}

static inline struct tls_context *tls_get_ctx(const struct sock *sk)
{
struct inet_connection_sock *icsk = inet_csk(sk);

return icsk->icsk_ulp_data;
}

static inline struct tls_sw_context_rx *tls_sw_ctx_rx(
const struct tls_context *tls_ctx)
Expand Down
24 changes: 14 additions & 10 deletions net/tls/tls_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ static int tls_push_record(struct sock *sk,
int flags,
unsigned char record_type)
{
struct tls_prot_info *prot = &ctx->prot_info;
struct tcp_sock *tp = tcp_sk(sk);
struct page_frag dummy_tag_frag;
skb_frag_t *frag;
Expand All @@ -256,15 +257,15 @@ static int tls_push_record(struct sock *sk,
frag = &record->frags[0];
tls_fill_prepend(ctx,
skb_frag_address(frag),
record->len - ctx->tx.prepend_size,
record->len - prot->prepend_size,
record_type,
ctx->crypto_send.info.version);

/* HW doesn't care about the data in the tag, because it fills it. */
dummy_tag_frag.page = skb_frag_page(frag);
dummy_tag_frag.offset = 0;

tls_append_frag(record, &dummy_tag_frag, ctx->tx.tag_size);
tls_append_frag(record, &dummy_tag_frag, prot->tag_size);
record->end_seq = tp->write_seq + record->len;
spin_lock_irq(&offload_ctx->lock);
list_add_tail(&record->list, &offload_ctx->records_list);
Expand Down Expand Up @@ -347,6 +348,7 @@ static int tls_push_data(struct sock *sk,
unsigned char record_type)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
int tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
int more = flags & (MSG_SENDPAGE_NOTLAST | MSG_MORE);
Expand Down Expand Up @@ -376,10 +378,10 @@ static int tls_push_data(struct sock *sk,
* we need to leave room for an authentication tag.
*/
max_open_record_len = TLS_MAX_PAYLOAD_SIZE +
tls_ctx->tx.prepend_size;
prot->prepend_size;
do {
rc = tls_do_allocation(sk, ctx, pfrag,
tls_ctx->tx.prepend_size);
prot->prepend_size);
if (rc) {
rc = sk_stream_wait_memory(sk, &timeo);
if (!rc)
Expand All @@ -397,7 +399,7 @@ static int tls_push_data(struct sock *sk,
size = orig_size;
destroy_record(record);
ctx->open_record = NULL;
} else if (record->len > tls_ctx->tx.prepend_size) {
} else if (record->len > prot->prepend_size) {
goto last_record;
}

Expand Down Expand Up @@ -658,6 +660,8 @@ int tls_device_decrypted(struct sock *sk, struct sk_buff *skb)
int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
{
u16 nonce_size, tag_size, iv_size, rec_seq_size;
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_record_info *start_marker_record;
struct tls_offload_context_tx *offload_ctx;
struct tls_crypto_info *crypto_info;
Expand Down Expand Up @@ -703,10 +707,10 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
goto free_offload_ctx;
}

ctx->tx.prepend_size = TLS_HEADER_SIZE + nonce_size;
ctx->tx.tag_size = tag_size;
ctx->tx.overhead_size = ctx->tx.prepend_size + ctx->tx.tag_size;
ctx->tx.iv_size = iv_size;
prot->prepend_size = TLS_HEADER_SIZE + nonce_size;
prot->tag_size = tag_size;
prot->overhead_size = prot->prepend_size + prot->tag_size;
prot->iv_size = iv_size;
ctx->tx.iv = kmalloc(iv_size + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
GFP_KERNEL);
if (!ctx->tx.iv) {
Expand All @@ -716,7 +720,7 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)

memcpy(ctx->tx.iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, iv, iv_size);

ctx->tx.rec_seq_size = rec_seq_size;
prot->rec_seq_size = rec_seq_size;
ctx->tx.rec_seq = kmemdup(rec_seq, rec_seq_size, GFP_KERNEL);
if (!ctx->tx.rec_seq) {
rc = -ENOMEM;
Expand Down
17 changes: 15 additions & 2 deletions net/tls/tls_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
unsigned int optlen, int tx)
{
struct tls_crypto_info *crypto_info;
struct tls_crypto_info *alt_crypto_info;
struct tls_context *ctx = tls_get_ctx(sk);
size_t optsize;
int rc = 0;
Expand All @@ -445,10 +446,13 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
goto out;
}

if (tx)
if (tx) {
crypto_info = &ctx->crypto_send.info;
else
alt_crypto_info = &ctx->crypto_recv.info;
} else {
crypto_info = &ctx->crypto_recv.info;
alt_crypto_info = &ctx->crypto_send.info;
}

/* Currently we don't support set crypto info more than one time */
if (TLS_CRYPTO_INFO_READY(crypto_info)) {
Expand All @@ -469,6 +473,15 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
goto err_crypto_info;
}

/* Ensure that TLS version and ciphers are same in both directions */
if (TLS_CRYPTO_INFO_READY(alt_crypto_info)) {
if (alt_crypto_info->version != crypto_info->version ||
alt_crypto_info->cipher_type != crypto_info->cipher_type) {
rc = -EINVAL;
goto err_crypto_info;
}
}

switch (crypto_info->cipher_type) {
case TLS_CIPHER_AES_GCM_128:
case TLS_CIPHER_AES_GCM_256: {
Expand Down
Loading

0 comments on commit 4509de1

Please sign in to comment.