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

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
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -179,7 +179,10 @@ struct chtls_hws {
	u32 copied_seq;
	u64 tx_seq_no;
	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 {
@@ -482,7 +485,7 @@ int send_tx_flowc_wr(struct sock *sk, int compl,
void chtls_tcp_push(struct sock *sk, int flags);
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_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);
unsigned int keyid_to_addr(int start_addr, int keyid);
void free_tls_keyid(struct sock *sk);
+44 −18
Original line number Diff line number Diff line
@@ -208,28 +208,53 @@ static void chtls_rxkey_ivauth(struct _key_ctx *kctx)

static int chtls_key_info(struct chtls_sock *csk,
			  struct _key_ctx *kctx,
			  u32 keylen, u32 optname)
			  u32 keylen, u32 optname,
			  int cipher_type)
{
	unsigned char key[AES_KEYSIZE_128];
	struct tls12_crypto_info_aes_gcm_128 *gcm_ctx;
	unsigned char key[AES_MAX_KEY_SIZE];
	unsigned char *key_p, *salt;
	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;
	int ret;

	gcm_ctx = (struct tls12_crypto_info_aes_gcm_128 *)
		  &csk->tlshws.crypto_info;

	key_ctx_size = sizeof(struct _key_ctx) +
		       roundup(keylen, 16) + AEAD_H_SIZE;

	if (keylen == AES_KEYSIZE_128) {
	/* GCM mode of AES supports 128 and 256 bit encryption, so
	 * prepare key context base on GCM cipher type
	 */
	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;
	} else {
		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);
		return -EINVAL;
	}
	memcpy(key, gcm_ctx->key, keylen);

	/* Calculate the H = CIPH(K, 0 repeated 16 times).
	 * It will go in key context
@@ -249,20 +274,20 @@ static int chtls_key_info(struct chtls_sock *csk,

		key_ctx = ((key_ctx_size >> 4) << 3);
		kctx->ctx_hdr = FILL_KEY_CRX_HDR(ck_size,
						 CHCR_KEYCTX_MAC_KEY_SIZE_128,
						 kctx_mackey_size,
						 0, 0, key_ctx);
		chtls_rxkey_ivauth(kctx);
	} else {
		kctx->ctx_hdr = FILL_KEY_CTX_HDR(ck_size,
						 CHCR_KEYCTX_MAC_KEY_SIZE_128,
						 kctx_mackey_size,
						 0, 0, key_ctx_size >> 4);
	}

	memcpy(kctx->salt, gcm_ctx->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
	memcpy(kctx->key, gcm_ctx->key, keylen);
	memcpy(kctx->salt, salt, salt_size);
	memcpy(kctx->key, key_p, keylen);
	memcpy(kctx->key + keylen, ghash_h, AEAD_H_SIZE);
	/* erase key info from driver */
	memset(gcm_ctx->key, 0, keylen);
	memset(key_p, 0, keylen);

	return 0;
}
@@ -288,7 +313,8 @@ static void chtls_set_scmd(struct chtls_sock *csk)
		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 chtls_dev *cdev;
@@ -352,7 +378,7 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 optname)

	/* key info */
	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)
		goto out_notcb;

+22 −1
Original line number Diff line number Diff line
@@ -486,6 +486,7 @@ static int do_chtls_setsockopt(struct sock *sk, int optname,
	struct tls_crypto_info *crypto_info, tmp_crypto_info;
	struct chtls_sock *csk;
	int keylen;
	int cipher_type;
	int rc = 0;

	csk = rcu_dereference_sk_user_data(sk);
@@ -509,6 +510,9 @@ static int do_chtls_setsockopt(struct sock *sk, int optname,

	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) {
	case TLS_CIPHER_AES_GCM_128: {
		/* Obtain version and type from previous copy */
@@ -525,13 +529,30 @@ static int do_chtls_setsockopt(struct sock *sk, int optname,
		}

		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;
	}
	default:
		rc = -EINVAL;
		goto out;
	}
	rc = chtls_setkey(csk, keylen, optname, cipher_type);
out:
	return rc;
}