Commit 596d0a28 authored by Vinay Kumar Yadav's avatar Vinay Kumar Yadav Committed by Herbert Xu

crypto: chtls - Add support for AES256-GCM based ciphers

Added support to set 256 bit key to the hardware from
setsockopt for AES256-GCM based ciphers.
Signed-off-by: default avatarVinay Kumar Yadav <vinay.yadav@chelsio.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 112e7b7b
...@@ -179,7 +179,10 @@ struct chtls_hws { ...@@ -179,7 +179,10 @@ struct chtls_hws {
u32 copied_seq; u32 copied_seq;
u64 tx_seq_no; u64 tx_seq_no;
struct tls_scmd scmd; struct tls_scmd scmd;
struct tls12_crypto_info_aes_gcm_128 crypto_info; union {
struct tls12_crypto_info_aes_gcm_128 aes_gcm_128;
struct tls12_crypto_info_aes_gcm_256 aes_gcm_256;
} crypto_info;
}; };
struct chtls_sock { struct chtls_sock {
...@@ -482,7 +485,7 @@ int send_tx_flowc_wr(struct sock *sk, int compl, ...@@ -482,7 +485,7 @@ int send_tx_flowc_wr(struct sock *sk, int compl,
void chtls_tcp_push(struct sock *sk, int flags); void chtls_tcp_push(struct sock *sk, int flags);
int chtls_push_frames(struct chtls_sock *csk, int comp); int chtls_push_frames(struct chtls_sock *csk, int comp);
int chtls_set_tcb_tflag(struct sock *sk, unsigned int bit_pos, int val); int chtls_set_tcb_tflag(struct sock *sk, unsigned int bit_pos, int val);
int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 mode); int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 mode, int cipher_type);
void skb_entail(struct sock *sk, struct sk_buff *skb, int flags); void skb_entail(struct sock *sk, struct sk_buff *skb, int flags);
unsigned int keyid_to_addr(int start_addr, int keyid); unsigned int keyid_to_addr(int start_addr, int keyid);
void free_tls_keyid(struct sock *sk); void free_tls_keyid(struct sock *sk);
......
...@@ -208,28 +208,53 @@ static void chtls_rxkey_ivauth(struct _key_ctx *kctx) ...@@ -208,28 +208,53 @@ static void chtls_rxkey_ivauth(struct _key_ctx *kctx)
static int chtls_key_info(struct chtls_sock *csk, static int chtls_key_info(struct chtls_sock *csk,
struct _key_ctx *kctx, struct _key_ctx *kctx,
u32 keylen, u32 optname) u32 keylen, u32 optname,
int cipher_type)
{ {
unsigned char key[AES_KEYSIZE_128]; unsigned char key[AES_MAX_KEY_SIZE];
struct tls12_crypto_info_aes_gcm_128 *gcm_ctx; unsigned char *key_p, *salt;
unsigned char ghash_h[AEAD_H_SIZE]; unsigned char ghash_h[AEAD_H_SIZE];
int ck_size, key_ctx_size; int ck_size, key_ctx_size, kctx_mackey_size, salt_size;
struct crypto_aes_ctx aes; struct crypto_aes_ctx aes;
int ret; int ret;
gcm_ctx = (struct tls12_crypto_info_aes_gcm_128 *)
&csk->tlshws.crypto_info;
key_ctx_size = sizeof(struct _key_ctx) + key_ctx_size = sizeof(struct _key_ctx) +
roundup(keylen, 16) + AEAD_H_SIZE; roundup(keylen, 16) + AEAD_H_SIZE;
if (keylen == AES_KEYSIZE_128) { /* GCM mode of AES supports 128 and 256 bit encryption, so
ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; * prepare key context base on GCM cipher type
} else { */
switch (cipher_type) {
case TLS_CIPHER_AES_GCM_128: {
struct tls12_crypto_info_aes_gcm_128 *gcm_ctx_128 =
(struct tls12_crypto_info_aes_gcm_128 *)
&csk->tlshws.crypto_info;
memcpy(key, gcm_ctx_128->key, keylen);
key_p = gcm_ctx_128->key;
salt = gcm_ctx_128->salt;
ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
salt_size = TLS_CIPHER_AES_GCM_128_SALT_SIZE;
kctx_mackey_size = CHCR_KEYCTX_MAC_KEY_SIZE_128;
break;
}
case TLS_CIPHER_AES_GCM_256: {
struct tls12_crypto_info_aes_gcm_256 *gcm_ctx_256 =
(struct tls12_crypto_info_aes_gcm_256 *)
&csk->tlshws.crypto_info;
memcpy(key, gcm_ctx_256->key, keylen);
key_p = gcm_ctx_256->key;
salt = gcm_ctx_256->salt;
ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
salt_size = TLS_CIPHER_AES_GCM_256_SALT_SIZE;
kctx_mackey_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
break;
}
default:
pr_err("GCM: Invalid key length %d\n", keylen); pr_err("GCM: Invalid key length %d\n", keylen);
return -EINVAL; return -EINVAL;
} }
memcpy(key, gcm_ctx->key, keylen);
/* Calculate the H = CIPH(K, 0 repeated 16 times). /* Calculate the H = CIPH(K, 0 repeated 16 times).
* It will go in key context * It will go in key context
...@@ -249,20 +274,20 @@ static int chtls_key_info(struct chtls_sock *csk, ...@@ -249,20 +274,20 @@ static int chtls_key_info(struct chtls_sock *csk,
key_ctx = ((key_ctx_size >> 4) << 3); key_ctx = ((key_ctx_size >> 4) << 3);
kctx->ctx_hdr = FILL_KEY_CRX_HDR(ck_size, kctx->ctx_hdr = FILL_KEY_CRX_HDR(ck_size,
CHCR_KEYCTX_MAC_KEY_SIZE_128, kctx_mackey_size,
0, 0, key_ctx); 0, 0, key_ctx);
chtls_rxkey_ivauth(kctx); chtls_rxkey_ivauth(kctx);
} else { } else {
kctx->ctx_hdr = FILL_KEY_CTX_HDR(ck_size, kctx->ctx_hdr = FILL_KEY_CTX_HDR(ck_size,
CHCR_KEYCTX_MAC_KEY_SIZE_128, kctx_mackey_size,
0, 0, key_ctx_size >> 4); 0, 0, key_ctx_size >> 4);
} }
memcpy(kctx->salt, gcm_ctx->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE); memcpy(kctx->salt, salt, salt_size);
memcpy(kctx->key, gcm_ctx->key, keylen); memcpy(kctx->key, key_p, keylen);
memcpy(kctx->key + keylen, ghash_h, AEAD_H_SIZE); memcpy(kctx->key + keylen, ghash_h, AEAD_H_SIZE);
/* erase key info from driver */ /* erase key info from driver */
memset(gcm_ctx->key, 0, keylen); memset(key_p, 0, keylen);
return 0; return 0;
} }
...@@ -288,7 +313,8 @@ static void chtls_set_scmd(struct chtls_sock *csk) ...@@ -288,7 +313,8 @@ static void chtls_set_scmd(struct chtls_sock *csk)
SCMD_TLS_FRAG_ENABLE_V(1); SCMD_TLS_FRAG_ENABLE_V(1);
} }
int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 optname) int chtls_setkey(struct chtls_sock *csk, u32 keylen,
u32 optname, int cipher_type)
{ {
struct tls_key_req *kwr; struct tls_key_req *kwr;
struct chtls_dev *cdev; struct chtls_dev *cdev;
...@@ -352,7 +378,7 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 optname) ...@@ -352,7 +378,7 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 optname)
/* key info */ /* key info */
kctx = (struct _key_ctx *)(kwr + 1); kctx = (struct _key_ctx *)(kwr + 1);
ret = chtls_key_info(csk, kctx, keylen, optname); ret = chtls_key_info(csk, kctx, keylen, optname, cipher_type);
if (ret) if (ret)
goto out_notcb; goto out_notcb;
......
...@@ -486,6 +486,7 @@ static int do_chtls_setsockopt(struct sock *sk, int optname, ...@@ -486,6 +486,7 @@ static int do_chtls_setsockopt(struct sock *sk, int optname,
struct tls_crypto_info *crypto_info, tmp_crypto_info; struct tls_crypto_info *crypto_info, tmp_crypto_info;
struct chtls_sock *csk; struct chtls_sock *csk;
int keylen; int keylen;
int cipher_type;
int rc = 0; int rc = 0;
csk = rcu_dereference_sk_user_data(sk); csk = rcu_dereference_sk_user_data(sk);
...@@ -509,6 +510,9 @@ static int do_chtls_setsockopt(struct sock *sk, int optname, ...@@ -509,6 +510,9 @@ static int do_chtls_setsockopt(struct sock *sk, int optname,
crypto_info = (struct tls_crypto_info *)&csk->tlshws.crypto_info; crypto_info = (struct tls_crypto_info *)&csk->tlshws.crypto_info;
/* GCM mode of AES supports 128 and 256 bit encryption, so
* copy keys from user based on GCM cipher type.
*/
switch (tmp_crypto_info.cipher_type) { switch (tmp_crypto_info.cipher_type) {
case TLS_CIPHER_AES_GCM_128: { case TLS_CIPHER_AES_GCM_128: {
/* Obtain version and type from previous copy */ /* Obtain version and type from previous copy */
...@@ -525,13 +529,30 @@ static int do_chtls_setsockopt(struct sock *sk, int optname, ...@@ -525,13 +529,30 @@ static int do_chtls_setsockopt(struct sock *sk, int optname,
} }
keylen = TLS_CIPHER_AES_GCM_128_KEY_SIZE; keylen = TLS_CIPHER_AES_GCM_128_KEY_SIZE;
rc = chtls_setkey(csk, keylen, optname); cipher_type = TLS_CIPHER_AES_GCM_128;
break;
}
case TLS_CIPHER_AES_GCM_256: {
crypto_info[0] = tmp_crypto_info;
rc = copy_from_user((char *)crypto_info + sizeof(*crypto_info),
optval + sizeof(*crypto_info),
sizeof(struct tls12_crypto_info_aes_gcm_256)
- sizeof(*crypto_info));
if (rc) {
rc = -EFAULT;
goto out;
}
keylen = TLS_CIPHER_AES_GCM_256_KEY_SIZE;
cipher_type = TLS_CIPHER_AES_GCM_256;
break; break;
} }
default: default:
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
rc = chtls_setkey(csk, keylen, optname, cipher_type);
out: out:
return rc; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment