Skip to content

Commit f295b3a

Browse files
nxa22042davem330
authored andcommitted
net/tls: Add support of AES128-CCM based ciphers
Added support for AES128-CCM based record encryption. AES128-CCM is similar to AES128-GCM. Both of them have same salt/iv/mac size. The notable difference between the two is that while invoking AES128-CCM operation, the salt||nonce (which is passed as IV) has to be prefixed with a hardcoded value '2'. Further, CCM implementation in kernel requires IV passed in crypto_aead_request() to be full '16' bytes. Therefore, the record structure 'struct tls_rec' has been modified to reserve '16' bytes for IV. This works for both GCM and CCM based cipher. Signed-off-by: Vakul Garg <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6a23c0a commit f295b3a

File tree

4 files changed

+97
-31
lines changed

4 files changed

+97
-31
lines changed

include/net/tls.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@
6060
#define TLS_AAD_SPACE_SIZE 13
6161
#define TLS_DEVICE_NAME_MAX 32
6262

63+
#define MAX_IV_SIZE 16
64+
65+
/* For AES-CCM, the full 16-bytes of IV is made of '4' fields of given sizes.
66+
*
67+
* IV[16] = b0[1] || implicit nonce[4] || explicit nonce[8] || length[3]
68+
*
69+
* The field 'length' is encoded in field 'b0' as '(length width - 1)'.
70+
* Hence b0 contains (3 - 1) = 2.
71+
*/
72+
#define TLS_AES_CCM_IV_B0_BYTE 2
73+
6374
/*
6475
* This structure defines the routines for Inline TLS driver.
6576
* The following routines are optional and filled with a
@@ -123,8 +134,7 @@ struct tls_rec {
123134
struct scatterlist sg_content_type;
124135

125136
char aad_space[TLS_AAD_SPACE_SIZE];
126-
u8 iv_data[TLS_CIPHER_AES_GCM_128_IV_SIZE +
127-
TLS_CIPHER_AES_GCM_128_SALT_SIZE];
137+
u8 iv_data[MAX_IV_SIZE];
128138
struct aead_request aead_req;
129139
u8 aead_req_ctx[];
130140
};
@@ -219,6 +229,7 @@ struct tls_prot_info {
219229
u16 tag_size;
220230
u16 overhead_size;
221231
u16 iv_size;
232+
u16 salt_size;
222233
u16 rec_seq_size;
223234
u16 aad_size;
224235
u16 tail_size;

include/uapi/linux/tls.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@
7070
#define TLS_CIPHER_AES_GCM_256_TAG_SIZE 16
7171
#define TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE 8
7272

73+
#define TLS_CIPHER_AES_CCM_128 53
74+
#define TLS_CIPHER_AES_CCM_128_IV_SIZE 8
75+
#define TLS_CIPHER_AES_CCM_128_KEY_SIZE 16
76+
#define TLS_CIPHER_AES_CCM_128_SALT_SIZE 4
77+
#define TLS_CIPHER_AES_CCM_128_TAG_SIZE 16
78+
#define TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE 8
79+
7380
#define TLS_SET_RECORD_TYPE 1
7481
#define TLS_GET_RECORD_TYPE 2
7582

@@ -94,4 +101,12 @@ struct tls12_crypto_info_aes_gcm_256 {
94101
unsigned char rec_seq[TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE];
95102
};
96103

104+
struct tls12_crypto_info_aes_ccm_128 {
105+
struct tls_crypto_info info;
106+
unsigned char iv[TLS_CIPHER_AES_CCM_128_IV_SIZE];
107+
unsigned char key[TLS_CIPHER_AES_CCM_128_KEY_SIZE];
108+
unsigned char salt[TLS_CIPHER_AES_CCM_128_SALT_SIZE];
109+
unsigned char rec_seq[TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE];
110+
};
111+
97112
#endif /* _UAPI_LINUX_TLS_H */

net/tls/tls_main.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -469,27 +469,32 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
469469

470470
switch (crypto_info->cipher_type) {
471471
case TLS_CIPHER_AES_GCM_128:
472+
optsize = sizeof(struct tls12_crypto_info_aes_gcm_128);
473+
break;
472474
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) {
477-
rc = -EINVAL;
478-
goto err_crypto_info;
479-
}
480-
rc = copy_from_user(crypto_info + 1, optval + sizeof(*crypto_info),
481-
optlen - sizeof(*crypto_info));
482-
if (rc) {
483-
rc = -EFAULT;
484-
goto err_crypto_info;
485-
}
475+
optsize = sizeof(struct tls12_crypto_info_aes_gcm_256);
486476
break;
487477
}
478+
case TLS_CIPHER_AES_CCM_128:
479+
optsize = sizeof(struct tls12_crypto_info_aes_ccm_128);
480+
break;
488481
default:
489482
rc = -EINVAL;
490483
goto err_crypto_info;
491484
}
492485

486+
if (optlen != optsize) {
487+
rc = -EINVAL;
488+
goto err_crypto_info;
489+
}
490+
491+
rc = copy_from_user(crypto_info + 1, optval + sizeof(*crypto_info),
492+
optlen - sizeof(*crypto_info));
493+
if (rc) {
494+
rc = -EFAULT;
495+
goto err_crypto_info;
496+
}
497+
493498
if (tx) {
494499
#ifdef CONFIG_TLS_DEVICE
495500
rc = tls_set_device_offload(sk, ctx);

net/tls/tls_sw.c

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@
4242
#include <net/strparser.h>
4343
#include <net/tls.h>
4444

45-
#define MAX_IV_SIZE TLS_CIPHER_AES_GCM_128_IV_SIZE
46-
4745
static int __skb_nsg(struct sk_buff *skb, int offset, int len,
4846
unsigned int recursion_level)
4947
{
@@ -479,11 +477,18 @@ static int tls_do_encryption(struct sock *sk,
479477
struct tls_rec *rec = ctx->open_rec;
480478
struct sk_msg *msg_en = &rec->msg_encrypted;
481479
struct scatterlist *sge = sk_msg_elem(msg_en, start);
482-
int rc;
480+
int rc, iv_offset = 0;
481+
482+
/* For CCM based ciphers, first byte of IV is a constant */
483+
if (prot->cipher_type == TLS_CIPHER_AES_CCM_128) {
484+
rec->iv_data[0] = TLS_AES_CCM_IV_B0_BYTE;
485+
iv_offset = 1;
486+
}
487+
488+
memcpy(&rec->iv_data[iv_offset], tls_ctx->tx.iv,
489+
prot->iv_size + prot->salt_size);
483490

484-
memcpy(rec->iv_data, tls_ctx->tx.iv, sizeof(rec->iv_data));
485-
xor_iv_with_seq(prot->version, rec->iv_data,
486-
tls_ctx->tx.rec_seq);
491+
xor_iv_with_seq(prot->version, rec->iv_data, tls_ctx->tx.rec_seq);
487492

488493
sge->offset += prot->prepend_size;
489494
sge->length -= prot->prepend_size;
@@ -1344,6 +1349,7 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
13441349
struct scatterlist *sgout = NULL;
13451350
const int data_len = rxm->full_len - prot->overhead_size +
13461351
prot->tail_size;
1352+
int iv_offset = 0;
13471353

13481354
if (*zc && (out_iov || out_sg)) {
13491355
if (out_iov)
@@ -1386,18 +1392,25 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
13861392
aad = (u8 *)(sgout + n_sgout);
13871393
iv = aad + prot->aad_size;
13881394

1395+
/* For CCM based ciphers, first byte of nonce+iv is always '2' */
1396+
if (prot->cipher_type == TLS_CIPHER_AES_CCM_128) {
1397+
iv[0] = 2;
1398+
iv_offset = 1;
1399+
}
1400+
13891401
/* Prepare IV */
13901402
err = skb_copy_bits(skb, rxm->offset + TLS_HEADER_SIZE,
1391-
iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
1403+
iv + iv_offset + prot->salt_size,
13921404
prot->iv_size);
13931405
if (err < 0) {
13941406
kfree(mem);
13951407
return err;
13961408
}
13971409
if (prot->version == TLS_1_3_VERSION)
1398-
memcpy(iv, tls_ctx->rx.iv, crypto_aead_ivsize(ctx->aead_recv));
1410+
memcpy(iv + iv_offset, tls_ctx->rx.iv,
1411+
crypto_aead_ivsize(ctx->aead_recv));
13991412
else
1400-
memcpy(iv, tls_ctx->rx.iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
1413+
memcpy(iv + iv_offset, tls_ctx->rx.iv, prot->salt_size);
14011414

14021415
xor_iv_with_seq(prot->version, iv, tls_ctx->rx.rec_seq);
14031416

@@ -2152,14 +2165,15 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
21522165
struct tls_crypto_info *crypto_info;
21532166
struct tls12_crypto_info_aes_gcm_128 *gcm_128_info;
21542167
struct tls12_crypto_info_aes_gcm_256 *gcm_256_info;
2168+
struct tls12_crypto_info_aes_ccm_128 *ccm_128_info;
21552169
struct tls_sw_context_tx *sw_ctx_tx = NULL;
21562170
struct tls_sw_context_rx *sw_ctx_rx = NULL;
21572171
struct cipher_context *cctx;
21582172
struct crypto_aead **aead;
21592173
struct strp_callbacks cb;
2160-
u16 nonce_size, tag_size, iv_size, rec_seq_size;
2174+
u16 nonce_size, tag_size, iv_size, rec_seq_size, salt_size;
21612175
struct crypto_tfm *tfm;
2162-
char *iv, *rec_seq, *key, *salt;
2176+
char *iv, *rec_seq, *key, *salt, *cipher_name;
21632177
size_t keysize;
21642178
int rc = 0;
21652179

@@ -2224,6 +2238,8 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
22242238
keysize = TLS_CIPHER_AES_GCM_128_KEY_SIZE;
22252239
key = gcm_128_info->key;
22262240
salt = gcm_128_info->salt;
2241+
salt_size = TLS_CIPHER_AES_GCM_128_SALT_SIZE;
2242+
cipher_name = "gcm(aes)";
22272243
break;
22282244
}
22292245
case TLS_CIPHER_AES_GCM_256: {
@@ -2239,6 +2255,25 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
22392255
keysize = TLS_CIPHER_AES_GCM_256_KEY_SIZE;
22402256
key = gcm_256_info->key;
22412257
salt = gcm_256_info->salt;
2258+
salt_size = TLS_CIPHER_AES_GCM_256_SALT_SIZE;
2259+
cipher_name = "gcm(aes)";
2260+
break;
2261+
}
2262+
case TLS_CIPHER_AES_CCM_128: {
2263+
nonce_size = TLS_CIPHER_AES_CCM_128_IV_SIZE;
2264+
tag_size = TLS_CIPHER_AES_CCM_128_TAG_SIZE;
2265+
iv_size = TLS_CIPHER_AES_CCM_128_IV_SIZE;
2266+
iv = ((struct tls12_crypto_info_aes_ccm_128 *)crypto_info)->iv;
2267+
rec_seq_size = TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE;
2268+
rec_seq =
2269+
((struct tls12_crypto_info_aes_ccm_128 *)crypto_info)->rec_seq;
2270+
ccm_128_info =
2271+
(struct tls12_crypto_info_aes_ccm_128 *)crypto_info;
2272+
keysize = TLS_CIPHER_AES_CCM_128_KEY_SIZE;
2273+
key = ccm_128_info->key;
2274+
salt = ccm_128_info->salt;
2275+
salt_size = TLS_CIPHER_AES_CCM_128_SALT_SIZE;
2276+
cipher_name = "ccm(aes)";
22422277
break;
22432278
}
22442279
default:
@@ -2268,24 +2303,24 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
22682303
prot->overhead_size = prot->prepend_size +
22692304
prot->tag_size + prot->tail_size;
22702305
prot->iv_size = iv_size;
2271-
cctx->iv = kmalloc(iv_size + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
2272-
GFP_KERNEL);
2306+
prot->salt_size = salt_size;
2307+
cctx->iv = kmalloc(iv_size + salt_size, GFP_KERNEL);
22732308
if (!cctx->iv) {
22742309
rc = -ENOMEM;
22752310
goto free_priv;
22762311
}
22772312
/* Note: 128 & 256 bit salt are the same size */
2278-
memcpy(cctx->iv, salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
2279-
memcpy(cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, iv, iv_size);
22802313
prot->rec_seq_size = rec_seq_size;
2314+
memcpy(cctx->iv, salt, salt_size);
2315+
memcpy(cctx->iv + salt_size, iv, iv_size);
22812316
cctx->rec_seq = kmemdup(rec_seq, rec_seq_size, GFP_KERNEL);
22822317
if (!cctx->rec_seq) {
22832318
rc = -ENOMEM;
22842319
goto free_iv;
22852320
}
22862321

22872322
if (!*aead) {
2288-
*aead = crypto_alloc_aead("gcm(aes)", 0, 0);
2323+
*aead = crypto_alloc_aead(cipher_name, 0, 0);
22892324
if (IS_ERR(*aead)) {
22902325
rc = PTR_ERR(*aead);
22912326
*aead = NULL;

0 commit comments

Comments
 (0)