1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2*73f04d3dSAditya Srivastava /*
3049359d6SJames Hsiao  * AMCC SoC PPC4xx Crypto Driver
4049359d6SJames Hsiao  *
5049359d6SJames Hsiao  * Copyright (c) 2008 Applied Micro Circuits Corporation.
6049359d6SJames Hsiao  * All rights reserved. James Hsiao <jhsiao@amcc.com>
7049359d6SJames Hsiao  *
8049359d6SJames Hsiao  * This file implements the Linux crypto algorithms.
9049359d6SJames Hsiao  */
10049359d6SJames Hsiao 
11049359d6SJames Hsiao #include <linux/kernel.h>
12049359d6SJames Hsiao #include <linux/interrupt.h>
13049359d6SJames Hsiao #include <linux/spinlock_types.h>
14049359d6SJames Hsiao #include <linux/scatterlist.h>
15049359d6SJames Hsiao #include <linux/crypto.h>
16049359d6SJames Hsiao #include <linux/hash.h>
17049359d6SJames Hsiao #include <crypto/internal/hash.h>
18049359d6SJames Hsiao #include <linux/dma-mapping.h>
19049359d6SJames Hsiao #include <crypto/algapi.h>
20a0aae821SChristian Lamparter #include <crypto/aead.h>
21049359d6SJames Hsiao #include <crypto/aes.h>
2259231368SChristian Lamparter #include <crypto/gcm.h>
23a24d22b2SEric Biggers #include <crypto/sha1.h>
24f2a13e7cSChristian Lamparter #include <crypto/ctr.h>
25ce05ffe1SChristian Lamparter #include <crypto/skcipher.h>
26049359d6SJames Hsiao #include "crypto4xx_reg_def.h"
27049359d6SJames Hsiao #include "crypto4xx_core.h"
28249c8d98SChristian Lamparter #include "crypto4xx_sa.h"
29049359d6SJames Hsiao 
set_dynamic_sa_command_0(struct dynamic_sa_ctl * sa,u32 save_h,u32 save_iv,u32 ld_h,u32 ld_iv,u32 hdr_proc,u32 h,u32 c,u32 pad_type,u32 op_grp,u32 op,u32 dir)303a4eac79SJingoo Han static void set_dynamic_sa_command_0(struct dynamic_sa_ctl *sa, u32 save_h,
313a4eac79SJingoo Han 				     u32 save_iv, u32 ld_h, u32 ld_iv,
323a4eac79SJingoo Han 				     u32 hdr_proc, u32 h, u32 c, u32 pad_type,
333a4eac79SJingoo Han 				     u32 op_grp, u32 op, u32 dir)
34049359d6SJames Hsiao {
35049359d6SJames Hsiao 	sa->sa_command_0.w = 0;
36049359d6SJames Hsiao 	sa->sa_command_0.bf.save_hash_state = save_h;
37049359d6SJames Hsiao 	sa->sa_command_0.bf.save_iv = save_iv;
38049359d6SJames Hsiao 	sa->sa_command_0.bf.load_hash_state = ld_h;
39049359d6SJames Hsiao 	sa->sa_command_0.bf.load_iv = ld_iv;
40049359d6SJames Hsiao 	sa->sa_command_0.bf.hdr_proc = hdr_proc;
41049359d6SJames Hsiao 	sa->sa_command_0.bf.hash_alg = h;
42049359d6SJames Hsiao 	sa->sa_command_0.bf.cipher_alg = c;
43049359d6SJames Hsiao 	sa->sa_command_0.bf.pad_type = pad_type & 3;
44049359d6SJames Hsiao 	sa->sa_command_0.bf.extend_pad = pad_type >> 2;
45049359d6SJames Hsiao 	sa->sa_command_0.bf.op_group = op_grp;
46049359d6SJames Hsiao 	sa->sa_command_0.bf.opcode = op;
47049359d6SJames Hsiao 	sa->sa_command_0.bf.dir = dir;
48049359d6SJames Hsiao }
49049359d6SJames Hsiao 
set_dynamic_sa_command_1(struct dynamic_sa_ctl * sa,u32 cm,u32 hmac_mc,u32 cfb,u32 esn,u32 sn_mask,u32 mute,u32 cp_pad,u32 cp_pay,u32 cp_hdr)503a4eac79SJingoo Han static void set_dynamic_sa_command_1(struct dynamic_sa_ctl *sa, u32 cm,
513a4eac79SJingoo Han 				     u32 hmac_mc, u32 cfb, u32 esn,
523a4eac79SJingoo Han 				     u32 sn_mask, u32 mute, u32 cp_pad,
533a4eac79SJingoo Han 				     u32 cp_pay, u32 cp_hdr)
54049359d6SJames Hsiao {
55049359d6SJames Hsiao 	sa->sa_command_1.w = 0;
56049359d6SJames Hsiao 	sa->sa_command_1.bf.crypto_mode31 = (cm & 4) >> 2;
57049359d6SJames Hsiao 	sa->sa_command_1.bf.crypto_mode9_8 = cm & 3;
5877450fd7SJulia Lawall 	sa->sa_command_1.bf.feedback_mode = cfb;
59049359d6SJames Hsiao 	sa->sa_command_1.bf.sa_rev = 1;
605a4326d3SChristian Lamparter 	sa->sa_command_1.bf.hmac_muting = hmac_mc;
61049359d6SJames Hsiao 	sa->sa_command_1.bf.extended_seq_num = esn;
62049359d6SJames Hsiao 	sa->sa_command_1.bf.seq_num_mask = sn_mask;
63049359d6SJames Hsiao 	sa->sa_command_1.bf.mutable_bit_proc = mute;
64049359d6SJames Hsiao 	sa->sa_command_1.bf.copy_pad = cp_pad;
65049359d6SJames Hsiao 	sa->sa_command_1.bf.copy_payload = cp_pay;
66049359d6SJames Hsiao 	sa->sa_command_1.bf.copy_hdr = cp_hdr;
67049359d6SJames Hsiao }
68049359d6SJames Hsiao 
crypto4xx_crypt(struct skcipher_request * req,const unsigned int ivlen,bool decrypt,bool check_blocksize)69ce05ffe1SChristian Lamparter static inline int crypto4xx_crypt(struct skcipher_request *req,
700f7a8137SChristian Lamparter 				  const unsigned int ivlen, bool decrypt,
710f7a8137SChristian Lamparter 				  bool check_blocksize)
72049359d6SJames Hsiao {
73ce05ffe1SChristian Lamparter 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
74ce05ffe1SChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
75c4e90650SChristian Lamparter 	__le32 iv[AES_IV_SIZE];
76049359d6SJames Hsiao 
770f7a8137SChristian Lamparter 	if (check_blocksize && !IS_ALIGNED(req->cryptlen, AES_BLOCK_SIZE))
780f7a8137SChristian Lamparter 		return -EINVAL;
790f7a8137SChristian Lamparter 
80cd4dcd6dSChristian Lamparter 	if (ivlen)
81ce05ffe1SChristian Lamparter 		crypto4xx_memcpy_to_le32(iv, req->iv, ivlen);
82049359d6SJames Hsiao 
83049359d6SJames Hsiao 	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
84ce05ffe1SChristian Lamparter 		req->cryptlen, iv, ivlen, decrypt ? ctx->sa_in : ctx->sa_out,
85658c9d2bSChristian Lamparter 		ctx->sa_len, 0, NULL);
86049359d6SJames Hsiao }
87049359d6SJames Hsiao 
crypto4xx_encrypt_noiv_block(struct skcipher_request * req)880f7a8137SChristian Lamparter int crypto4xx_encrypt_noiv_block(struct skcipher_request *req)
89049359d6SJames Hsiao {
900f7a8137SChristian Lamparter 	return crypto4xx_crypt(req, 0, false, true);
91a8d79d7bSChristian Lamparter }
92049359d6SJames Hsiao 
crypto4xx_encrypt_iv_stream(struct skcipher_request * req)930f7a8137SChristian Lamparter int crypto4xx_encrypt_iv_stream(struct skcipher_request *req)
94a8d79d7bSChristian Lamparter {
950f7a8137SChristian Lamparter 	return crypto4xx_crypt(req, AES_IV_SIZE, false, false);
96a8d79d7bSChristian Lamparter }
97049359d6SJames Hsiao 
crypto4xx_decrypt_noiv_block(struct skcipher_request * req)980f7a8137SChristian Lamparter int crypto4xx_decrypt_noiv_block(struct skcipher_request *req)
99a8d79d7bSChristian Lamparter {
1000f7a8137SChristian Lamparter 	return crypto4xx_crypt(req, 0, true, true);
101a8d79d7bSChristian Lamparter }
102a8d79d7bSChristian Lamparter 
crypto4xx_decrypt_iv_stream(struct skcipher_request * req)1030f7a8137SChristian Lamparter int crypto4xx_decrypt_iv_stream(struct skcipher_request *req)
104a8d79d7bSChristian Lamparter {
1050f7a8137SChristian Lamparter 	return crypto4xx_crypt(req, AES_IV_SIZE, true, false);
1060f7a8137SChristian Lamparter }
1070f7a8137SChristian Lamparter 
crypto4xx_encrypt_iv_block(struct skcipher_request * req)1080f7a8137SChristian Lamparter int crypto4xx_encrypt_iv_block(struct skcipher_request *req)
1090f7a8137SChristian Lamparter {
1100f7a8137SChristian Lamparter 	return crypto4xx_crypt(req, AES_IV_SIZE, false, true);
1110f7a8137SChristian Lamparter }
1120f7a8137SChristian Lamparter 
crypto4xx_decrypt_iv_block(struct skcipher_request * req)1130f7a8137SChristian Lamparter int crypto4xx_decrypt_iv_block(struct skcipher_request *req)
1140f7a8137SChristian Lamparter {
1150f7a8137SChristian Lamparter 	return crypto4xx_crypt(req, AES_IV_SIZE, true, true);
116049359d6SJames Hsiao }
117049359d6SJames Hsiao 
118*73f04d3dSAditya Srivastava /*
119049359d6SJames Hsiao  * AES Functions
120049359d6SJames Hsiao  */
crypto4xx_setkey_aes(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen,unsigned char cm,u8 fb)121ce05ffe1SChristian Lamparter static int crypto4xx_setkey_aes(struct crypto_skcipher *cipher,
122049359d6SJames Hsiao 				const u8 *key,
123049359d6SJames Hsiao 				unsigned int keylen,
124049359d6SJames Hsiao 				unsigned char cm,
125049359d6SJames Hsiao 				u8 fb)
126049359d6SJames Hsiao {
127ce05ffe1SChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
128049359d6SJames Hsiao 	struct dynamic_sa_ctl *sa;
129049359d6SJames Hsiao 	int    rc;
130049359d6SJames Hsiao 
131674f368aSEric Biggers 	if (keylen != AES_KEYSIZE_256 && keylen != AES_KEYSIZE_192 &&
132674f368aSEric Biggers 	    keylen != AES_KEYSIZE_128)
133049359d6SJames Hsiao 		return -EINVAL;
134049359d6SJames Hsiao 
135049359d6SJames Hsiao 	/* Create SA */
1362f77690dSChristian Lamparter 	if (ctx->sa_in || ctx->sa_out)
137049359d6SJames Hsiao 		crypto4xx_free_sa(ctx);
138049359d6SJames Hsiao 
139049359d6SJames Hsiao 	rc = crypto4xx_alloc_sa(ctx, SA_AES128_LEN + (keylen-16) / 4);
140049359d6SJames Hsiao 	if (rc)
141049359d6SJames Hsiao 		return rc;
142049359d6SJames Hsiao 
143049359d6SJames Hsiao 	/* Setup SA */
1449e0a0b3aSChristian Lamparter 	sa = ctx->sa_in;
145049359d6SJames Hsiao 
14625baaf8eSChristian Lamparter 	set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, (cm == CRYPTO_MODE_ECB ?
14725baaf8eSChristian Lamparter 				 SA_NOT_SAVE_IV : SA_SAVE_IV),
14825baaf8eSChristian Lamparter 				 SA_NOT_LOAD_HASH, (cm == CRYPTO_MODE_ECB ?
14925baaf8eSChristian Lamparter 				 SA_LOAD_IV_FROM_SA : SA_LOAD_IV_FROM_STATE),
150049359d6SJames Hsiao 				 SA_NO_HEADER_PROC, SA_HASH_ALG_NULL,
151049359d6SJames Hsiao 				 SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO,
152049359d6SJames Hsiao 				 SA_OP_GROUP_BASIC, SA_OPCODE_DECRYPT,
153049359d6SJames Hsiao 				 DIR_INBOUND);
154049359d6SJames Hsiao 
155049359d6SJames Hsiao 	set_dynamic_sa_command_1(sa, cm, SA_HASH_MODE_HASH,
156049359d6SJames Hsiao 				 fb, SA_EXTENDED_SN_OFF,
157049359d6SJames Hsiao 				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
158049359d6SJames Hsiao 				 SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
159049359d6SJames Hsiao 				 SA_NOT_COPY_HDR);
1604865b122SChristian Lamparter 	crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa),
161049359d6SJames Hsiao 				 key, keylen);
162453e3090SChristian Lamparter 	sa->sa_contents.w = SA_AES_CONTENTS | (keylen << 2);
163049359d6SJames Hsiao 	sa->sa_command_1.bf.key_len = keylen >> 3;
164049359d6SJames Hsiao 
165049359d6SJames Hsiao 	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
1669e0a0b3aSChristian Lamparter 	sa = ctx->sa_out;
167049359d6SJames Hsiao 	sa->sa_command_0.bf.dir = DIR_OUTBOUND;
16825baaf8eSChristian Lamparter 	/*
16925baaf8eSChristian Lamparter 	 * SA_OPCODE_ENCRYPT is the same value as SA_OPCODE_DECRYPT.
17025baaf8eSChristian Lamparter 	 * it's the DIR_(IN|OUT)BOUND that matters
17125baaf8eSChristian Lamparter 	 */
17225baaf8eSChristian Lamparter 	sa->sa_command_0.bf.opcode = SA_OPCODE_ENCRYPT;
173049359d6SJames Hsiao 
174049359d6SJames Hsiao 	return 0;
175049359d6SJames Hsiao }
176049359d6SJames Hsiao 
crypto4xx_setkey_aes_cbc(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)177ce05ffe1SChristian Lamparter int crypto4xx_setkey_aes_cbc(struct crypto_skcipher *cipher,
178049359d6SJames Hsiao 			     const u8 *key, unsigned int keylen)
179049359d6SJames Hsiao {
180049359d6SJames Hsiao 	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_CBC,
181049359d6SJames Hsiao 				    CRYPTO_FEEDBACK_MODE_NO_FB);
182049359d6SJames Hsiao }
183049359d6SJames Hsiao 
crypto4xx_setkey_aes_cfb(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)184ce05ffe1SChristian Lamparter int crypto4xx_setkey_aes_cfb(struct crypto_skcipher *cipher,
185f2a13e7cSChristian Lamparter 			     const u8 *key, unsigned int keylen)
186f2a13e7cSChristian Lamparter {
187f2a13e7cSChristian Lamparter 	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_CFB,
188f2a13e7cSChristian Lamparter 				    CRYPTO_FEEDBACK_MODE_128BIT_CFB);
189f2a13e7cSChristian Lamparter }
190f2a13e7cSChristian Lamparter 
crypto4xx_setkey_aes_ecb(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)191ce05ffe1SChristian Lamparter int crypto4xx_setkey_aes_ecb(struct crypto_skcipher *cipher,
192f2a13e7cSChristian Lamparter 			     const u8 *key, unsigned int keylen)
193f2a13e7cSChristian Lamparter {
194f2a13e7cSChristian Lamparter 	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_ECB,
195f2a13e7cSChristian Lamparter 				    CRYPTO_FEEDBACK_MODE_NO_FB);
196f2a13e7cSChristian Lamparter }
197f2a13e7cSChristian Lamparter 
crypto4xx_setkey_aes_ofb(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)198ce05ffe1SChristian Lamparter int crypto4xx_setkey_aes_ofb(struct crypto_skcipher *cipher,
199f2a13e7cSChristian Lamparter 			     const u8 *key, unsigned int keylen)
200f2a13e7cSChristian Lamparter {
201f2a13e7cSChristian Lamparter 	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_OFB,
202f2a13e7cSChristian Lamparter 				    CRYPTO_FEEDBACK_MODE_64BIT_OFB);
203f2a13e7cSChristian Lamparter }
204f2a13e7cSChristian Lamparter 
crypto4xx_setkey_rfc3686(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)205ce05ffe1SChristian Lamparter int crypto4xx_setkey_rfc3686(struct crypto_skcipher *cipher,
206f2a13e7cSChristian Lamparter 			     const u8 *key, unsigned int keylen)
207f2a13e7cSChristian Lamparter {
208ce05ffe1SChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
209f2a13e7cSChristian Lamparter 	int rc;
210f2a13e7cSChristian Lamparter 
211f2a13e7cSChristian Lamparter 	rc = crypto4xx_setkey_aes(cipher, key, keylen - CTR_RFC3686_NONCE_SIZE,
212f2a13e7cSChristian Lamparter 		CRYPTO_MODE_CTR, CRYPTO_FEEDBACK_MODE_NO_FB);
213f2a13e7cSChristian Lamparter 	if (rc)
214f2a13e7cSChristian Lamparter 		return rc;
215f2a13e7cSChristian Lamparter 
2162f77690dSChristian Lamparter 	ctx->iv_nonce = cpu_to_le32p((u32 *)&key[keylen -
2172f77690dSChristian Lamparter 						 CTR_RFC3686_NONCE_SIZE]);
218f2a13e7cSChristian Lamparter 
219f2a13e7cSChristian Lamparter 	return 0;
220f2a13e7cSChristian Lamparter }
221f2a13e7cSChristian Lamparter 
crypto4xx_rfc3686_encrypt(struct skcipher_request * req)222ce05ffe1SChristian Lamparter int crypto4xx_rfc3686_encrypt(struct skcipher_request *req)
223f2a13e7cSChristian Lamparter {
224ce05ffe1SChristian Lamparter 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
225ce05ffe1SChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
226cd4dcd6dSChristian Lamparter 	__le32 iv[AES_IV_SIZE / 4] = {
2272f77690dSChristian Lamparter 		ctx->iv_nonce,
228ce05ffe1SChristian Lamparter 		cpu_to_le32p((u32 *) req->iv),
229ce05ffe1SChristian Lamparter 		cpu_to_le32p((u32 *) (req->iv + 4)),
230cd4dcd6dSChristian Lamparter 		cpu_to_le32(1) };
231f2a13e7cSChristian Lamparter 
232f2a13e7cSChristian Lamparter 	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
233ce05ffe1SChristian Lamparter 				  req->cryptlen, iv, AES_IV_SIZE,
234658c9d2bSChristian Lamparter 				  ctx->sa_out, ctx->sa_len, 0, NULL);
235f2a13e7cSChristian Lamparter }
236f2a13e7cSChristian Lamparter 
crypto4xx_rfc3686_decrypt(struct skcipher_request * req)237ce05ffe1SChristian Lamparter int crypto4xx_rfc3686_decrypt(struct skcipher_request *req)
238f2a13e7cSChristian Lamparter {
239ce05ffe1SChristian Lamparter 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
240ce05ffe1SChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
241cd4dcd6dSChristian Lamparter 	__le32 iv[AES_IV_SIZE / 4] = {
2422f77690dSChristian Lamparter 		ctx->iv_nonce,
243ce05ffe1SChristian Lamparter 		cpu_to_le32p((u32 *) req->iv),
244ce05ffe1SChristian Lamparter 		cpu_to_le32p((u32 *) (req->iv + 4)),
245cd4dcd6dSChristian Lamparter 		cpu_to_le32(1) };
246f2a13e7cSChristian Lamparter 
247f2a13e7cSChristian Lamparter 	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
248ce05ffe1SChristian Lamparter 				  req->cryptlen, iv, AES_IV_SIZE,
249658c9d2bSChristian Lamparter 				  ctx->sa_out, ctx->sa_len, 0, NULL);
250f2a13e7cSChristian Lamparter }
251f2a13e7cSChristian Lamparter 
25298e87e3dSChristian Lamparter static int
crypto4xx_ctr_crypt(struct skcipher_request * req,bool encrypt)25398e87e3dSChristian Lamparter crypto4xx_ctr_crypt(struct skcipher_request *req, bool encrypt)
25498e87e3dSChristian Lamparter {
25598e87e3dSChristian Lamparter 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
25698e87e3dSChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
25798e87e3dSChristian Lamparter 	size_t iv_len = crypto_skcipher_ivsize(cipher);
25898e87e3dSChristian Lamparter 	unsigned int counter = be32_to_cpup((__be32 *)(req->iv + iv_len - 4));
25998e87e3dSChristian Lamparter 	unsigned int nblks = ALIGN(req->cryptlen, AES_BLOCK_SIZE) /
26098e87e3dSChristian Lamparter 			AES_BLOCK_SIZE;
26198e87e3dSChristian Lamparter 
26298e87e3dSChristian Lamparter 	/*
26398e87e3dSChristian Lamparter 	 * The hardware uses only the last 32-bits as the counter while the
26498e87e3dSChristian Lamparter 	 * kernel tests (aes_ctr_enc_tv_template[4] for example) expect that
26598e87e3dSChristian Lamparter 	 * the whole IV is a counter.  So fallback if the counter is going to
26698e87e3dSChristian Lamparter 	 * overlow.
26798e87e3dSChristian Lamparter 	 */
26898e87e3dSChristian Lamparter 	if (counter + nblks < counter) {
2699848e4c8SChristian Lamparter 		SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->sw_cipher.cipher);
27098e87e3dSChristian Lamparter 		int ret;
27198e87e3dSChristian Lamparter 
2729848e4c8SChristian Lamparter 		skcipher_request_set_sync_tfm(subreq, ctx->sw_cipher.cipher);
27398e87e3dSChristian Lamparter 		skcipher_request_set_callback(subreq, req->base.flags,
27498e87e3dSChristian Lamparter 			NULL, NULL);
27598e87e3dSChristian Lamparter 		skcipher_request_set_crypt(subreq, req->src, req->dst,
27698e87e3dSChristian Lamparter 			req->cryptlen, req->iv);
27798e87e3dSChristian Lamparter 		ret = encrypt ? crypto_skcipher_encrypt(subreq)
27898e87e3dSChristian Lamparter 			: crypto_skcipher_decrypt(subreq);
27998e87e3dSChristian Lamparter 		skcipher_request_zero(subreq);
28098e87e3dSChristian Lamparter 		return ret;
28198e87e3dSChristian Lamparter 	}
28298e87e3dSChristian Lamparter 
2830f7a8137SChristian Lamparter 	return encrypt ? crypto4xx_encrypt_iv_stream(req)
2840f7a8137SChristian Lamparter 		       : crypto4xx_decrypt_iv_stream(req);
28598e87e3dSChristian Lamparter }
28698e87e3dSChristian Lamparter 
crypto4xx_sk_setup_fallback(struct crypto4xx_ctx * ctx,struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)28798e87e3dSChristian Lamparter static int crypto4xx_sk_setup_fallback(struct crypto4xx_ctx *ctx,
28898e87e3dSChristian Lamparter 				       struct crypto_skcipher *cipher,
28998e87e3dSChristian Lamparter 				       const u8 *key,
29098e87e3dSChristian Lamparter 				       unsigned int keylen)
29198e87e3dSChristian Lamparter {
2929848e4c8SChristian Lamparter 	crypto_sync_skcipher_clear_flags(ctx->sw_cipher.cipher,
29398e87e3dSChristian Lamparter 				    CRYPTO_TFM_REQ_MASK);
2949848e4c8SChristian Lamparter 	crypto_sync_skcipher_set_flags(ctx->sw_cipher.cipher,
29598e87e3dSChristian Lamparter 		crypto_skcipher_get_flags(cipher) & CRYPTO_TFM_REQ_MASK);
296af5034e8SEric Biggers 	return crypto_sync_skcipher_setkey(ctx->sw_cipher.cipher, key, keylen);
29798e87e3dSChristian Lamparter }
29898e87e3dSChristian Lamparter 
crypto4xx_setkey_aes_ctr(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)29998e87e3dSChristian Lamparter int crypto4xx_setkey_aes_ctr(struct crypto_skcipher *cipher,
30098e87e3dSChristian Lamparter 			     const u8 *key, unsigned int keylen)
30198e87e3dSChristian Lamparter {
30298e87e3dSChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
30398e87e3dSChristian Lamparter 	int rc;
30498e87e3dSChristian Lamparter 
30598e87e3dSChristian Lamparter 	rc = crypto4xx_sk_setup_fallback(ctx, cipher, key, keylen);
30698e87e3dSChristian Lamparter 	if (rc)
30798e87e3dSChristian Lamparter 		return rc;
30898e87e3dSChristian Lamparter 
30998e87e3dSChristian Lamparter 	return crypto4xx_setkey_aes(cipher, key, keylen,
31098e87e3dSChristian Lamparter 		CRYPTO_MODE_CTR, CRYPTO_FEEDBACK_MODE_NO_FB);
31198e87e3dSChristian Lamparter }
31298e87e3dSChristian Lamparter 
crypto4xx_encrypt_ctr(struct skcipher_request * req)31398e87e3dSChristian Lamparter int crypto4xx_encrypt_ctr(struct skcipher_request *req)
31498e87e3dSChristian Lamparter {
31598e87e3dSChristian Lamparter 	return crypto4xx_ctr_crypt(req, true);
31698e87e3dSChristian Lamparter }
31798e87e3dSChristian Lamparter 
crypto4xx_decrypt_ctr(struct skcipher_request * req)31898e87e3dSChristian Lamparter int crypto4xx_decrypt_ctr(struct skcipher_request *req)
31998e87e3dSChristian Lamparter {
32098e87e3dSChristian Lamparter 	return crypto4xx_ctr_crypt(req, false);
32198e87e3dSChristian Lamparter }
32298e87e3dSChristian Lamparter 
crypto4xx_aead_need_fallback(struct aead_request * req,unsigned int len,bool is_ccm,bool decrypt)32365ea8b67SChristian Lamparter static inline bool crypto4xx_aead_need_fallback(struct aead_request *req,
324584201f1SChristian Lamparter 						unsigned int len,
32565ea8b67SChristian Lamparter 						bool is_ccm, bool decrypt)
32665ea8b67SChristian Lamparter {
32765ea8b67SChristian Lamparter 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
32865ea8b67SChristian Lamparter 
32965ea8b67SChristian Lamparter 	/* authsize has to be a multiple of 4 */
33065ea8b67SChristian Lamparter 	if (aead->authsize & 3)
33165ea8b67SChristian Lamparter 		return true;
33265ea8b67SChristian Lamparter 
33365ea8b67SChristian Lamparter 	/*
334584201f1SChristian Lamparter 	 * hardware does not handle cases where plaintext
335584201f1SChristian Lamparter 	 * is less than a block.
33665ea8b67SChristian Lamparter 	 */
337584201f1SChristian Lamparter 	if (len < AES_BLOCK_SIZE)
33865ea8b67SChristian Lamparter 		return true;
33965ea8b67SChristian Lamparter 
340584201f1SChristian Lamparter 	/* assoc len needs to be a multiple of 4 and <= 1020 */
341584201f1SChristian Lamparter 	if (req->assoclen & 0x3 || req->assoclen > 1020)
34265ea8b67SChristian Lamparter 		return true;
34365ea8b67SChristian Lamparter 
34465ea8b67SChristian Lamparter 	/* CCM supports only counter field length of 2 and 4 bytes */
34565ea8b67SChristian Lamparter 	if (is_ccm && !(req->iv[0] == 1 || req->iv[0] == 3))
34665ea8b67SChristian Lamparter 		return true;
34765ea8b67SChristian Lamparter 
34865ea8b67SChristian Lamparter 	return false;
34965ea8b67SChristian Lamparter }
35065ea8b67SChristian Lamparter 
crypto4xx_aead_fallback(struct aead_request * req,struct crypto4xx_ctx * ctx,bool do_decrypt)35165ea8b67SChristian Lamparter static int crypto4xx_aead_fallback(struct aead_request *req,
35265ea8b67SChristian Lamparter 	struct crypto4xx_ctx *ctx, bool do_decrypt)
35365ea8b67SChristian Lamparter {
354c4e90650SChristian Lamparter 	struct aead_request *subreq = aead_request_ctx(req);
35565ea8b67SChristian Lamparter 
35665ea8b67SChristian Lamparter 	aead_request_set_tfm(subreq, ctx->sw_cipher.aead);
35765ea8b67SChristian Lamparter 	aead_request_set_callback(subreq, req->base.flags,
35865ea8b67SChristian Lamparter 				  req->base.complete, req->base.data);
35965ea8b67SChristian Lamparter 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
36065ea8b67SChristian Lamparter 			       req->iv);
36165ea8b67SChristian Lamparter 	aead_request_set_ad(subreq, req->assoclen);
36265ea8b67SChristian Lamparter 	return do_decrypt ? crypto_aead_decrypt(subreq) :
36365ea8b67SChristian Lamparter 			    crypto_aead_encrypt(subreq);
36465ea8b67SChristian Lamparter }
36565ea8b67SChristian Lamparter 
crypto4xx_aead_setup_fallback(struct crypto4xx_ctx * ctx,struct crypto_aead * cipher,const u8 * key,unsigned int keylen)36698e87e3dSChristian Lamparter static int crypto4xx_aead_setup_fallback(struct crypto4xx_ctx *ctx,
36765ea8b67SChristian Lamparter 					 struct crypto_aead *cipher,
36865ea8b67SChristian Lamparter 					 const u8 *key,
36965ea8b67SChristian Lamparter 					 unsigned int keylen)
37065ea8b67SChristian Lamparter {
37165ea8b67SChristian Lamparter 	crypto_aead_clear_flags(ctx->sw_cipher.aead, CRYPTO_TFM_REQ_MASK);
37265ea8b67SChristian Lamparter 	crypto_aead_set_flags(ctx->sw_cipher.aead,
37365ea8b67SChristian Lamparter 		crypto_aead_get_flags(cipher) & CRYPTO_TFM_REQ_MASK);
374af5034e8SEric Biggers 	return crypto_aead_setkey(ctx->sw_cipher.aead, key, keylen);
37565ea8b67SChristian Lamparter }
37665ea8b67SChristian Lamparter 
377*73f04d3dSAditya Srivastava /*
37865ea8b67SChristian Lamparter  * AES-CCM Functions
37965ea8b67SChristian Lamparter  */
38065ea8b67SChristian Lamparter 
crypto4xx_setkey_aes_ccm(struct crypto_aead * cipher,const u8 * key,unsigned int keylen)38165ea8b67SChristian Lamparter int crypto4xx_setkey_aes_ccm(struct crypto_aead *cipher, const u8 *key,
38265ea8b67SChristian Lamparter 			     unsigned int keylen)
38365ea8b67SChristian Lamparter {
38465ea8b67SChristian Lamparter 	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
38565ea8b67SChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
38665ea8b67SChristian Lamparter 	struct dynamic_sa_ctl *sa;
38765ea8b67SChristian Lamparter 	int rc = 0;
38865ea8b67SChristian Lamparter 
38998e87e3dSChristian Lamparter 	rc = crypto4xx_aead_setup_fallback(ctx, cipher, key, keylen);
39065ea8b67SChristian Lamparter 	if (rc)
39165ea8b67SChristian Lamparter 		return rc;
39265ea8b67SChristian Lamparter 
39365ea8b67SChristian Lamparter 	if (ctx->sa_in || ctx->sa_out)
39465ea8b67SChristian Lamparter 		crypto4xx_free_sa(ctx);
39565ea8b67SChristian Lamparter 
39665ea8b67SChristian Lamparter 	rc = crypto4xx_alloc_sa(ctx, SA_AES128_CCM_LEN + (keylen - 16) / 4);
39765ea8b67SChristian Lamparter 	if (rc)
39865ea8b67SChristian Lamparter 		return rc;
39965ea8b67SChristian Lamparter 
40065ea8b67SChristian Lamparter 	/* Setup SA */
40165ea8b67SChristian Lamparter 	sa = (struct dynamic_sa_ctl *) ctx->sa_in;
40265ea8b67SChristian Lamparter 	sa->sa_contents.w = SA_AES_CCM_CONTENTS | (keylen << 2);
40365ea8b67SChristian Lamparter 
4040b5a7f71SChristian Lamparter 	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
40565ea8b67SChristian Lamparter 				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
40665ea8b67SChristian Lamparter 				 SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
40765ea8b67SChristian Lamparter 				 SA_CIPHER_ALG_AES,
40865ea8b67SChristian Lamparter 				 SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
40965ea8b67SChristian Lamparter 				 SA_OPCODE_HASH_DECRYPT, DIR_INBOUND);
41065ea8b67SChristian Lamparter 
41165ea8b67SChristian Lamparter 	set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
41265ea8b67SChristian Lamparter 				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
41365ea8b67SChristian Lamparter 				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
41465ea8b67SChristian Lamparter 				 SA_NOT_COPY_PAD, SA_COPY_PAYLOAD,
41565ea8b67SChristian Lamparter 				 SA_NOT_COPY_HDR);
41665ea8b67SChristian Lamparter 
41765ea8b67SChristian Lamparter 	sa->sa_command_1.bf.key_len = keylen >> 3;
41865ea8b67SChristian Lamparter 
41965ea8b67SChristian Lamparter 	crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa), key, keylen);
42065ea8b67SChristian Lamparter 
42165ea8b67SChristian Lamparter 	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
42265ea8b67SChristian Lamparter 	sa = (struct dynamic_sa_ctl *) ctx->sa_out;
42365ea8b67SChristian Lamparter 
42465ea8b67SChristian Lamparter 	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
42565ea8b67SChristian Lamparter 				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
42665ea8b67SChristian Lamparter 				 SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
42765ea8b67SChristian Lamparter 				 SA_CIPHER_ALG_AES,
42865ea8b67SChristian Lamparter 				 SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
42965ea8b67SChristian Lamparter 				 SA_OPCODE_ENCRYPT_HASH, DIR_OUTBOUND);
43065ea8b67SChristian Lamparter 
43165ea8b67SChristian Lamparter 	set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
43265ea8b67SChristian Lamparter 				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
43365ea8b67SChristian Lamparter 				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
43465ea8b67SChristian Lamparter 				 SA_COPY_PAD, SA_COPY_PAYLOAD,
43565ea8b67SChristian Lamparter 				 SA_NOT_COPY_HDR);
43665ea8b67SChristian Lamparter 
43765ea8b67SChristian Lamparter 	sa->sa_command_1.bf.key_len = keylen >> 3;
43865ea8b67SChristian Lamparter 	return 0;
43965ea8b67SChristian Lamparter }
44065ea8b67SChristian Lamparter 
crypto4xx_crypt_aes_ccm(struct aead_request * req,bool decrypt)44165ea8b67SChristian Lamparter static int crypto4xx_crypt_aes_ccm(struct aead_request *req, bool decrypt)
44265ea8b67SChristian Lamparter {
44365ea8b67SChristian Lamparter 	struct crypto4xx_ctx *ctx  = crypto_tfm_ctx(req->base.tfm);
444658c9d2bSChristian Lamparter 	struct crypto4xx_aead_reqctx *rctx = aead_request_ctx(req);
44565ea8b67SChristian Lamparter 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
44665ea8b67SChristian Lamparter 	__le32 iv[16];
447c4e90650SChristian Lamparter 	u32 tmp_sa[SA_AES128_CCM_LEN + 4];
44865ea8b67SChristian Lamparter 	struct dynamic_sa_ctl *sa = (struct dynamic_sa_ctl *)tmp_sa;
449584201f1SChristian Lamparter 	unsigned int len = req->cryptlen;
45065ea8b67SChristian Lamparter 
45165ea8b67SChristian Lamparter 	if (decrypt)
45265ea8b67SChristian Lamparter 		len -= crypto_aead_authsize(aead);
45365ea8b67SChristian Lamparter 
454584201f1SChristian Lamparter 	if (crypto4xx_aead_need_fallback(req, len, true, decrypt))
455584201f1SChristian Lamparter 		return crypto4xx_aead_fallback(req, ctx, decrypt);
456584201f1SChristian Lamparter 
457c4e90650SChristian Lamparter 	memcpy(tmp_sa, decrypt ? ctx->sa_in : ctx->sa_out, ctx->sa_len * 4);
45865ea8b67SChristian Lamparter 	sa->sa_command_0.bf.digest_len = crypto_aead_authsize(aead) >> 2;
45965ea8b67SChristian Lamparter 
46065ea8b67SChristian Lamparter 	if (req->iv[0] == 1) {
46165ea8b67SChristian Lamparter 		/* CRYPTO_MODE_AES_ICM */
46265ea8b67SChristian Lamparter 		sa->sa_command_1.bf.crypto_mode9_8 = 1;
46365ea8b67SChristian Lamparter 	}
46465ea8b67SChristian Lamparter 
46565ea8b67SChristian Lamparter 	iv[3] = cpu_to_le32(0);
46665ea8b67SChristian Lamparter 	crypto4xx_memcpy_to_le32(iv, req->iv, 16 - (req->iv[0] + 1));
46765ea8b67SChristian Lamparter 
46865ea8b67SChristian Lamparter 	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
46965ea8b67SChristian Lamparter 				  len, iv, sizeof(iv),
470658c9d2bSChristian Lamparter 				  sa, ctx->sa_len, req->assoclen, rctx->dst);
47165ea8b67SChristian Lamparter }
47265ea8b67SChristian Lamparter 
crypto4xx_encrypt_aes_ccm(struct aead_request * req)47365ea8b67SChristian Lamparter int crypto4xx_encrypt_aes_ccm(struct aead_request *req)
47465ea8b67SChristian Lamparter {
47565ea8b67SChristian Lamparter 	return crypto4xx_crypt_aes_ccm(req, false);
47665ea8b67SChristian Lamparter }
47765ea8b67SChristian Lamparter 
crypto4xx_decrypt_aes_ccm(struct aead_request * req)47865ea8b67SChristian Lamparter int crypto4xx_decrypt_aes_ccm(struct aead_request *req)
47965ea8b67SChristian Lamparter {
48065ea8b67SChristian Lamparter 	return crypto4xx_crypt_aes_ccm(req, true);
48165ea8b67SChristian Lamparter }
48265ea8b67SChristian Lamparter 
crypto4xx_setauthsize_aead(struct crypto_aead * cipher,unsigned int authsize)48365ea8b67SChristian Lamparter int crypto4xx_setauthsize_aead(struct crypto_aead *cipher,
48465ea8b67SChristian Lamparter 			       unsigned int authsize)
48565ea8b67SChristian Lamparter {
48665ea8b67SChristian Lamparter 	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
48765ea8b67SChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
48865ea8b67SChristian Lamparter 
48965ea8b67SChristian Lamparter 	return crypto_aead_setauthsize(ctx->sw_cipher.aead, authsize);
49065ea8b67SChristian Lamparter }
49165ea8b67SChristian Lamparter 
492*73f04d3dSAditya Srivastava /*
49359231368SChristian Lamparter  * AES-GCM Functions
49459231368SChristian Lamparter  */
49559231368SChristian Lamparter 
crypto4xx_aes_gcm_validate_keylen(unsigned int keylen)49659231368SChristian Lamparter static int crypto4xx_aes_gcm_validate_keylen(unsigned int keylen)
49759231368SChristian Lamparter {
49859231368SChristian Lamparter 	switch (keylen) {
49959231368SChristian Lamparter 	case 16:
50059231368SChristian Lamparter 	case 24:
50159231368SChristian Lamparter 	case 32:
50259231368SChristian Lamparter 		return 0;
50359231368SChristian Lamparter 	default:
50459231368SChristian Lamparter 		return -EINVAL;
50559231368SChristian Lamparter 	}
50659231368SChristian Lamparter }
50759231368SChristian Lamparter 
crypto4xx_compute_gcm_hash_key_sw(__le32 * hash_start,const u8 * key,unsigned int keylen)50859231368SChristian Lamparter static int crypto4xx_compute_gcm_hash_key_sw(__le32 *hash_start, const u8 *key,
50959231368SChristian Lamparter 					     unsigned int keylen)
51059231368SChristian Lamparter {
511da3e7a97SArd Biesheuvel 	struct crypto_aes_ctx ctx;
51259231368SChristian Lamparter 	uint8_t src[16] = { 0 };
513da3e7a97SArd Biesheuvel 	int rc;
51459231368SChristian Lamparter 
515da3e7a97SArd Biesheuvel 	rc = aes_expandkey(&ctx, key, keylen);
51659231368SChristian Lamparter 	if (rc) {
517da3e7a97SArd Biesheuvel 		pr_err("aes_expandkey() failed: %d\n", rc);
518da3e7a97SArd Biesheuvel 		return rc;
51959231368SChristian Lamparter 	}
52059231368SChristian Lamparter 
521da3e7a97SArd Biesheuvel 	aes_encrypt(&ctx, src, src);
52259231368SChristian Lamparter 	crypto4xx_memcpy_to_le32(hash_start, src, 16);
523da3e7a97SArd Biesheuvel 	memzero_explicit(&ctx, sizeof(ctx));
524da3e7a97SArd Biesheuvel 	return 0;
52559231368SChristian Lamparter }
52659231368SChristian Lamparter 
crypto4xx_setkey_aes_gcm(struct crypto_aead * cipher,const u8 * key,unsigned int keylen)52759231368SChristian Lamparter int crypto4xx_setkey_aes_gcm(struct crypto_aead *cipher,
52859231368SChristian Lamparter 			     const u8 *key, unsigned int keylen)
52959231368SChristian Lamparter {
53059231368SChristian Lamparter 	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
53159231368SChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
53259231368SChristian Lamparter 	struct dynamic_sa_ctl *sa;
53359231368SChristian Lamparter 	int    rc = 0;
53459231368SChristian Lamparter 
535674f368aSEric Biggers 	if (crypto4xx_aes_gcm_validate_keylen(keylen) != 0)
53659231368SChristian Lamparter 		return -EINVAL;
53759231368SChristian Lamparter 
53898e87e3dSChristian Lamparter 	rc = crypto4xx_aead_setup_fallback(ctx, cipher, key, keylen);
53959231368SChristian Lamparter 	if (rc)
54059231368SChristian Lamparter 		return rc;
54159231368SChristian Lamparter 
54259231368SChristian Lamparter 	if (ctx->sa_in || ctx->sa_out)
54359231368SChristian Lamparter 		crypto4xx_free_sa(ctx);
54459231368SChristian Lamparter 
54559231368SChristian Lamparter 	rc = crypto4xx_alloc_sa(ctx, SA_AES128_GCM_LEN + (keylen - 16) / 4);
54659231368SChristian Lamparter 	if (rc)
54759231368SChristian Lamparter 		return rc;
54859231368SChristian Lamparter 
54959231368SChristian Lamparter 	sa  = (struct dynamic_sa_ctl *) ctx->sa_in;
55059231368SChristian Lamparter 
55159231368SChristian Lamparter 	sa->sa_contents.w = SA_AES_GCM_CONTENTS | (keylen << 2);
55259231368SChristian Lamparter 	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
55359231368SChristian Lamparter 				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
55459231368SChristian Lamparter 				 SA_NO_HEADER_PROC, SA_HASH_ALG_GHASH,
55559231368SChristian Lamparter 				 SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO,
55659231368SChristian Lamparter 				 SA_OP_GROUP_BASIC, SA_OPCODE_HASH_DECRYPT,
55759231368SChristian Lamparter 				 DIR_INBOUND);
55859231368SChristian Lamparter 	set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
55959231368SChristian Lamparter 				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
56059231368SChristian Lamparter 				 SA_SEQ_MASK_ON, SA_MC_DISABLE,
56159231368SChristian Lamparter 				 SA_NOT_COPY_PAD, SA_COPY_PAYLOAD,
56259231368SChristian Lamparter 				 SA_NOT_COPY_HDR);
56359231368SChristian Lamparter 
56459231368SChristian Lamparter 	sa->sa_command_1.bf.key_len = keylen >> 3;
56559231368SChristian Lamparter 
56659231368SChristian Lamparter 	crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa),
56759231368SChristian Lamparter 				 key, keylen);
56859231368SChristian Lamparter 
56959231368SChristian Lamparter 	rc = crypto4xx_compute_gcm_hash_key_sw(get_dynamic_sa_inner_digest(sa),
57059231368SChristian Lamparter 		key, keylen);
57159231368SChristian Lamparter 	if (rc) {
57259231368SChristian Lamparter 		pr_err("GCM hash key setting failed = %d\n", rc);
57359231368SChristian Lamparter 		goto err;
57459231368SChristian Lamparter 	}
57559231368SChristian Lamparter 
57659231368SChristian Lamparter 	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
57759231368SChristian Lamparter 	sa = (struct dynamic_sa_ctl *) ctx->sa_out;
57859231368SChristian Lamparter 	sa->sa_command_0.bf.dir = DIR_OUTBOUND;
57959231368SChristian Lamparter 	sa->sa_command_0.bf.opcode = SA_OPCODE_ENCRYPT_HASH;
58059231368SChristian Lamparter 
58159231368SChristian Lamparter 	return 0;
58259231368SChristian Lamparter err:
58359231368SChristian Lamparter 	crypto4xx_free_sa(ctx);
58459231368SChristian Lamparter 	return rc;
58559231368SChristian Lamparter }
58659231368SChristian Lamparter 
crypto4xx_crypt_aes_gcm(struct aead_request * req,bool decrypt)58759231368SChristian Lamparter static inline int crypto4xx_crypt_aes_gcm(struct aead_request *req,
58859231368SChristian Lamparter 					  bool decrypt)
58959231368SChristian Lamparter {
59059231368SChristian Lamparter 	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
591584201f1SChristian Lamparter 	struct crypto4xx_aead_reqctx *rctx = aead_request_ctx(req);
59259231368SChristian Lamparter 	__le32 iv[4];
593584201f1SChristian Lamparter 	unsigned int len = req->cryptlen;
59459231368SChristian Lamparter 
595584201f1SChristian Lamparter 	if (decrypt)
596584201f1SChristian Lamparter 		len -= crypto_aead_authsize(crypto_aead_reqtfm(req));
597584201f1SChristian Lamparter 
598584201f1SChristian Lamparter 	if (crypto4xx_aead_need_fallback(req, len, false, decrypt))
59959231368SChristian Lamparter 		return crypto4xx_aead_fallback(req, ctx, decrypt);
60059231368SChristian Lamparter 
60159231368SChristian Lamparter 	crypto4xx_memcpy_to_le32(iv, req->iv, GCM_AES_IV_SIZE);
60259231368SChristian Lamparter 	iv[3] = cpu_to_le32(1);
60359231368SChristian Lamparter 
60459231368SChristian Lamparter 	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
60559231368SChristian Lamparter 				  len, iv, sizeof(iv),
60659231368SChristian Lamparter 				  decrypt ? ctx->sa_in : ctx->sa_out,
607658c9d2bSChristian Lamparter 				  ctx->sa_len, req->assoclen, rctx->dst);
60859231368SChristian Lamparter }
60959231368SChristian Lamparter 
crypto4xx_encrypt_aes_gcm(struct aead_request * req)61059231368SChristian Lamparter int crypto4xx_encrypt_aes_gcm(struct aead_request *req)
61159231368SChristian Lamparter {
61259231368SChristian Lamparter 	return crypto4xx_crypt_aes_gcm(req, false);
61359231368SChristian Lamparter }
61459231368SChristian Lamparter 
crypto4xx_decrypt_aes_gcm(struct aead_request * req)61559231368SChristian Lamparter int crypto4xx_decrypt_aes_gcm(struct aead_request *req)
61659231368SChristian Lamparter {
61759231368SChristian Lamparter 	return crypto4xx_crypt_aes_gcm(req, true);
61859231368SChristian Lamparter }
61959231368SChristian Lamparter 
620*73f04d3dSAditya Srivastava /*
621049359d6SJames Hsiao  * HASH SHA1 Functions
622049359d6SJames Hsiao  */
crypto4xx_hash_alg_init(struct crypto_tfm * tfm,unsigned int sa_len,unsigned char ha,unsigned char hm)623049359d6SJames Hsiao static int crypto4xx_hash_alg_init(struct crypto_tfm *tfm,
624049359d6SJames Hsiao 				   unsigned int sa_len,
625049359d6SJames Hsiao 				   unsigned char ha,
626049359d6SJames Hsiao 				   unsigned char hm)
627049359d6SJames Hsiao {
628049359d6SJames Hsiao 	struct crypto_alg *alg = tfm->__crt_alg;
629a0aae821SChristian Lamparter 	struct crypto4xx_alg *my_alg;
630049359d6SJames Hsiao 	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
6319e0a0b3aSChristian Lamparter 	struct dynamic_sa_hash160 *sa;
632049359d6SJames Hsiao 	int rc;
633049359d6SJames Hsiao 
634a0aae821SChristian Lamparter 	my_alg = container_of(__crypto_ahash_alg(alg), struct crypto4xx_alg,
635a0aae821SChristian Lamparter 			      alg.u.hash);
636049359d6SJames Hsiao 	ctx->dev   = my_alg->dev;
637049359d6SJames Hsiao 
638049359d6SJames Hsiao 	/* Create SA */
6392f77690dSChristian Lamparter 	if (ctx->sa_in || ctx->sa_out)
640049359d6SJames Hsiao 		crypto4xx_free_sa(ctx);
641049359d6SJames Hsiao 
642049359d6SJames Hsiao 	rc = crypto4xx_alloc_sa(ctx, sa_len);
643049359d6SJames Hsiao 	if (rc)
644049359d6SJames Hsiao 		return rc;
645049359d6SJames Hsiao 
6466b1679f4SHerbert Xu 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
6476b1679f4SHerbert Xu 				 sizeof(struct crypto4xx_ctx));
6489e0a0b3aSChristian Lamparter 	sa = (struct dynamic_sa_hash160 *)ctx->sa_in;
6499e0a0b3aSChristian Lamparter 	set_dynamic_sa_command_0(&sa->ctrl, SA_SAVE_HASH, SA_NOT_SAVE_IV,
650049359d6SJames Hsiao 				 SA_NOT_LOAD_HASH, SA_LOAD_IV_FROM_SA,
651049359d6SJames Hsiao 				 SA_NO_HEADER_PROC, ha, SA_CIPHER_ALG_NULL,
652049359d6SJames Hsiao 				 SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
653049359d6SJames Hsiao 				 SA_OPCODE_HASH, DIR_INBOUND);
6549e0a0b3aSChristian Lamparter 	set_dynamic_sa_command_1(&sa->ctrl, 0, SA_HASH_MODE_HASH,
655049359d6SJames Hsiao 				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
656049359d6SJames Hsiao 				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
657049359d6SJames Hsiao 				 SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
658049359d6SJames Hsiao 				 SA_NOT_COPY_HDR);
659049359d6SJames Hsiao 	/* Need to zero hash digest in SA */
6609e0a0b3aSChristian Lamparter 	memset(sa->inner_digest, 0, sizeof(sa->inner_digest));
6619e0a0b3aSChristian Lamparter 	memset(sa->outer_digest, 0, sizeof(sa->outer_digest));
662049359d6SJames Hsiao 
663049359d6SJames Hsiao 	return 0;
664049359d6SJames Hsiao }
665049359d6SJames Hsiao 
crypto4xx_hash_init(struct ahash_request * req)666049359d6SJames Hsiao int crypto4xx_hash_init(struct ahash_request *req)
667049359d6SJames Hsiao {
668049359d6SJames Hsiao 	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
669049359d6SJames Hsiao 	int ds;
670049359d6SJames Hsiao 	struct dynamic_sa_ctl *sa;
671049359d6SJames Hsiao 
6729e0a0b3aSChristian Lamparter 	sa = ctx->sa_in;
673049359d6SJames Hsiao 	ds = crypto_ahash_digestsize(
674049359d6SJames Hsiao 			__crypto_ahash_cast(req->base.tfm));
675049359d6SJames Hsiao 	sa->sa_command_0.bf.digest_len = ds >> 2;
676049359d6SJames Hsiao 	sa->sa_command_0.bf.load_hash_state = SA_LOAD_HASH_FROM_SA;
677049359d6SJames Hsiao 
678049359d6SJames Hsiao 	return 0;
679049359d6SJames Hsiao }
680049359d6SJames Hsiao 
crypto4xx_hash_update(struct ahash_request * req)681049359d6SJames Hsiao int crypto4xx_hash_update(struct ahash_request *req)
682049359d6SJames Hsiao {
683cd4dcd6dSChristian Lamparter 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
684049359d6SJames Hsiao 	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
685cd4dcd6dSChristian Lamparter 	struct scatterlist dst;
686cd4dcd6dSChristian Lamparter 	unsigned int ds = crypto_ahash_digestsize(ahash);
687049359d6SJames Hsiao 
688cd4dcd6dSChristian Lamparter 	sg_init_one(&dst, req->result, ds);
689049359d6SJames Hsiao 
690cd4dcd6dSChristian Lamparter 	return crypto4xx_build_pd(&req->base, ctx, req->src, &dst,
691cd4dcd6dSChristian Lamparter 				  req->nbytes, NULL, 0, ctx->sa_in,
692658c9d2bSChristian Lamparter 				  ctx->sa_len, 0, NULL);
693049359d6SJames Hsiao }
694049359d6SJames Hsiao 
crypto4xx_hash_final(struct ahash_request * req)695049359d6SJames Hsiao int crypto4xx_hash_final(struct ahash_request *req)
696049359d6SJames Hsiao {
697049359d6SJames Hsiao 	return 0;
698049359d6SJames Hsiao }
699049359d6SJames Hsiao 
crypto4xx_hash_digest(struct ahash_request * req)700049359d6SJames Hsiao int crypto4xx_hash_digest(struct ahash_request *req)
701049359d6SJames Hsiao {
702cd4dcd6dSChristian Lamparter 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
703049359d6SJames Hsiao 	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
704cd4dcd6dSChristian Lamparter 	struct scatterlist dst;
705cd4dcd6dSChristian Lamparter 	unsigned int ds = crypto_ahash_digestsize(ahash);
706049359d6SJames Hsiao 
707cd4dcd6dSChristian Lamparter 	sg_init_one(&dst, req->result, ds);
708049359d6SJames Hsiao 
709cd4dcd6dSChristian Lamparter 	return crypto4xx_build_pd(&req->base, ctx, req->src, &dst,
710cd4dcd6dSChristian Lamparter 				  req->nbytes, NULL, 0, ctx->sa_in,
711658c9d2bSChristian Lamparter 				  ctx->sa_len, 0, NULL);
712049359d6SJames Hsiao }
713049359d6SJames Hsiao 
714*73f04d3dSAditya Srivastava /*
715049359d6SJames Hsiao  * SHA1 Algorithm
716049359d6SJames Hsiao  */
crypto4xx_sha1_alg_init(struct crypto_tfm * tfm)717049359d6SJames Hsiao int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm)
718049359d6SJames Hsiao {
719049359d6SJames Hsiao 	return crypto4xx_hash_alg_init(tfm, SA_HASH160_LEN, SA_HASH_ALG_SHA1,
720049359d6SJames Hsiao 				       SA_HASH_MODE_HASH);
721049359d6SJames Hsiao }
722