1301422e3SAntoine Tenart // SPDX-License-Identifier: GPL-2.0
21b44c5a6SAntoine Ténart /*
31b44c5a6SAntoine Ténart  * Copyright (C) 2017 Marvell
41b44c5a6SAntoine Ténart  *
51b44c5a6SAntoine Ténart  * Antoine Tenart <antoine.tenart@free-electrons.com>
61b44c5a6SAntoine Ténart  */
71b44c5a6SAntoine Ténart 
84a593fb3SPascal van Leeuwen #include <asm/unaligned.h>
91b44c5a6SAntoine Ténart #include <linux/device.h>
101b44c5a6SAntoine Ténart #include <linux/dma-mapping.h>
111b44c5a6SAntoine Ténart #include <linux/dmapool.h>
12f6beaea3SAntoine Tenart #include <crypto/aead.h>
131b44c5a6SAntoine Ténart #include <crypto/aes.h>
14f6beaea3SAntoine Tenart #include <crypto/authenc.h>
154a593fb3SPascal van Leeuwen #include <crypto/chacha.h>
16f26882a3SPascal van Leeuwen #include <crypto/ctr.h>
1704007b0eSArd Biesheuvel #include <crypto/internal/des.h>
183e450886SPascal van Leeuwen #include <crypto/gcm.h>
193e450886SPascal van Leeuwen #include <crypto/ghash.h>
20a6061921SPascal van Leeuwen #include <crypto/poly1305.h>
21f6beaea3SAntoine Tenart #include <crypto/sha.h>
221769f704SPascal van Leeuwen #include <crypto/sm3.h>
23fcca797dSPascal van Leeuwen #include <crypto/sm4.h>
24c7da38a7SPascal van Leeuwen #include <crypto/xts.h>
251b44c5a6SAntoine Ténart #include <crypto/skcipher.h>
26f6beaea3SAntoine Tenart #include <crypto/internal/aead.h>
271eb7b403SOfer Heifetz #include <crypto/internal/skcipher.h>
281b44c5a6SAntoine Ténart 
291b44c5a6SAntoine Ténart #include "safexcel.h"
301b44c5a6SAntoine Ténart 
311b44c5a6SAntoine Ténart enum safexcel_cipher_direction {
321b44c5a6SAntoine Ténart 	SAFEXCEL_ENCRYPT,
331b44c5a6SAntoine Ténart 	SAFEXCEL_DECRYPT,
341b44c5a6SAntoine Ténart };
351b44c5a6SAntoine Ténart 
36a7dea8c0SOfer Heifetz enum safexcel_cipher_alg {
37a7dea8c0SOfer Heifetz 	SAFEXCEL_DES,
3862469879SOfer Heifetz 	SAFEXCEL_3DES,
39a7dea8c0SOfer Heifetz 	SAFEXCEL_AES,
404a593fb3SPascal van Leeuwen 	SAFEXCEL_CHACHA20,
41fcca797dSPascal van Leeuwen 	SAFEXCEL_SM4,
42a7dea8c0SOfer Heifetz };
43a7dea8c0SOfer Heifetz 
441b44c5a6SAntoine Ténart struct safexcel_cipher_ctx {
451b44c5a6SAntoine Ténart 	struct safexcel_context base;
461b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv;
471b44c5a6SAntoine Ténart 
481b44c5a6SAntoine Ténart 	u32 mode;
49a7dea8c0SOfer Heifetz 	enum safexcel_cipher_alg alg;
50098e51e5SPascal van Leeuwen 	u8 aead; /* !=0=AEAD, 2=IPSec ESP AEAD, 3=IPsec ESP GMAC */
51098e51e5SPascal van Leeuwen 	u8 xcm;  /* 0=authenc, 1=GCM, 2 reserved for CCM */
52098e51e5SPascal van Leeuwen 	u8 aadskip;
53098e51e5SPascal van Leeuwen 	u8 blocksz;
54098e51e5SPascal van Leeuwen 	u32 ivmask;
55098e51e5SPascal van Leeuwen 	u32 ctrinit;
561b44c5a6SAntoine Ténart 
57c7da38a7SPascal van Leeuwen 	__le32 key[16];
5854f9e8faSPascal van Leeuwen 	u32 nonce;
59c7da38a7SPascal van Leeuwen 	unsigned int key_len, xts;
60f6beaea3SAntoine Tenart 
61f6beaea3SAntoine Tenart 	/* All the below is AEAD specific */
62a7dea8c0SOfer Heifetz 	u32 hash_alg;
63f6beaea3SAntoine Tenart 	u32 state_sz;
6413a1bb93SPascal van Leeuwen 	__be32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)];
6513a1bb93SPascal van Leeuwen 	__be32 opad[SHA512_DIGEST_SIZE / sizeof(u32)];
663e450886SPascal van Leeuwen 
673e450886SPascal van Leeuwen 	struct crypto_cipher *hkaes;
68a6061921SPascal van Leeuwen 	struct crypto_aead *fback;
691b44c5a6SAntoine Ténart };
701b44c5a6SAntoine Ténart 
711eb7b403SOfer Heifetz struct safexcel_cipher_req {
72847ccfc5SOfer Heifetz 	enum safexcel_cipher_direction direction;
7389332590SAntoine Tenart 	/* Number of result descriptors associated to the request */
7489332590SAntoine Tenart 	unsigned int rdescs;
751eb7b403SOfer Heifetz 	bool needs_inv;
7619b347b3SPascal van Leeuwen 	int  nr_src, nr_dst;
771eb7b403SOfer Heifetz };
781eb7b403SOfer Heifetz 
79098e51e5SPascal van Leeuwen static int safexcel_skcipher_iv(struct safexcel_cipher_ctx *ctx, u8 *iv,
800e17e362SPascal van Leeuwen 				struct safexcel_command_desc *cdesc)
811b44c5a6SAntoine Ténart {
82098e51e5SPascal van Leeuwen 	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) {
83493e289cSPascal van Leeuwen 		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
84493e289cSPascal van Leeuwen 		/* 32 bit nonce */
85493e289cSPascal van Leeuwen 		cdesc->control_data.token[0] = ctx->nonce;
86493e289cSPascal van Leeuwen 		/* 64 bit IV part */
87493e289cSPascal van Leeuwen 		memcpy(&cdesc->control_data.token[1], iv, 8);
88098e51e5SPascal van Leeuwen 		/* 32 bit counter, start at 0 or 1 (big endian!) */
8913a1bb93SPascal van Leeuwen 		cdesc->control_data.token[3] =
90098e51e5SPascal van Leeuwen 			(__force u32)cpu_to_be32(ctx->ctrinit);
91098e51e5SPascal van Leeuwen 		return 4;
92a19052d4SPascal van Leeuwen 	}
93a19052d4SPascal van Leeuwen 	if (ctx->alg == SAFEXCEL_CHACHA20) {
944a593fb3SPascal van Leeuwen 		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
954a593fb3SPascal van Leeuwen 		/* 96 bit nonce part */
964a593fb3SPascal van Leeuwen 		memcpy(&cdesc->control_data.token[0], &iv[4], 12);
974a593fb3SPascal van Leeuwen 		/* 32 bit counter */
984a593fb3SPascal van Leeuwen 		cdesc->control_data.token[3] = *(u32 *)iv;
99098e51e5SPascal van Leeuwen 		return 4;
100493e289cSPascal van Leeuwen 	}
101493e289cSPascal van Leeuwen 
102098e51e5SPascal van Leeuwen 	cdesc->control_data.options |= ctx->ivmask;
103098e51e5SPascal van Leeuwen 	memcpy(cdesc->control_data.token, iv, ctx->blocksz);
104098e51e5SPascal van Leeuwen 	return ctx->blocksz / sizeof(u32);
10554f9e8faSPascal van Leeuwen }
1060e17e362SPascal van Leeuwen 
1070e17e362SPascal van Leeuwen static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
1080e17e362SPascal van Leeuwen 				    struct safexcel_command_desc *cdesc,
109098e51e5SPascal van Leeuwen 				    struct safexcel_token *atoken,
1100e17e362SPascal van Leeuwen 				    u32 length)
1110e17e362SPascal van Leeuwen {
1120e17e362SPascal van Leeuwen 	struct safexcel_token *token;
113098e51e5SPascal van Leeuwen 	int ivlen;
1140e17e362SPascal van Leeuwen 
115098e51e5SPascal van Leeuwen 	ivlen = safexcel_skcipher_iv(ctx, iv, cdesc);
116098e51e5SPascal van Leeuwen 	if (ivlen == 4) {
117098e51e5SPascal van Leeuwen 		/* No space in cdesc, instruction moves to atoken */
118098e51e5SPascal van Leeuwen 		cdesc->additional_cdata_size = 1;
119098e51e5SPascal van Leeuwen 		token = atoken;
120098e51e5SPascal van Leeuwen 	} else {
121098e51e5SPascal van Leeuwen 		/* Everything fits in cdesc */
122098e51e5SPascal van Leeuwen 		token = (struct safexcel_token *)(cdesc->control_data.token + 2);
123098e51e5SPascal van Leeuwen 		/* Need to pad with NOP */
124098e51e5SPascal van Leeuwen 		eip197_noop_token(&token[1]);
125098e51e5SPascal van Leeuwen 	}
1261b44c5a6SAntoine Ténart 
127098e51e5SPascal van Leeuwen 	token->opcode = EIP197_TOKEN_OPCODE_DIRECTION;
128098e51e5SPascal van Leeuwen 	token->packet_length = length;
129098e51e5SPascal van Leeuwen 	token->stat = EIP197_TOKEN_STAT_LAST_PACKET |
13015f64ee0SAntoine Tenart 		      EIP197_TOKEN_STAT_LAST_HASH;
131098e51e5SPascal van Leeuwen 	token->instructions = EIP197_TOKEN_INS_LAST |
132a74d850fSPascal van Leeuwen 			      EIP197_TOKEN_INS_TYPE_CRYPTO |
1331b44c5a6SAntoine Ténart 			      EIP197_TOKEN_INS_TYPE_OUTPUT;
1341b44c5a6SAntoine Ténart }
1351b44c5a6SAntoine Ténart 
136098e51e5SPascal van Leeuwen static void safexcel_aead_iv(struct safexcel_cipher_ctx *ctx, u8 *iv,
137098e51e5SPascal van Leeuwen 			     struct safexcel_command_desc *cdesc)
138098e51e5SPascal van Leeuwen {
139098e51e5SPascal van Leeuwen 	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD ||
140098e51e5SPascal van Leeuwen 	    ctx->aead & EIP197_AEAD_TYPE_IPSEC_ESP) { /* _ESP and _ESP_GMAC */
141098e51e5SPascal van Leeuwen 		/* 32 bit nonce */
142098e51e5SPascal van Leeuwen 		cdesc->control_data.token[0] = ctx->nonce;
143098e51e5SPascal van Leeuwen 		/* 64 bit IV part */
144098e51e5SPascal van Leeuwen 		memcpy(&cdesc->control_data.token[1], iv, 8);
145098e51e5SPascal van Leeuwen 		/* 32 bit counter, start at 0 or 1 (big endian!) */
146098e51e5SPascal van Leeuwen 		cdesc->control_data.token[3] =
147098e51e5SPascal van Leeuwen 			(__force u32)cpu_to_be32(ctx->ctrinit);
148098e51e5SPascal van Leeuwen 		return;
149098e51e5SPascal van Leeuwen 	}
150098e51e5SPascal van Leeuwen 	if (ctx->xcm == EIP197_XCM_MODE_GCM || ctx->alg == SAFEXCEL_CHACHA20) {
151098e51e5SPascal van Leeuwen 		/* 96 bit IV part */
152098e51e5SPascal van Leeuwen 		memcpy(&cdesc->control_data.token[0], iv, 12);
153098e51e5SPascal van Leeuwen 		/* 32 bit counter, start at 0 or 1 (big endian!) */
154098e51e5SPascal van Leeuwen 		cdesc->control_data.token[3] =
155098e51e5SPascal van Leeuwen 			(__force u32)cpu_to_be32(ctx->ctrinit);
156098e51e5SPascal van Leeuwen 		return;
157098e51e5SPascal van Leeuwen 	}
158098e51e5SPascal van Leeuwen 	/* CBC */
159098e51e5SPascal van Leeuwen 	memcpy(cdesc->control_data.token, iv, ctx->blocksz);
160098e51e5SPascal van Leeuwen }
161098e51e5SPascal van Leeuwen 
162f6beaea3SAntoine Tenart static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
163f6beaea3SAntoine Tenart 				struct safexcel_command_desc *cdesc,
164098e51e5SPascal van Leeuwen 				struct safexcel_token *atoken,
165f6beaea3SAntoine Tenart 				enum safexcel_cipher_direction direction,
166f6beaea3SAntoine Tenart 				u32 cryptlen, u32 assoclen, u32 digestsize)
167f6beaea3SAntoine Tenart {
168098e51e5SPascal van Leeuwen 	struct safexcel_token *aadref;
169098e51e5SPascal van Leeuwen 	int atoksize = 2; /* Start with minimum size */
170098e51e5SPascal van Leeuwen 	int assocadj = assoclen - ctx->aadskip, aadalign;
171f6beaea3SAntoine Tenart 
172098e51e5SPascal van Leeuwen 	/* Always 4 dwords of embedded IV  for AEAD modes */
173098e51e5SPascal van Leeuwen 	cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
174f6beaea3SAntoine Tenart 
175098e51e5SPascal van Leeuwen 	if (direction == SAFEXCEL_DECRYPT)
176d2d9e6fdSPascal van Leeuwen 		cryptlen -= digestsize;
177d2d9e6fdSPascal van Leeuwen 
178098e51e5SPascal van Leeuwen 	if (unlikely(ctx->xcm == EIP197_XCM_MODE_CCM)) {
179098e51e5SPascal van Leeuwen 		/* Construct IV block B0 for the CBC-MAC */
180098e51e5SPascal van Leeuwen 		u8 *final_iv = (u8 *)cdesc->control_data.token;
181098e51e5SPascal van Leeuwen 		u8 *cbcmaciv = (u8 *)&atoken[1];
182098e51e5SPascal van Leeuwen 		__le32 *aadlen = (__le32 *)&atoken[5];
18354f9e8faSPascal van Leeuwen 
184098e51e5SPascal van Leeuwen 		if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
185098e51e5SPascal van Leeuwen 			/* Length + nonce */
186098e51e5SPascal van Leeuwen 			cdesc->control_data.token[0] = ctx->nonce;
187098e51e5SPascal van Leeuwen 			/* Fixup flags byte */
188098e51e5SPascal van Leeuwen 			*(__le32 *)cbcmaciv =
189098e51e5SPascal van Leeuwen 				cpu_to_le32(ctx->nonce |
190098e51e5SPascal van Leeuwen 					    ((assocadj > 0) << 6) |
191098e51e5SPascal van Leeuwen 					    ((digestsize - 2) << 2));
192098e51e5SPascal van Leeuwen 			/* 64 bit IV part */
193098e51e5SPascal van Leeuwen 			memcpy(&cdesc->control_data.token[1], iv, 8);
194098e51e5SPascal van Leeuwen 			memcpy(cbcmaciv + 4, iv, 8);
195098e51e5SPascal van Leeuwen 			/* Start counter at 0 */
196098e51e5SPascal van Leeuwen 			cdesc->control_data.token[3] = 0;
197098e51e5SPascal van Leeuwen 			/* Message length */
198098e51e5SPascal van Leeuwen 			*(__be32 *)(cbcmaciv + 12) = cpu_to_be32(cryptlen);
199098e51e5SPascal van Leeuwen 		} else {
200098e51e5SPascal van Leeuwen 			/* Variable length IV part */
201098e51e5SPascal van Leeuwen 			memcpy(final_iv, iv, 15 - iv[0]);
202098e51e5SPascal van Leeuwen 			memcpy(cbcmaciv, iv, 15 - iv[0]);
203098e51e5SPascal van Leeuwen 			/* Start variable length counter at 0 */
204098e51e5SPascal van Leeuwen 			memset(final_iv + 15 - iv[0], 0, iv[0] + 1);
205098e51e5SPascal van Leeuwen 			memset(cbcmaciv + 15 - iv[0], 0, iv[0] - 1);
206098e51e5SPascal van Leeuwen 			/* fixup flags byte */
207098e51e5SPascal van Leeuwen 			cbcmaciv[0] |= ((assocadj > 0) << 6) |
208098e51e5SPascal van Leeuwen 				       ((digestsize - 2) << 2);
209098e51e5SPascal van Leeuwen 			/* insert lower 2 bytes of message length */
210098e51e5SPascal van Leeuwen 			cbcmaciv[14] = cryptlen >> 8;
211098e51e5SPascal van Leeuwen 			cbcmaciv[15] = cryptlen & 255;
212f6beaea3SAntoine Tenart 		}
21354f9e8faSPascal van Leeuwen 
214098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
215098e51e5SPascal van Leeuwen 		atoken->packet_length = AES_BLOCK_SIZE +
216098e51e5SPascal van Leeuwen 					((assocadj > 0) << 1);
217098e51e5SPascal van Leeuwen 		atoken->stat = 0;
218098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_ORIGIN_TOKEN |
219098e51e5SPascal van Leeuwen 				       EIP197_TOKEN_INS_TYPE_HASH;
220098e51e5SPascal van Leeuwen 
221098e51e5SPascal van Leeuwen 		if (likely(assocadj)) {
222098e51e5SPascal van Leeuwen 			*aadlen = cpu_to_le32((assocadj >> 8) |
223098e51e5SPascal van Leeuwen 					      (assocadj & 255) << 8);
224098e51e5SPascal van Leeuwen 			atoken += 6;
225098e51e5SPascal van Leeuwen 			atoksize += 7;
226098e51e5SPascal van Leeuwen 		} else {
227098e51e5SPascal van Leeuwen 			atoken += 5;
228098e51e5SPascal van Leeuwen 			atoksize += 6;
229098e51e5SPascal van Leeuwen 		}
230098e51e5SPascal van Leeuwen 
231098e51e5SPascal van Leeuwen 		/* Process AAD data */
232098e51e5SPascal van Leeuwen 		aadref = atoken;
233098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION;
234098e51e5SPascal van Leeuwen 		atoken->packet_length = assocadj;
235098e51e5SPascal van Leeuwen 		atoken->stat = 0;
236098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH;
237098e51e5SPascal van Leeuwen 		atoken++;
238098e51e5SPascal van Leeuwen 
239098e51e5SPascal van Leeuwen 		/* For CCM only, align AAD data towards hash engine */
240098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
241098e51e5SPascal van Leeuwen 		aadalign = (assocadj + 2) & 15;
242098e51e5SPascal van Leeuwen 		atoken->packet_length = assocadj && aadalign ?
243098e51e5SPascal van Leeuwen 						16 - aadalign :
244098e51e5SPascal van Leeuwen 						0;
245098e51e5SPascal van Leeuwen 		if (likely(cryptlen)) {
246098e51e5SPascal van Leeuwen 			atoken->stat = 0;
247098e51e5SPascal van Leeuwen 			atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH;
248098e51e5SPascal van Leeuwen 		} else {
249098e51e5SPascal van Leeuwen 			atoken->stat = EIP197_TOKEN_STAT_LAST_HASH;
250098e51e5SPascal van Leeuwen 			atoken->instructions = EIP197_TOKEN_INS_LAST |
251098e51e5SPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_HASH;
252098e51e5SPascal van Leeuwen 		}
253098e51e5SPascal van Leeuwen 	} else {
254098e51e5SPascal van Leeuwen 		safexcel_aead_iv(ctx, iv, cdesc);
255098e51e5SPascal van Leeuwen 
256098e51e5SPascal van Leeuwen 		/* Process AAD data */
257098e51e5SPascal van Leeuwen 		aadref = atoken;
258098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION;
259098e51e5SPascal van Leeuwen 		atoken->packet_length = assocadj;
260098e51e5SPascal van Leeuwen 		atoken->stat = EIP197_TOKEN_STAT_LAST_HASH;
261098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_LAST |
262098e51e5SPascal van Leeuwen 				       EIP197_TOKEN_INS_TYPE_HASH;
263098e51e5SPascal van Leeuwen 	}
264098e51e5SPascal van Leeuwen 	atoken++;
265098e51e5SPascal van Leeuwen 
266a6061921SPascal van Leeuwen 	if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
26792c60cefSPascal van Leeuwen 		/* For ESP mode (and not GMAC), skip over the IV */
268098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION;
269098e51e5SPascal van Leeuwen 		atoken->packet_length = EIP197_AEAD_IPSEC_IV_SIZE;
270098e51e5SPascal van Leeuwen 		atoken->stat = 0;
271098e51e5SPascal van Leeuwen 		atoken->instructions = 0;
272098e51e5SPascal van Leeuwen 		atoken++;
273098e51e5SPascal van Leeuwen 		atoksize++;
274098e51e5SPascal van Leeuwen 	} else if (unlikely(ctx->alg == SAFEXCEL_CHACHA20 &&
275098e51e5SPascal van Leeuwen 			    direction == SAFEXCEL_DECRYPT)) {
276098e51e5SPascal van Leeuwen 		/* Poly-chacha decryption needs a dummy NOP here ... */
277098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
278098e51e5SPascal van Leeuwen 		atoken->packet_length = 16; /* According to Op Manual */
279098e51e5SPascal van Leeuwen 		atoken->stat = 0;
280098e51e5SPascal van Leeuwen 		atoken->instructions = 0;
281098e51e5SPascal van Leeuwen 		atoken++;
282098e51e5SPascal van Leeuwen 		atoksize++;
283a6061921SPascal van Leeuwen 	}
284a6061921SPascal van Leeuwen 
285098e51e5SPascal van Leeuwen 	if  (ctx->xcm) {
286098e51e5SPascal van Leeuwen 		/* For GCM and CCM, obtain enc(Y0) */
287098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT_REMRES;
288098e51e5SPascal van Leeuwen 		atoken->packet_length = 0;
289098e51e5SPascal van Leeuwen 		atoken->stat = 0;
290098e51e5SPascal van Leeuwen 		atoken->instructions = AES_BLOCK_SIZE;
291098e51e5SPascal van Leeuwen 		atoken++;
292098e51e5SPascal van Leeuwen 
293098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
294098e51e5SPascal van Leeuwen 		atoken->packet_length = AES_BLOCK_SIZE;
295098e51e5SPascal van Leeuwen 		atoken->stat = 0;
296098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
297098e51e5SPascal van Leeuwen 				       EIP197_TOKEN_INS_TYPE_CRYPTO;
298098e51e5SPascal van Leeuwen 		atoken++;
299098e51e5SPascal van Leeuwen 		atoksize += 2;
300098e51e5SPascal van Leeuwen 	}
30154f9e8faSPascal van Leeuwen 
302a6061921SPascal van Leeuwen 	if (likely(cryptlen || ctx->alg == SAFEXCEL_CHACHA20)) {
303098e51e5SPascal van Leeuwen 		/* Fixup stat field for AAD direction instruction */
304098e51e5SPascal van Leeuwen 		aadref->stat = 0;
305098e51e5SPascal van Leeuwen 
306098e51e5SPascal van Leeuwen 		/* Process crypto data */
307098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION;
308098e51e5SPascal van Leeuwen 		atoken->packet_length = cryptlen;
309098e51e5SPascal van Leeuwen 
31092c60cefSPascal van Leeuwen 		if (unlikely(ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP_GMAC)) {
311098e51e5SPascal van Leeuwen 			/* Fixup instruction field for AAD dir instruction */
312098e51e5SPascal van Leeuwen 			aadref->instructions = EIP197_TOKEN_INS_TYPE_HASH;
313098e51e5SPascal van Leeuwen 
31492c60cefSPascal van Leeuwen 			/* Do not send to crypt engine in case of GMAC */
315098e51e5SPascal van Leeuwen 			atoken->instructions = EIP197_TOKEN_INS_LAST |
31692c60cefSPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_HASH |
31792c60cefSPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_OUTPUT;
31892c60cefSPascal van Leeuwen 		} else {
319098e51e5SPascal van Leeuwen 			atoken->instructions = EIP197_TOKEN_INS_LAST |
32054f9e8faSPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_CRYPTO |
32154f9e8faSPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_HASH |
32254f9e8faSPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_OUTPUT;
32392c60cefSPascal van Leeuwen 		}
3243e450886SPascal van Leeuwen 
3254eb76fafSPascal van Leeuwen 		cryptlen &= 15;
326098e51e5SPascal van Leeuwen 		if (unlikely(ctx->xcm == EIP197_XCM_MODE_CCM && cryptlen)) {
327098e51e5SPascal van Leeuwen 			atoken->stat = 0;
328098e51e5SPascal van Leeuwen 			/* For CCM only, pad crypto data to the hash engine */
329098e51e5SPascal van Leeuwen 			atoken++;
330098e51e5SPascal van Leeuwen 			atoksize++;
331098e51e5SPascal van Leeuwen 			atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
332098e51e5SPascal van Leeuwen 			atoken->packet_length = 16 - cryptlen;
333098e51e5SPascal van Leeuwen 			atoken->stat = EIP197_TOKEN_STAT_LAST_HASH;
334098e51e5SPascal van Leeuwen 			atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH;
3354eb76fafSPascal van Leeuwen 		} else {
336098e51e5SPascal van Leeuwen 			atoken->stat = EIP197_TOKEN_STAT_LAST_HASH;
3374eb76fafSPascal van Leeuwen 		}
338098e51e5SPascal van Leeuwen 		atoken++;
339098e51e5SPascal van Leeuwen 		atoksize++;
3403e450886SPascal van Leeuwen 	}
341098e51e5SPascal van Leeuwen 
342098e51e5SPascal van Leeuwen 	if (direction == SAFEXCEL_ENCRYPT) {
343098e51e5SPascal van Leeuwen 		/* Append ICV */
344098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
345098e51e5SPascal van Leeuwen 		atoken->packet_length = digestsize;
346098e51e5SPascal van Leeuwen 		atoken->stat = EIP197_TOKEN_STAT_LAST_HASH |
347098e51e5SPascal van Leeuwen 			       EIP197_TOKEN_STAT_LAST_PACKET;
348098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
349098e51e5SPascal van Leeuwen 				       EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
350098e51e5SPascal van Leeuwen 	} else {
351098e51e5SPascal van Leeuwen 		/* Extract ICV */
352098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_RETRIEVE;
353098e51e5SPascal van Leeuwen 		atoken->packet_length = digestsize;
354098e51e5SPascal van Leeuwen 		atoken->stat = EIP197_TOKEN_STAT_LAST_HASH |
355098e51e5SPascal van Leeuwen 			       EIP197_TOKEN_STAT_LAST_PACKET;
356098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
357098e51e5SPascal van Leeuwen 		atoken++;
358098e51e5SPascal van Leeuwen 		atoksize++;
359098e51e5SPascal van Leeuwen 
360098e51e5SPascal van Leeuwen 		/* Verify ICV */
361098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_VERIFY;
362098e51e5SPascal van Leeuwen 		atoken->packet_length = digestsize |
363098e51e5SPascal van Leeuwen 					EIP197_TOKEN_HASH_RESULT_VERIFY;
364098e51e5SPascal van Leeuwen 		atoken->stat = EIP197_TOKEN_STAT_LAST_HASH |
365098e51e5SPascal van Leeuwen 			       EIP197_TOKEN_STAT_LAST_PACKET;
366098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT;
367098e51e5SPascal van Leeuwen 	}
368098e51e5SPascal van Leeuwen 
369098e51e5SPascal van Leeuwen 	/* Fixup length of the token in the command descriptor */
370098e51e5SPascal van Leeuwen 	cdesc->additional_cdata_size = atoksize;
371f6beaea3SAntoine Tenart }
372f6beaea3SAntoine Tenart 
3738ac1283eSAntoine Tenart static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm,
3748ac1283eSAntoine Tenart 					const u8 *key, unsigned int len)
3751b44c5a6SAntoine Ténart {
3761b44c5a6SAntoine Ténart 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3771b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
378871df319SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
3791b44c5a6SAntoine Ténart 	struct crypto_aes_ctx aes;
3801b44c5a6SAntoine Ténart 	int ret, i;
3811b44c5a6SAntoine Ténart 
382363a90c2SArd Biesheuvel 	ret = aes_expandkey(&aes, key, len);
3831b44c5a6SAntoine Ténart 	if (ret) {
3841b44c5a6SAntoine Ténart 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
3851b44c5a6SAntoine Ténart 		return ret;
3861b44c5a6SAntoine Ténart 	}
3871b44c5a6SAntoine Ténart 
38853c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
3891b44c5a6SAntoine Ténart 		for (i = 0; i < len / sizeof(u32); i++) {
39013a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
3911b44c5a6SAntoine Ténart 				ctx->base.needs_inv = true;
3921b44c5a6SAntoine Ténart 				break;
3931b44c5a6SAntoine Ténart 			}
3941b44c5a6SAntoine Ténart 		}
395c4daf4ccSOfer Heifetz 	}
3961b44c5a6SAntoine Ténart 
3971b44c5a6SAntoine Ténart 	for (i = 0; i < len / sizeof(u32); i++)
3981b44c5a6SAntoine Ténart 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
3991b44c5a6SAntoine Ténart 
4001b44c5a6SAntoine Ténart 	ctx->key_len = len;
4011b44c5a6SAntoine Ténart 
4021b44c5a6SAntoine Ténart 	memzero_explicit(&aes, sizeof(aes));
4031b44c5a6SAntoine Ténart 	return 0;
4041b44c5a6SAntoine Ténart }
4051b44c5a6SAntoine Ténart 
40677cdd4efSPascal van Leeuwen static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key,
407f6beaea3SAntoine Tenart 				unsigned int len)
408f6beaea3SAntoine Tenart {
409f6beaea3SAntoine Tenart 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
410f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
411f6beaea3SAntoine Tenart 	struct safexcel_ahash_export_state istate, ostate;
412f6beaea3SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
413f6beaea3SAntoine Tenart 	struct crypto_authenc_keys keys;
4140e17e362SPascal van Leeuwen 	struct crypto_aes_ctx aes;
41513a1bb93SPascal van Leeuwen 	int err = -EINVAL, i;
416f6beaea3SAntoine Tenart 
4171769f704SPascal van Leeuwen 	if (unlikely(crypto_authenc_extractkeys(&keys, key, len)))
418f6beaea3SAntoine Tenart 		goto badkey;
419f6beaea3SAntoine Tenart 
4200e17e362SPascal van Leeuwen 	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) {
4211769f704SPascal van Leeuwen 		/* Must have at least space for the nonce here */
4221769f704SPascal van Leeuwen 		if (unlikely(keys.enckeylen < CTR_RFC3686_NONCE_SIZE))
423f6beaea3SAntoine Tenart 			goto badkey;
4240e17e362SPascal van Leeuwen 		/* last 4 bytes of key are the nonce! */
425f26882a3SPascal van Leeuwen 		ctx->nonce = *(u32 *)(keys.enckey + keys.enckeylen -
426f26882a3SPascal van Leeuwen 				      CTR_RFC3686_NONCE_SIZE);
4270e17e362SPascal van Leeuwen 		/* exclude the nonce here */
4281769f704SPascal van Leeuwen 		keys.enckeylen -= CTR_RFC3686_NONCE_SIZE;
4290e17e362SPascal van Leeuwen 	}
430f6beaea3SAntoine Tenart 
431f6beaea3SAntoine Tenart 	/* Encryption key */
4320e17e362SPascal van Leeuwen 	switch (ctx->alg) {
433bb7679b8SPascal van Leeuwen 	case SAFEXCEL_DES:
434bb7679b8SPascal van Leeuwen 		err = verify_aead_des_key(ctfm, keys.enckey, keys.enckeylen);
435bb7679b8SPascal van Leeuwen 		if (unlikely(err))
436bb7679b8SPascal van Leeuwen 			goto badkey_expflags;
437bb7679b8SPascal van Leeuwen 		break;
4380e17e362SPascal van Leeuwen 	case SAFEXCEL_3DES:
43921f5a15eSArd Biesheuvel 		err = verify_aead_des3_key(ctfm, keys.enckey, keys.enckeylen);
44077cdd4efSPascal van Leeuwen 		if (unlikely(err))
4410e17e362SPascal van Leeuwen 			goto badkey_expflags;
4420e17e362SPascal van Leeuwen 		break;
4430e17e362SPascal van Leeuwen 	case SAFEXCEL_AES:
4440e17e362SPascal van Leeuwen 		err = aes_expandkey(&aes, keys.enckey, keys.enckeylen);
4450e17e362SPascal van Leeuwen 		if (unlikely(err))
4460e17e362SPascal van Leeuwen 			goto badkey;
4470e17e362SPascal van Leeuwen 		break;
4481769f704SPascal van Leeuwen 	case SAFEXCEL_SM4:
4491769f704SPascal van Leeuwen 		if (unlikely(keys.enckeylen != SM4_KEY_SIZE))
4501769f704SPascal van Leeuwen 			goto badkey;
4511769f704SPascal van Leeuwen 		break;
4520e17e362SPascal van Leeuwen 	default:
4530e17e362SPascal van Leeuwen 		dev_err(priv->dev, "aead: unsupported cipher algorithm\n");
4540e17e362SPascal van Leeuwen 		goto badkey;
45577cdd4efSPascal van Leeuwen 	}
45677cdd4efSPascal van Leeuwen 
45713a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
45813a1bb93SPascal van Leeuwen 		for (i = 0; i < keys.enckeylen / sizeof(u32); i++) {
459b8151220SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) !=
460b8151220SPascal van Leeuwen 			    ((u32 *)keys.enckey)[i]) {
461f6beaea3SAntoine Tenart 				ctx->base.needs_inv = true;
46213a1bb93SPascal van Leeuwen 				break;
46313a1bb93SPascal van Leeuwen 			}
46413a1bb93SPascal van Leeuwen 		}
46513a1bb93SPascal van Leeuwen 	}
466f6beaea3SAntoine Tenart 
467f6beaea3SAntoine Tenart 	/* Auth key */
468a7dea8c0SOfer Heifetz 	switch (ctx->hash_alg) {
46901ba061dSAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA1:
47001ba061dSAntoine Tenart 		if (safexcel_hmac_setkey("safexcel-sha1", keys.authkey,
47101ba061dSAntoine Tenart 					 keys.authkeylen, &istate, &ostate))
47201ba061dSAntoine Tenart 			goto badkey;
47301ba061dSAntoine Tenart 		break;
474678b2878SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA224:
475678b2878SAntoine Tenart 		if (safexcel_hmac_setkey("safexcel-sha224", keys.authkey,
476678b2878SAntoine Tenart 					 keys.authkeylen, &istate, &ostate))
477678b2878SAntoine Tenart 			goto badkey;
478678b2878SAntoine Tenart 		break;
479678b2878SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA256:
480f6beaea3SAntoine Tenart 		if (safexcel_hmac_setkey("safexcel-sha256", keys.authkey,
481f6beaea3SAntoine Tenart 					 keys.authkeylen, &istate, &ostate))
482f6beaea3SAntoine Tenart 			goto badkey;
483678b2878SAntoine Tenart 		break;
484ea23cb53SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA384:
485ea23cb53SAntoine Tenart 		if (safexcel_hmac_setkey("safexcel-sha384", keys.authkey,
486ea23cb53SAntoine Tenart 					 keys.authkeylen, &istate, &ostate))
487ea23cb53SAntoine Tenart 			goto badkey;
488ea23cb53SAntoine Tenart 		break;
48987eee125SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA512:
49087eee125SAntoine Tenart 		if (safexcel_hmac_setkey("safexcel-sha512", keys.authkey,
49187eee125SAntoine Tenart 					 keys.authkeylen, &istate, &ostate))
49287eee125SAntoine Tenart 			goto badkey;
49387eee125SAntoine Tenart 		break;
4941769f704SPascal van Leeuwen 	case CONTEXT_CONTROL_CRYPTO_ALG_SM3:
4951769f704SPascal van Leeuwen 		if (safexcel_hmac_setkey("safexcel-sm3", keys.authkey,
4961769f704SPascal van Leeuwen 					 keys.authkeylen, &istate, &ostate))
4971769f704SPascal van Leeuwen 			goto badkey;
4981769f704SPascal van Leeuwen 		break;
499678b2878SAntoine Tenart 	default:
5001a61af28SColin Ian King 		dev_err(priv->dev, "aead: unsupported hash algorithm\n");
501678b2878SAntoine Tenart 		goto badkey;
502678b2878SAntoine Tenart 	}
503f6beaea3SAntoine Tenart 
504f6beaea3SAntoine Tenart 	crypto_aead_set_flags(ctfm, crypto_aead_get_flags(ctfm) &
505f6beaea3SAntoine Tenart 				    CRYPTO_TFM_RES_MASK);
506f6beaea3SAntoine Tenart 
50753c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma &&
508f6beaea3SAntoine Tenart 	    (memcmp(ctx->ipad, istate.state, ctx->state_sz) ||
509f6beaea3SAntoine Tenart 	     memcmp(ctx->opad, ostate.state, ctx->state_sz)))
510f6beaea3SAntoine Tenart 		ctx->base.needs_inv = true;
511f6beaea3SAntoine Tenart 
512f6beaea3SAntoine Tenart 	/* Now copy the keys into the context */
51313a1bb93SPascal van Leeuwen 	for (i = 0; i < keys.enckeylen / sizeof(u32); i++)
514b8151220SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(((u32 *)keys.enckey)[i]);
515f6beaea3SAntoine Tenart 	ctx->key_len = keys.enckeylen;
516f6beaea3SAntoine Tenart 
517f6beaea3SAntoine Tenart 	memcpy(ctx->ipad, &istate.state, ctx->state_sz);
518f6beaea3SAntoine Tenart 	memcpy(ctx->opad, &ostate.state, ctx->state_sz);
519f6beaea3SAntoine Tenart 
520f6beaea3SAntoine Tenart 	memzero_explicit(&keys, sizeof(keys));
521f6beaea3SAntoine Tenart 	return 0;
522f6beaea3SAntoine Tenart 
523f6beaea3SAntoine Tenart badkey:
524f6beaea3SAntoine Tenart 	crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
5250e17e362SPascal van Leeuwen badkey_expflags:
526f6beaea3SAntoine Tenart 	memzero_explicit(&keys, sizeof(keys));
5270e17e362SPascal van Leeuwen 	return err;
528f6beaea3SAntoine Tenart }
529f6beaea3SAntoine Tenart 
5301b44c5a6SAntoine Ténart static int safexcel_context_control(struct safexcel_cipher_ctx *ctx,
531847ccfc5SOfer Heifetz 				    struct crypto_async_request *async,
5328ac1283eSAntoine Tenart 				    struct safexcel_cipher_req *sreq,
5331b44c5a6SAntoine Ténart 				    struct safexcel_command_desc *cdesc)
5341b44c5a6SAntoine Ténart {
5351b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
536d2d9e6fdSPascal van Leeuwen 	int ctrl_size = ctx->key_len / sizeof(u32);
537d2d9e6fdSPascal van Leeuwen 
538d2d9e6fdSPascal van Leeuwen 	cdesc->control_data.control1 = ctx->mode;
5391b44c5a6SAntoine Ténart 
540f6beaea3SAntoine Tenart 	if (ctx->aead) {
541d2d9e6fdSPascal van Leeuwen 		/* Take in account the ipad+opad digests */
5423e450886SPascal van Leeuwen 		if (ctx->xcm) {
5433e450886SPascal van Leeuwen 			ctrl_size += ctx->state_sz / sizeof(u32);
5443e450886SPascal van Leeuwen 			cdesc->control_data.control0 =
5453e450886SPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
5463e450886SPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
5473e450886SPascal van Leeuwen 				ctx->hash_alg |
5483e450886SPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
549a6061921SPascal van Leeuwen 		} else if (ctx->alg == SAFEXCEL_CHACHA20) {
550a6061921SPascal van Leeuwen 			/* Chacha20-Poly1305 */
551a6061921SPascal van Leeuwen 			cdesc->control_data.control0 =
552a6061921SPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
553a6061921SPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20 |
554a6061921SPascal van Leeuwen 				(sreq->direction == SAFEXCEL_ENCRYPT ?
555a6061921SPascal van Leeuwen 					CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT :
556a6061921SPascal van Leeuwen 					CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN) |
557a6061921SPascal van Leeuwen 				ctx->hash_alg |
558a6061921SPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
559a6061921SPascal van Leeuwen 			return 0;
5603e450886SPascal van Leeuwen 		} else {
561d2d9e6fdSPascal van Leeuwen 			ctrl_size += ctx->state_sz / sizeof(u32) * 2;
5623e450886SPascal van Leeuwen 			cdesc->control_data.control0 =
5633e450886SPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
5643e450886SPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_HMAC |
5653e450886SPascal van Leeuwen 				ctx->hash_alg |
5663e450886SPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
5673e450886SPascal van Leeuwen 		}
5684eb76fafSPascal van Leeuwen 
56992c60cefSPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_ENCRYPT &&
57092c60cefSPascal van Leeuwen 		    (ctx->xcm == EIP197_XCM_MODE_CCM ||
57192c60cefSPascal van Leeuwen 		     ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP_GMAC))
57292c60cefSPascal van Leeuwen 			cdesc->control_data.control0 |=
57392c60cefSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_ENCRYPT_OUT;
57492c60cefSPascal van Leeuwen 		else if (sreq->direction == SAFEXCEL_ENCRYPT)
57592c60cefSPascal van Leeuwen 			cdesc->control_data.control0 |=
57692c60cefSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT;
57792c60cefSPascal van Leeuwen 		else if (ctx->xcm == EIP197_XCM_MODE_CCM)
57892c60cefSPascal van Leeuwen 			cdesc->control_data.control0 |=
57992c60cefSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_DECRYPT_HASH_IN;
580d2d9e6fdSPascal van Leeuwen 		else
5813e450886SPascal van Leeuwen 			cdesc->control_data.control0 |=
5823e450886SPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN;
583d2d9e6fdSPascal van Leeuwen 	} else {
584d2d9e6fdSPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_ENCRYPT)
585d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 =
586d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_CRYPTO_OUT |
587d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
588d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
589d2d9e6fdSPascal van Leeuwen 		else
590d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 =
591d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_CRYPTO_IN |
592d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
593d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
594f6beaea3SAntoine Tenart 	}
5951b44c5a6SAntoine Ténart 
596a7dea8c0SOfer Heifetz 	if (ctx->alg == SAFEXCEL_DES) {
597d2d9e6fdSPascal van Leeuwen 		cdesc->control_data.control0 |=
598d2d9e6fdSPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_DES;
59962469879SOfer Heifetz 	} else if (ctx->alg == SAFEXCEL_3DES) {
600d2d9e6fdSPascal van Leeuwen 		cdesc->control_data.control0 |=
601d2d9e6fdSPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_3DES;
602a7dea8c0SOfer Heifetz 	} else if (ctx->alg == SAFEXCEL_AES) {
603c7da38a7SPascal van Leeuwen 		switch (ctx->key_len >> ctx->xts) {
6041b44c5a6SAntoine Ténart 		case AES_KEYSIZE_128:
605d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 |=
606d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_AES128;
6071b44c5a6SAntoine Ténart 			break;
6081b44c5a6SAntoine Ténart 		case AES_KEYSIZE_192:
609d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 |=
610d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_AES192;
6111b44c5a6SAntoine Ténart 			break;
6121b44c5a6SAntoine Ténart 		case AES_KEYSIZE_256:
613d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 |=
614d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_AES256;
6151b44c5a6SAntoine Ténart 			break;
6161b44c5a6SAntoine Ténart 		default:
6171b44c5a6SAntoine Ténart 			dev_err(priv->dev, "aes keysize not supported: %u\n",
618c7da38a7SPascal van Leeuwen 				ctx->key_len >> ctx->xts);
6191b44c5a6SAntoine Ténart 			return -EINVAL;
6201b44c5a6SAntoine Ténart 		}
6214a593fb3SPascal van Leeuwen 	} else if (ctx->alg == SAFEXCEL_CHACHA20) {
6224a593fb3SPascal van Leeuwen 		cdesc->control_data.control0 |=
6234a593fb3SPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20;
624fcca797dSPascal van Leeuwen 	} else if (ctx->alg == SAFEXCEL_SM4) {
625fcca797dSPascal van Leeuwen 		cdesc->control_data.control0 |=
626fcca797dSPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_SM4;
627a7dea8c0SOfer Heifetz 	}
628fef0cfe5SAntoine Tenart 
6291b44c5a6SAntoine Ténart 	return 0;
6301b44c5a6SAntoine Ténart }
6311b44c5a6SAntoine Ténart 
6321eb7b403SOfer Heifetz static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int ring,
6331b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
6348ac1283eSAntoine Tenart 				      struct scatterlist *src,
6358ac1283eSAntoine Tenart 				      struct scatterlist *dst,
6368ac1283eSAntoine Tenart 				      unsigned int cryptlen,
6378ac1283eSAntoine Tenart 				      struct safexcel_cipher_req *sreq,
6381b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
6391b44c5a6SAntoine Ténart {
6405bdb6e6aSPascal van Leeuwen 	struct skcipher_request *areq = skcipher_request_cast(async);
6415bdb6e6aSPascal van Leeuwen 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq);
6425bdb6e6aSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(skcipher);
6431b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
6441b44c5a6SAntoine Ténart 	int ndesc = 0;
6451b44c5a6SAntoine Ténart 
6461b44c5a6SAntoine Ténart 	*ret = 0;
6471b44c5a6SAntoine Ténart 
64889332590SAntoine Tenart 	if (unlikely(!sreq->rdescs))
64989332590SAntoine Tenart 		return 0;
65089332590SAntoine Tenart 
65189332590SAntoine Tenart 	while (sreq->rdescs--) {
6521b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
6531b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
6541b44c5a6SAntoine Ténart 			dev_err(priv->dev,
6551b44c5a6SAntoine Ténart 				"cipher: result: could not retrieve the result descriptor\n");
6561b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
6571b44c5a6SAntoine Ténart 			break;
6581b44c5a6SAntoine Ténart 		}
6591b44c5a6SAntoine Ténart 
660bdfd1909SAntoine Tenart 		if (likely(!*ret))
661bdfd1909SAntoine Tenart 			*ret = safexcel_rdesc_check_errors(priv, rdesc);
6621b44c5a6SAntoine Ténart 
6631b44c5a6SAntoine Ténart 		ndesc++;
66489332590SAntoine Tenart 	}
6651b44c5a6SAntoine Ténart 
6661b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
6671b44c5a6SAntoine Ténart 
6688ac1283eSAntoine Tenart 	if (src == dst) {
66919b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL);
6701b44c5a6SAntoine Ténart 	} else {
67119b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE);
67219b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE);
6731b44c5a6SAntoine Ténart 	}
6741b44c5a6SAntoine Ténart 
6755bdb6e6aSPascal van Leeuwen 	/*
6765bdb6e6aSPascal van Leeuwen 	 * Update IV in req from last crypto output word for CBC modes
6775bdb6e6aSPascal van Leeuwen 	 */
6785bdb6e6aSPascal van Leeuwen 	if ((!ctx->aead) && (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) &&
6795bdb6e6aSPascal van Leeuwen 	    (sreq->direction == SAFEXCEL_ENCRYPT)) {
6805bdb6e6aSPascal van Leeuwen 		/* For encrypt take the last output word */
68119b347b3SPascal van Leeuwen 		sg_pcopy_to_buffer(dst, sreq->nr_dst, areq->iv,
6825bdb6e6aSPascal van Leeuwen 				   crypto_skcipher_ivsize(skcipher),
6835bdb6e6aSPascal van Leeuwen 				   (cryptlen -
6845bdb6e6aSPascal van Leeuwen 				    crypto_skcipher_ivsize(skcipher)));
6855bdb6e6aSPascal van Leeuwen 	}
6865bdb6e6aSPascal van Leeuwen 
6871b44c5a6SAntoine Ténart 	*should_complete = true;
6881b44c5a6SAntoine Ténart 
6891b44c5a6SAntoine Ténart 	return ndesc;
6901b44c5a6SAntoine Ténart }
6911b44c5a6SAntoine Ténart 
692a7dea8c0SOfer Heifetz static int safexcel_send_req(struct crypto_async_request *base, int ring,
6938ac1283eSAntoine Tenart 			     struct safexcel_cipher_req *sreq,
6948ac1283eSAntoine Tenart 			     struct scatterlist *src, struct scatterlist *dst,
695f6beaea3SAntoine Tenart 			     unsigned int cryptlen, unsigned int assoclen,
696f6beaea3SAntoine Tenart 			     unsigned int digestsize, u8 *iv, int *commands,
6978ac1283eSAntoine Tenart 			     int *results)
6981b44c5a6SAntoine Ténart {
6995bdb6e6aSPascal van Leeuwen 	struct skcipher_request *areq = skcipher_request_cast(base);
7005bdb6e6aSPascal van Leeuwen 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq);
7018ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
7021b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
7031b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc;
70419b347b3SPascal van Leeuwen 	struct safexcel_command_desc *first_cdesc = NULL;
705e5c8ee1fSAntoine Tenart 	struct safexcel_result_desc *rdesc, *first_rdesc = NULL;
7061b44c5a6SAntoine Ténart 	struct scatterlist *sg;
70719b347b3SPascal van Leeuwen 	unsigned int totlen;
70819b347b3SPascal van Leeuwen 	unsigned int totlen_src = cryptlen + assoclen;
70919b347b3SPascal van Leeuwen 	unsigned int totlen_dst = totlen_src;
710098e51e5SPascal van Leeuwen 	struct safexcel_token *atoken;
71119b347b3SPascal van Leeuwen 	int n_cdesc = 0, n_rdesc = 0;
71219b347b3SPascal van Leeuwen 	int queued, i, ret = 0;
71319b347b3SPascal van Leeuwen 	bool first = true;
7141b44c5a6SAntoine Ténart 
71519b347b3SPascal van Leeuwen 	sreq->nr_src = sg_nents_for_len(src, totlen_src);
71619b347b3SPascal van Leeuwen 
71719b347b3SPascal van Leeuwen 	if (ctx->aead) {
71819b347b3SPascal van Leeuwen 		/*
71919b347b3SPascal van Leeuwen 		 * AEAD has auth tag appended to output for encrypt and
72019b347b3SPascal van Leeuwen 		 * removed from the output for decrypt!
72119b347b3SPascal van Leeuwen 		 */
72219b347b3SPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_DECRYPT)
72319b347b3SPascal van Leeuwen 			totlen_dst -= digestsize;
72419b347b3SPascal van Leeuwen 		else
72519b347b3SPascal van Leeuwen 			totlen_dst += digestsize;
72619b347b3SPascal van Leeuwen 
72719b347b3SPascal van Leeuwen 		memcpy(ctx->base.ctxr->data + ctx->key_len / sizeof(u32),
72819b347b3SPascal van Leeuwen 		       ctx->ipad, ctx->state_sz);
7293e450886SPascal van Leeuwen 		if (!ctx->xcm)
7303e450886SPascal van Leeuwen 			memcpy(ctx->base.ctxr->data + (ctx->key_len +
7313e450886SPascal van Leeuwen 			       ctx->state_sz) / sizeof(u32), ctx->opad,
7323e450886SPascal van Leeuwen 			       ctx->state_sz);
73319b347b3SPascal van Leeuwen 	} else if ((ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) &&
7345bdb6e6aSPascal van Leeuwen 		   (sreq->direction == SAFEXCEL_DECRYPT)) {
7355bdb6e6aSPascal van Leeuwen 		/*
7365bdb6e6aSPascal van Leeuwen 		 * Save IV from last crypto input word for CBC modes in decrypt
7375bdb6e6aSPascal van Leeuwen 		 * direction. Need to do this first in case of inplace operation
7385bdb6e6aSPascal van Leeuwen 		 * as it will be overwritten.
7395bdb6e6aSPascal van Leeuwen 		 */
74019b347b3SPascal van Leeuwen 		sg_pcopy_to_buffer(src, sreq->nr_src, areq->iv,
7415bdb6e6aSPascal van Leeuwen 				   crypto_skcipher_ivsize(skcipher),
74219b347b3SPascal van Leeuwen 				   (totlen_src -
7435bdb6e6aSPascal van Leeuwen 				    crypto_skcipher_ivsize(skcipher)));
7445bdb6e6aSPascal van Leeuwen 	}
7455bdb6e6aSPascal van Leeuwen 
74619b347b3SPascal van Leeuwen 	sreq->nr_dst = sg_nents_for_len(dst, totlen_dst);
7471b44c5a6SAntoine Ténart 
74819b347b3SPascal van Leeuwen 	/*
74919b347b3SPascal van Leeuwen 	 * Remember actual input length, source buffer length may be
75019b347b3SPascal van Leeuwen 	 * updated in case of inline operation below.
75119b347b3SPascal van Leeuwen 	 */
75219b347b3SPascal van Leeuwen 	totlen = totlen_src;
75319b347b3SPascal van Leeuwen 	queued = totlen_src;
75419b347b3SPascal van Leeuwen 
75519b347b3SPascal van Leeuwen 	if (src == dst) {
75619b347b3SPascal van Leeuwen 		sreq->nr_src = max(sreq->nr_src, sreq->nr_dst);
75719b347b3SPascal van Leeuwen 		sreq->nr_dst = sreq->nr_src;
75819b347b3SPascal van Leeuwen 		if (unlikely((totlen_src || totlen_dst) &&
75919b347b3SPascal van Leeuwen 		    (sreq->nr_src <= 0))) {
76019b347b3SPascal van Leeuwen 			dev_err(priv->dev, "In-place buffer not large enough (need %d bytes)!",
76119b347b3SPascal van Leeuwen 				max(totlen_src, totlen_dst));
7621b44c5a6SAntoine Ténart 			return -EINVAL;
7631b44c5a6SAntoine Ténart 		}
76419b347b3SPascal van Leeuwen 		dma_map_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL);
76519b347b3SPascal van Leeuwen 	} else {
76619b347b3SPascal van Leeuwen 		if (unlikely(totlen_src && (sreq->nr_src <= 0))) {
76719b347b3SPascal van Leeuwen 			dev_err(priv->dev, "Source buffer not large enough (need %d bytes)!",
76819b347b3SPascal van Leeuwen 				totlen_src);
76919b347b3SPascal van Leeuwen 			return -EINVAL;
77019b347b3SPascal van Leeuwen 		}
77119b347b3SPascal van Leeuwen 		dma_map_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE);
77219b347b3SPascal van Leeuwen 
77319b347b3SPascal van Leeuwen 		if (unlikely(totlen_dst && (sreq->nr_dst <= 0))) {
77419b347b3SPascal van Leeuwen 			dev_err(priv->dev, "Dest buffer not large enough (need %d bytes)!",
77519b347b3SPascal van Leeuwen 				totlen_dst);
77619b347b3SPascal van Leeuwen 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
77719b347b3SPascal van Leeuwen 				     DMA_TO_DEVICE);
77819b347b3SPascal van Leeuwen 			return -EINVAL;
77919b347b3SPascal van Leeuwen 		}
78019b347b3SPascal van Leeuwen 		dma_map_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE);
7811b44c5a6SAntoine Ténart 	}
7821b44c5a6SAntoine Ténart 
7831b44c5a6SAntoine Ténart 	memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len);
7841b44c5a6SAntoine Ténart 
785cb97aa94SPascal van Leeuwen 	if (!totlen) {
786cb97aa94SPascal van Leeuwen 		/*
787cb97aa94SPascal van Leeuwen 		 * The EIP97 cannot deal with zero length input packets!
788cb97aa94SPascal van Leeuwen 		 * So stuff a dummy command descriptor indicating a 1 byte
789cb97aa94SPascal van Leeuwen 		 * (dummy) input packet, using the context record as source.
790cb97aa94SPascal van Leeuwen 		 */
791cb97aa94SPascal van Leeuwen 		first_cdesc = safexcel_add_cdesc(priv, ring,
792cb97aa94SPascal van Leeuwen 						 1, 1, ctx->base.ctxr_dma,
793cb97aa94SPascal van Leeuwen 						 1, 1, ctx->base.ctxr_dma,
794cb97aa94SPascal van Leeuwen 						 &atoken);
795cb97aa94SPascal van Leeuwen 		if (IS_ERR(first_cdesc)) {
796cb97aa94SPascal van Leeuwen 			/* No space left in the command descriptor ring */
797cb97aa94SPascal van Leeuwen 			ret = PTR_ERR(first_cdesc);
798cb97aa94SPascal van Leeuwen 			goto cdesc_rollback;
799cb97aa94SPascal van Leeuwen 		}
800cb97aa94SPascal van Leeuwen 		n_cdesc = 1;
801cb97aa94SPascal van Leeuwen 		goto skip_cdesc;
802cb97aa94SPascal van Leeuwen 	}
803f6beaea3SAntoine Tenart 
8041b44c5a6SAntoine Ténart 	/* command descriptors */
80519b347b3SPascal van Leeuwen 	for_each_sg(src, sg, sreq->nr_src, i) {
8061b44c5a6SAntoine Ténart 		int len = sg_dma_len(sg);
8071b44c5a6SAntoine Ténart 
8081b44c5a6SAntoine Ténart 		/* Do not overflow the request */
809cb97aa94SPascal van Leeuwen 		if (queued < len)
8101b44c5a6SAntoine Ténart 			len = queued;
8111b44c5a6SAntoine Ténart 
81219b347b3SPascal van Leeuwen 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
81319b347b3SPascal van Leeuwen 					   !(queued - len),
814f6beaea3SAntoine Tenart 					   sg_dma_address(sg), len, totlen,
815098e51e5SPascal van Leeuwen 					   ctx->base.ctxr_dma, &atoken);
8161b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
8171b44c5a6SAntoine Ténart 			/* No space left in the command descriptor ring */
8181b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
8191b44c5a6SAntoine Ténart 			goto cdesc_rollback;
8201b44c5a6SAntoine Ténart 		}
8211b44c5a6SAntoine Ténart 
822cb97aa94SPascal van Leeuwen 		if (!n_cdesc)
82319b347b3SPascal van Leeuwen 			first_cdesc = cdesc;
8241b44c5a6SAntoine Ténart 
825cb97aa94SPascal van Leeuwen 		n_cdesc++;
8261b44c5a6SAntoine Ténart 		queued -= len;
8271b44c5a6SAntoine Ténart 		if (!queued)
8281b44c5a6SAntoine Ténart 			break;
8291b44c5a6SAntoine Ténart 	}
830cb97aa94SPascal van Leeuwen skip_cdesc:
83119b347b3SPascal van Leeuwen 	/* Add context control words and token to first command descriptor */
83219b347b3SPascal van Leeuwen 	safexcel_context_control(ctx, base, sreq, first_cdesc);
83319b347b3SPascal van Leeuwen 	if (ctx->aead)
834098e51e5SPascal van Leeuwen 		safexcel_aead_token(ctx, iv, first_cdesc, atoken,
83519b347b3SPascal van Leeuwen 				    sreq->direction, cryptlen,
83619b347b3SPascal van Leeuwen 				    assoclen, digestsize);
83719b347b3SPascal van Leeuwen 	else
838098e51e5SPascal van Leeuwen 		safexcel_skcipher_token(ctx, iv, first_cdesc, atoken,
83919b347b3SPascal van Leeuwen 					cryptlen);
84019b347b3SPascal van Leeuwen 
8411b44c5a6SAntoine Ténart 	/* result descriptors */
84219b347b3SPascal van Leeuwen 	for_each_sg(dst, sg, sreq->nr_dst, i) {
84319b347b3SPascal van Leeuwen 		bool last = (i == sreq->nr_dst - 1);
8441b44c5a6SAntoine Ténart 		u32 len = sg_dma_len(sg);
8451b44c5a6SAntoine Ténart 
84619b347b3SPascal van Leeuwen 		/* only allow the part of the buffer we know we need */
84719b347b3SPascal van Leeuwen 		if (len > totlen_dst)
84819b347b3SPascal van Leeuwen 			len = totlen_dst;
84919b347b3SPascal van Leeuwen 		if (unlikely(!len))
85019b347b3SPascal van Leeuwen 			break;
85119b347b3SPascal van Leeuwen 		totlen_dst -= len;
85219b347b3SPascal van Leeuwen 
85319b347b3SPascal van Leeuwen 		/* skip over AAD space in buffer - not written */
85419b347b3SPascal van Leeuwen 		if (assoclen) {
85519b347b3SPascal van Leeuwen 			if (assoclen >= len) {
85619b347b3SPascal van Leeuwen 				assoclen -= len;
85719b347b3SPascal van Leeuwen 				continue;
85819b347b3SPascal van Leeuwen 			}
8591b44c5a6SAntoine Ténart 			rdesc = safexcel_add_rdesc(priv, ring, first, last,
86019b347b3SPascal van Leeuwen 						   sg_dma_address(sg) +
86119b347b3SPascal van Leeuwen 						   assoclen,
86219b347b3SPascal van Leeuwen 						   len - assoclen);
86319b347b3SPascal van Leeuwen 			assoclen = 0;
86419b347b3SPascal van Leeuwen 		} else {
86519b347b3SPascal van Leeuwen 			rdesc = safexcel_add_rdesc(priv, ring, first, last,
86619b347b3SPascal van Leeuwen 						   sg_dma_address(sg),
86719b347b3SPascal van Leeuwen 						   len);
86819b347b3SPascal van Leeuwen 		}
8691b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
8701b44c5a6SAntoine Ténart 			/* No space left in the result descriptor ring */
8711b44c5a6SAntoine Ténart 			ret = PTR_ERR(rdesc);
8721b44c5a6SAntoine Ténart 			goto rdesc_rollback;
8731b44c5a6SAntoine Ténart 		}
87419b347b3SPascal van Leeuwen 		if (first) {
8759744fec9SOfer Heifetz 			first_rdesc = rdesc;
87619b347b3SPascal van Leeuwen 			first = false;
87719b347b3SPascal van Leeuwen 		}
8781b44c5a6SAntoine Ténart 		n_rdesc++;
8791b44c5a6SAntoine Ténart 	}
8801b44c5a6SAntoine Ténart 
88119b347b3SPascal van Leeuwen 	if (unlikely(first)) {
88219b347b3SPascal van Leeuwen 		/*
88319b347b3SPascal van Leeuwen 		 * Special case: AEAD decrypt with only AAD data.
88419b347b3SPascal van Leeuwen 		 * In this case there is NO output data from the engine,
88519b347b3SPascal van Leeuwen 		 * but the engine still needs a result descriptor!
88619b347b3SPascal van Leeuwen 		 * Create a dummy one just for catching the result token.
88719b347b3SPascal van Leeuwen 		 */
88819b347b3SPascal van Leeuwen 		rdesc = safexcel_add_rdesc(priv, ring, true, true, 0, 0);
88919b347b3SPascal van Leeuwen 		if (IS_ERR(rdesc)) {
89019b347b3SPascal van Leeuwen 			/* No space left in the result descriptor ring */
89119b347b3SPascal van Leeuwen 			ret = PTR_ERR(rdesc);
89219b347b3SPascal van Leeuwen 			goto rdesc_rollback;
89319b347b3SPascal van Leeuwen 		}
89419b347b3SPascal van Leeuwen 		first_rdesc = rdesc;
89519b347b3SPascal van Leeuwen 		n_rdesc = 1;
89619b347b3SPascal van Leeuwen 	}
89719b347b3SPascal van Leeuwen 
8989744fec9SOfer Heifetz 	safexcel_rdr_req_set(priv, ring, first_rdesc, base);
89997858434SAntoine Ténart 
9001b44c5a6SAntoine Ténart 	*commands = n_cdesc;
901152bdf4cSOfer Heifetz 	*results = n_rdesc;
9021b44c5a6SAntoine Ténart 	return 0;
9031b44c5a6SAntoine Ténart 
9041b44c5a6SAntoine Ténart rdesc_rollback:
9051b44c5a6SAntoine Ténart 	for (i = 0; i < n_rdesc; i++)
9061b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].rdr);
9071b44c5a6SAntoine Ténart cdesc_rollback:
9081b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
9091b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
9101b44c5a6SAntoine Ténart 
9118ac1283eSAntoine Tenart 	if (src == dst) {
91219b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL);
9131b44c5a6SAntoine Ténart 	} else {
91419b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE);
91519b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE);
9161b44c5a6SAntoine Ténart 	}
9171b44c5a6SAntoine Ténart 
9181b44c5a6SAntoine Ténart 	return ret;
9191b44c5a6SAntoine Ténart }
9201b44c5a6SAntoine Ténart 
9211b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
9221b44c5a6SAntoine Ténart 				      int ring,
9238ac1283eSAntoine Tenart 				      struct crypto_async_request *base,
92489332590SAntoine Tenart 				      struct safexcel_cipher_req *sreq,
9251b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
9261b44c5a6SAntoine Ténart {
9278ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
9281b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
9291b44c5a6SAntoine Ténart 	int ndesc = 0, enq_ret;
9301b44c5a6SAntoine Ténart 
9311b44c5a6SAntoine Ténart 	*ret = 0;
9321b44c5a6SAntoine Ténart 
93389332590SAntoine Tenart 	if (unlikely(!sreq->rdescs))
93489332590SAntoine Tenart 		return 0;
93589332590SAntoine Tenart 
93689332590SAntoine Tenart 	while (sreq->rdescs--) {
9371b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
9381b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
9391b44c5a6SAntoine Ténart 			dev_err(priv->dev,
9401b44c5a6SAntoine Ténart 				"cipher: invalidate: could not retrieve the result descriptor\n");
9411b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
9421b44c5a6SAntoine Ténart 			break;
9431b44c5a6SAntoine Ténart 		}
9441b44c5a6SAntoine Ténart 
945cda3e73aSAntoine Tenart 		if (likely(!*ret))
946cda3e73aSAntoine Tenart 			*ret = safexcel_rdesc_check_errors(priv, rdesc);
9471b44c5a6SAntoine Ténart 
9481b44c5a6SAntoine Ténart 		ndesc++;
94989332590SAntoine Tenart 	}
9501b44c5a6SAntoine Ténart 
9511b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
9521b44c5a6SAntoine Ténart 
9531b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
9541b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
9551b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
9561b44c5a6SAntoine Ténart 
9571b44c5a6SAntoine Ténart 		*should_complete = true;
9581b44c5a6SAntoine Ténart 
9591b44c5a6SAntoine Ténart 		return ndesc;
9601b44c5a6SAntoine Ténart 	}
9611b44c5a6SAntoine Ténart 
96286671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
96386671abbSAntoine Ténart 	ctx->base.ring = ring;
9641b44c5a6SAntoine Ténart 
96586671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
9668ac1283eSAntoine Tenart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
96786671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
9681b44c5a6SAntoine Ténart 
9691b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
9701b44c5a6SAntoine Ténart 		*ret = enq_ret;
9711b44c5a6SAntoine Ténart 
9728472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
9738472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
97486671abbSAntoine Ténart 
9751b44c5a6SAntoine Ténart 	*should_complete = false;
9761b44c5a6SAntoine Ténart 
9771b44c5a6SAntoine Ténart 	return ndesc;
9781b44c5a6SAntoine Ténart }
9791b44c5a6SAntoine Ténart 
9808ac1283eSAntoine Tenart static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv,
9818ac1283eSAntoine Tenart 					   int ring,
9821eb7b403SOfer Heifetz 					   struct crypto_async_request *async,
9831eb7b403SOfer Heifetz 					   bool *should_complete, int *ret)
9841eb7b403SOfer Heifetz {
9851eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
9861eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
9871eb7b403SOfer Heifetz 	int err;
9881eb7b403SOfer Heifetz 
9891eb7b403SOfer Heifetz 	if (sreq->needs_inv) {
9901eb7b403SOfer Heifetz 		sreq->needs_inv = false;
99189332590SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async, sreq,
9921eb7b403SOfer Heifetz 						 should_complete, ret);
9931eb7b403SOfer Heifetz 	} else {
9948ac1283eSAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
9958ac1283eSAntoine Tenart 						 req->dst, req->cryptlen, sreq,
9961eb7b403SOfer Heifetz 						 should_complete, ret);
9971eb7b403SOfer Heifetz 	}
9981eb7b403SOfer Heifetz 
9991eb7b403SOfer Heifetz 	return err;
10001eb7b403SOfer Heifetz }
10011eb7b403SOfer Heifetz 
1002f6beaea3SAntoine Tenart static int safexcel_aead_handle_result(struct safexcel_crypto_priv *priv,
1003f6beaea3SAntoine Tenart 				       int ring,
1004f6beaea3SAntoine Tenart 				       struct crypto_async_request *async,
1005f6beaea3SAntoine Tenart 				       bool *should_complete, int *ret)
1006f6beaea3SAntoine Tenart {
1007f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
1008f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1009f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
1010f6beaea3SAntoine Tenart 	int err;
1011f6beaea3SAntoine Tenart 
1012f6beaea3SAntoine Tenart 	if (sreq->needs_inv) {
1013f6beaea3SAntoine Tenart 		sreq->needs_inv = false;
101489332590SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async, sreq,
1015f6beaea3SAntoine Tenart 						 should_complete, ret);
1016f6beaea3SAntoine Tenart 	} else {
1017f6beaea3SAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
1018f6beaea3SAntoine Tenart 						 req->dst,
1019f6beaea3SAntoine Tenart 						 req->cryptlen + crypto_aead_authsize(tfm),
1020f6beaea3SAntoine Tenart 						 sreq, should_complete, ret);
1021f6beaea3SAntoine Tenart 	}
1022f6beaea3SAntoine Tenart 
1023f6beaea3SAntoine Tenart 	return err;
1024f6beaea3SAntoine Tenart }
1025f6beaea3SAntoine Tenart 
10268ac1283eSAntoine Tenart static int safexcel_cipher_send_inv(struct crypto_async_request *base,
10279744fec9SOfer Heifetz 				    int ring, int *commands, int *results)
10281b44c5a6SAntoine Ténart {
10298ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
10301b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
10311b44c5a6SAntoine Ténart 	int ret;
10321b44c5a6SAntoine Ténart 
10339744fec9SOfer Heifetz 	ret = safexcel_invalidate_cache(base, priv, ctx->base.ctxr_dma, ring);
10341b44c5a6SAntoine Ténart 	if (unlikely(ret))
10351b44c5a6SAntoine Ténart 		return ret;
10361b44c5a6SAntoine Ténart 
10371b44c5a6SAntoine Ténart 	*commands = 1;
10381b44c5a6SAntoine Ténart 	*results = 1;
10391b44c5a6SAntoine Ténart 
10401b44c5a6SAntoine Ténart 	return 0;
10411b44c5a6SAntoine Ténart }
10421b44c5a6SAntoine Ténart 
10438ac1283eSAntoine Tenart static int safexcel_skcipher_send(struct crypto_async_request *async, int ring,
10441eb7b403SOfer Heifetz 				  int *commands, int *results)
10451eb7b403SOfer Heifetz {
10461eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
1047871df319SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
10481eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
1049871df319SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
10501eb7b403SOfer Heifetz 	int ret;
10511eb7b403SOfer Heifetz 
105253c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv);
1053871df319SAntoine Ténart 
10545bdb6e6aSPascal van Leeuwen 	if (sreq->needs_inv) {
10559744fec9SOfer Heifetz 		ret = safexcel_cipher_send_inv(async, ring, commands, results);
10565bdb6e6aSPascal van Leeuwen 	} else {
10575bdb6e6aSPascal van Leeuwen 		struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
10585bdb6e6aSPascal van Leeuwen 		u8 input_iv[AES_BLOCK_SIZE];
10595bdb6e6aSPascal van Leeuwen 
10605bdb6e6aSPascal van Leeuwen 		/*
10615bdb6e6aSPascal van Leeuwen 		 * Save input IV in case of CBC decrypt mode
10625bdb6e6aSPascal van Leeuwen 		 * Will be overwritten with output IV prior to use!
10635bdb6e6aSPascal van Leeuwen 		 */
10645bdb6e6aSPascal van Leeuwen 		memcpy(input_iv, req->iv, crypto_skcipher_ivsize(skcipher));
10655bdb6e6aSPascal van Leeuwen 
10669744fec9SOfer Heifetz 		ret = safexcel_send_req(async, ring, sreq, req->src,
10675bdb6e6aSPascal van Leeuwen 					req->dst, req->cryptlen, 0, 0, input_iv,
1068f6beaea3SAntoine Tenart 					commands, results);
10695bdb6e6aSPascal van Leeuwen 	}
107089332590SAntoine Tenart 
107189332590SAntoine Tenart 	sreq->rdescs = *results;
1072f6beaea3SAntoine Tenart 	return ret;
1073f6beaea3SAntoine Tenart }
1074f6beaea3SAntoine Tenart 
1075f6beaea3SAntoine Tenart static int safexcel_aead_send(struct crypto_async_request *async, int ring,
10769744fec9SOfer Heifetz 			      int *commands, int *results)
1077f6beaea3SAntoine Tenart {
1078f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
1079f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1080f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
1081f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
1082f6beaea3SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
1083f6beaea3SAntoine Tenart 	int ret;
1084f6beaea3SAntoine Tenart 
108553c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv);
1086f6beaea3SAntoine Tenart 
1087f6beaea3SAntoine Tenart 	if (sreq->needs_inv)
10889744fec9SOfer Heifetz 		ret = safexcel_cipher_send_inv(async, ring, commands, results);
1089f6beaea3SAntoine Tenart 	else
10909744fec9SOfer Heifetz 		ret = safexcel_send_req(async, ring, sreq, req->src, req->dst,
10919744fec9SOfer Heifetz 					req->cryptlen, req->assoclen,
1092f6beaea3SAntoine Tenart 					crypto_aead_authsize(tfm), req->iv,
10931eb7b403SOfer Heifetz 					commands, results);
109489332590SAntoine Tenart 	sreq->rdescs = *results;
10951eb7b403SOfer Heifetz 	return ret;
10961eb7b403SOfer Heifetz }
10971eb7b403SOfer Heifetz 
10988ac1283eSAntoine Tenart static int safexcel_cipher_exit_inv(struct crypto_tfm *tfm,
10998ac1283eSAntoine Tenart 				    struct crypto_async_request *base,
11008ac1283eSAntoine Tenart 				    struct safexcel_cipher_req *sreq,
11018ac1283eSAntoine Tenart 				    struct safexcel_inv_result *result)
11021b44c5a6SAntoine Ténart {
11031b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
11041b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
110586671abbSAntoine Ténart 	int ring = ctx->base.ring;
11061b44c5a6SAntoine Ténart 
11078ac1283eSAntoine Tenart 	init_completion(&result->completion);
11081b44c5a6SAntoine Ténart 
11098ac1283eSAntoine Tenart 	ctx = crypto_tfm_ctx(base->tfm);
11101b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
11111eb7b403SOfer Heifetz 	sreq->needs_inv = true;
11121b44c5a6SAntoine Ténart 
111386671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
11148ac1283eSAntoine Tenart 	crypto_enqueue_request(&priv->ring[ring].queue, base);
111586671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
11161b44c5a6SAntoine Ténart 
11178472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
11188472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
11191b44c5a6SAntoine Ténart 
11208ac1283eSAntoine Tenart 	wait_for_completion(&result->completion);
11211b44c5a6SAntoine Ténart 
11228ac1283eSAntoine Tenart 	if (result->error) {
11231b44c5a6SAntoine Ténart 		dev_warn(priv->dev,
11241b44c5a6SAntoine Ténart 			"cipher: sync: invalidate: completion error %d\n",
11258ac1283eSAntoine Tenart 			 result->error);
11268ac1283eSAntoine Tenart 		return result->error;
11271b44c5a6SAntoine Ténart 	}
11281b44c5a6SAntoine Ténart 
11291b44c5a6SAntoine Ténart 	return 0;
11301b44c5a6SAntoine Ténart }
11311b44c5a6SAntoine Ténart 
11328ac1283eSAntoine Tenart static int safexcel_skcipher_exit_inv(struct crypto_tfm *tfm)
11338ac1283eSAntoine Tenart {
11348ac1283eSAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, skcipher, EIP197_SKCIPHER_REQ_SIZE);
11358ac1283eSAntoine Tenart 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
11368ac1283eSAntoine Tenart 	struct safexcel_inv_result result = {};
11378ac1283eSAntoine Tenart 
11388ac1283eSAntoine Tenart 	memset(req, 0, sizeof(struct skcipher_request));
11398ac1283eSAntoine Tenart 
11408ac1283eSAntoine Tenart 	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
11418ac1283eSAntoine Tenart 				      safexcel_inv_complete, &result);
11428ac1283eSAntoine Tenart 	skcipher_request_set_tfm(req, __crypto_skcipher_cast(tfm));
11438ac1283eSAntoine Tenart 
11448ac1283eSAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
11458ac1283eSAntoine Tenart }
11468ac1283eSAntoine Tenart 
1147f6beaea3SAntoine Tenart static int safexcel_aead_exit_inv(struct crypto_tfm *tfm)
1148f6beaea3SAntoine Tenart {
1149f6beaea3SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, aead, EIP197_AEAD_REQ_SIZE);
1150f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
1151f6beaea3SAntoine Tenart 	struct safexcel_inv_result result = {};
1152f6beaea3SAntoine Tenart 
1153f6beaea3SAntoine Tenart 	memset(req, 0, sizeof(struct aead_request));
1154f6beaea3SAntoine Tenart 
1155f6beaea3SAntoine Tenart 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1156f6beaea3SAntoine Tenart 				  safexcel_inv_complete, &result);
1157f6beaea3SAntoine Tenart 	aead_request_set_tfm(req, __crypto_aead_cast(tfm));
1158f6beaea3SAntoine Tenart 
1159f6beaea3SAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
1160f6beaea3SAntoine Tenart }
1161f6beaea3SAntoine Tenart 
1162a7dea8c0SOfer Heifetz static int safexcel_queue_req(struct crypto_async_request *base,
11638ac1283eSAntoine Tenart 			struct safexcel_cipher_req *sreq,
116493369b5dSPascal van Leeuwen 			enum safexcel_cipher_direction dir)
11651b44c5a6SAntoine Ténart {
11668ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
11671b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
116886671abbSAntoine Ténart 	int ret, ring;
11691b44c5a6SAntoine Ténart 
11701eb7b403SOfer Heifetz 	sreq->needs_inv = false;
1171847ccfc5SOfer Heifetz 	sreq->direction = dir;
11721b44c5a6SAntoine Ténart 
11731b44c5a6SAntoine Ténart 	if (ctx->base.ctxr) {
117453c83e91SAntoine Tenart 		if (priv->flags & EIP197_TRC_CACHE && ctx->base.needs_inv) {
11751eb7b403SOfer Heifetz 			sreq->needs_inv = true;
11761eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
11771eb7b403SOfer Heifetz 		}
11781b44c5a6SAntoine Ténart 	} else {
11791b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
11801b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
11818ac1283eSAntoine Tenart 						 EIP197_GFP_FLAGS(*base),
11821b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
11831b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
11841b44c5a6SAntoine Ténart 			return -ENOMEM;
11851b44c5a6SAntoine Ténart 	}
11861b44c5a6SAntoine Ténart 
118786671abbSAntoine Ténart 	ring = ctx->base.ring;
11881b44c5a6SAntoine Ténart 
118986671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
11908ac1283eSAntoine Tenart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
119186671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
119286671abbSAntoine Ténart 
11938472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
11948472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
11951b44c5a6SAntoine Ténart 
11961b44c5a6SAntoine Ténart 	return ret;
11971b44c5a6SAntoine Ténart }
11981b44c5a6SAntoine Ténart 
119993369b5dSPascal van Leeuwen static int safexcel_encrypt(struct skcipher_request *req)
12001b44c5a6SAntoine Ténart {
1201a7dea8c0SOfer Heifetz 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
120293369b5dSPascal van Leeuwen 			SAFEXCEL_ENCRYPT);
12031b44c5a6SAntoine Ténart }
12041b44c5a6SAntoine Ténart 
120593369b5dSPascal van Leeuwen static int safexcel_decrypt(struct skcipher_request *req)
12061b44c5a6SAntoine Ténart {
1207a7dea8c0SOfer Heifetz 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
120893369b5dSPascal van Leeuwen 			SAFEXCEL_DECRYPT);
12091b44c5a6SAntoine Ténart }
12101b44c5a6SAntoine Ténart 
12111b44c5a6SAntoine Ténart static int safexcel_skcipher_cra_init(struct crypto_tfm *tfm)
12121b44c5a6SAntoine Ténart {
12131b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
12141b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
12151b44c5a6SAntoine Ténart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
12161b44c5a6SAntoine Ténart 			     alg.skcipher.base);
12171b44c5a6SAntoine Ténart 
12181eb7b403SOfer Heifetz 	crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm),
12191eb7b403SOfer Heifetz 				    sizeof(struct safexcel_cipher_req));
12201b44c5a6SAntoine Ténart 
12218ac1283eSAntoine Tenart 	ctx->priv = tmpl->priv;
12228ac1283eSAntoine Tenart 
12238ac1283eSAntoine Tenart 	ctx->base.send = safexcel_skcipher_send;
12248ac1283eSAntoine Tenart 	ctx->base.handle_result = safexcel_skcipher_handle_result;
1225098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD;
1226098e51e5SPascal van Leeuwen 	ctx->ctrinit = 1;
12278ac1283eSAntoine Tenart 	return 0;
12288ac1283eSAntoine Tenart }
12298ac1283eSAntoine Tenart 
12308ac1283eSAntoine Tenart static int safexcel_cipher_cra_exit(struct crypto_tfm *tfm)
12318ac1283eSAntoine Tenart {
12328ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
12338ac1283eSAntoine Tenart 
1234ce679559SAntoine Tenart 	memzero_explicit(ctx->key, sizeof(ctx->key));
12358ac1283eSAntoine Tenart 
12368ac1283eSAntoine Tenart 	/* context not allocated, skip invalidation */
12378ac1283eSAntoine Tenart 	if (!ctx->base.ctxr)
12388ac1283eSAntoine Tenart 		return -ENOMEM;
12398ac1283eSAntoine Tenart 
1240ce679559SAntoine Tenart 	memzero_explicit(ctx->base.ctxr->data, sizeof(ctx->base.ctxr->data));
12411b44c5a6SAntoine Ténart 	return 0;
12421b44c5a6SAntoine Ténart }
12431b44c5a6SAntoine Ténart 
12441b44c5a6SAntoine Ténart static void safexcel_skcipher_cra_exit(struct crypto_tfm *tfm)
12451b44c5a6SAntoine Ténart {
12461b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
12471b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
12481b44c5a6SAntoine Ténart 	int ret;
12491b44c5a6SAntoine Ténart 
12508ac1283eSAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
12511b44c5a6SAntoine Ténart 		return;
12521b44c5a6SAntoine Ténart 
125353c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
12548ac1283eSAntoine Tenart 		ret = safexcel_skcipher_exit_inv(tfm);
12551b44c5a6SAntoine Ténart 		if (ret)
12568ac1283eSAntoine Tenart 			dev_warn(priv->dev, "skcipher: invalidation error %d\n",
12578ac1283eSAntoine Tenart 				 ret);
1258871df319SAntoine Ténart 	} else {
1259871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
1260871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
1261871df319SAntoine Ténart 	}
12621b44c5a6SAntoine Ténart }
12631b44c5a6SAntoine Ténart 
1264f6beaea3SAntoine Tenart static void safexcel_aead_cra_exit(struct crypto_tfm *tfm)
1265f6beaea3SAntoine Tenart {
1266f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1267f6beaea3SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
1268f6beaea3SAntoine Tenart 	int ret;
1269f6beaea3SAntoine Tenart 
1270f6beaea3SAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
1271f6beaea3SAntoine Tenart 		return;
1272f6beaea3SAntoine Tenart 
127353c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
1274f6beaea3SAntoine Tenart 		ret = safexcel_aead_exit_inv(tfm);
1275f6beaea3SAntoine Tenart 		if (ret)
1276f6beaea3SAntoine Tenart 			dev_warn(priv->dev, "aead: invalidation error %d\n",
1277f6beaea3SAntoine Tenart 				 ret);
1278f6beaea3SAntoine Tenart 	} else {
1279f6beaea3SAntoine Tenart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
1280f6beaea3SAntoine Tenart 			      ctx->base.ctxr_dma);
1281f6beaea3SAntoine Tenart 	}
1282f6beaea3SAntoine Tenart }
1283f6beaea3SAntoine Tenart 
128493369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_ecb_cra_init(struct crypto_tfm *tfm)
128593369b5dSPascal van Leeuwen {
128693369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
128793369b5dSPascal van Leeuwen 
128893369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
128993369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
129093369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1291098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1292098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
129393369b5dSPascal van Leeuwen 	return 0;
129493369b5dSPascal van Leeuwen }
129593369b5dSPascal van Leeuwen 
12961b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_ecb_aes = {
12971b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1298062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
12991b44c5a6SAntoine Ténart 	.alg.skcipher = {
13008ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
130193369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
130293369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
13031b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
13041b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
13051b44c5a6SAntoine Ténart 		.base = {
13061b44c5a6SAntoine Ténart 			.cra_name = "ecb(aes)",
13071b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-ecb-aes",
1308aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
13092c95e6d9SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
13101b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
13111b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
13121b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
13131b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
131493369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ecb_cra_init,
13151b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
13161b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
13171b44c5a6SAntoine Ténart 		},
13181b44c5a6SAntoine Ténart 	},
13191b44c5a6SAntoine Ténart };
13201b44c5a6SAntoine Ténart 
132193369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_cbc_cra_init(struct crypto_tfm *tfm)
13221b44c5a6SAntoine Ténart {
132393369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
13241b44c5a6SAntoine Ténart 
132593369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
132693369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1327098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
132893369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
132993369b5dSPascal van Leeuwen 	return 0;
13301b44c5a6SAntoine Ténart }
13311b44c5a6SAntoine Ténart 
13321b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_cbc_aes = {
13331b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1334062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
13351b44c5a6SAntoine Ténart 	.alg.skcipher = {
13368ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
133793369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
133893369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
13391b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
13401b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
13411b44c5a6SAntoine Ténart 		.ivsize = AES_BLOCK_SIZE,
13421b44c5a6SAntoine Ténart 		.base = {
13431b44c5a6SAntoine Ténart 			.cra_name = "cbc(aes)",
13441b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-cbc-aes",
1345aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
13462c95e6d9SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
13471b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
13481b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
13491b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
13501b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
135193369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_cbc_cra_init,
13521b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
13531b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
13541b44c5a6SAntoine Ténart 		},
13551b44c5a6SAntoine Ténart 	},
13561b44c5a6SAntoine Ténart };
1357f6beaea3SAntoine Tenart 
135848e97afaSPascal van Leeuwen static int safexcel_skcipher_aes_cfb_cra_init(struct crypto_tfm *tfm)
135948e97afaSPascal van Leeuwen {
136048e97afaSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
136148e97afaSPascal van Leeuwen 
136248e97afaSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
136348e97afaSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1364098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
136548e97afaSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB;
136648e97afaSPascal van Leeuwen 	return 0;
136748e97afaSPascal van Leeuwen }
136848e97afaSPascal van Leeuwen 
136948e97afaSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cfb_aes = {
137048e97afaSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
137148e97afaSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XFB,
137248e97afaSPascal van Leeuwen 	.alg.skcipher = {
137348e97afaSPascal van Leeuwen 		.setkey = safexcel_skcipher_aes_setkey,
137448e97afaSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
137548e97afaSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
137648e97afaSPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE,
137748e97afaSPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE,
137848e97afaSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
137948e97afaSPascal van Leeuwen 		.base = {
138048e97afaSPascal van Leeuwen 			.cra_name = "cfb(aes)",
138148e97afaSPascal van Leeuwen 			.cra_driver_name = "safexcel-cfb-aes",
138248e97afaSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
138348e97afaSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
138448e97afaSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
138548e97afaSPascal van Leeuwen 			.cra_blocksize = 1,
138648e97afaSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
138748e97afaSPascal van Leeuwen 			.cra_alignmask = 0,
138848e97afaSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_cfb_cra_init,
138948e97afaSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
139048e97afaSPascal van Leeuwen 			.cra_module = THIS_MODULE,
139148e97afaSPascal van Leeuwen 		},
139248e97afaSPascal van Leeuwen 	},
139348e97afaSPascal van Leeuwen };
139448e97afaSPascal van Leeuwen 
139550485dfbSPascal van Leeuwen static int safexcel_skcipher_aes_ofb_cra_init(struct crypto_tfm *tfm)
139650485dfbSPascal van Leeuwen {
139750485dfbSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
139850485dfbSPascal van Leeuwen 
139950485dfbSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
140050485dfbSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1401098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
140250485dfbSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB;
140350485dfbSPascal van Leeuwen 	return 0;
140450485dfbSPascal van Leeuwen }
140550485dfbSPascal van Leeuwen 
140650485dfbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ofb_aes = {
140750485dfbSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
140850485dfbSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XFB,
140950485dfbSPascal van Leeuwen 	.alg.skcipher = {
141050485dfbSPascal van Leeuwen 		.setkey = safexcel_skcipher_aes_setkey,
141150485dfbSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
141250485dfbSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
141350485dfbSPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE,
141450485dfbSPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE,
141550485dfbSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
141650485dfbSPascal van Leeuwen 		.base = {
141750485dfbSPascal van Leeuwen 			.cra_name = "ofb(aes)",
141850485dfbSPascal van Leeuwen 			.cra_driver_name = "safexcel-ofb-aes",
141950485dfbSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
142050485dfbSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
142150485dfbSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
142250485dfbSPascal van Leeuwen 			.cra_blocksize = 1,
142350485dfbSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
142450485dfbSPascal van Leeuwen 			.cra_alignmask = 0,
142550485dfbSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ofb_cra_init,
142650485dfbSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
142750485dfbSPascal van Leeuwen 			.cra_module = THIS_MODULE,
142850485dfbSPascal van Leeuwen 		},
142950485dfbSPascal van Leeuwen 	},
143050485dfbSPascal van Leeuwen };
143150485dfbSPascal van Leeuwen 
143254f9e8faSPascal van Leeuwen static int safexcel_skcipher_aesctr_setkey(struct crypto_skcipher *ctfm,
143354f9e8faSPascal van Leeuwen 					   const u8 *key, unsigned int len)
143454f9e8faSPascal van Leeuwen {
143554f9e8faSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
143654f9e8faSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
143754f9e8faSPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
143854f9e8faSPascal van Leeuwen 	struct crypto_aes_ctx aes;
143954f9e8faSPascal van Leeuwen 	int ret, i;
144054f9e8faSPascal van Leeuwen 	unsigned int keylen;
144154f9e8faSPascal van Leeuwen 
144254f9e8faSPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
1443f26882a3SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
144454f9e8faSPascal van Leeuwen 	/* exclude the nonce here */
1445f26882a3SPascal van Leeuwen 	keylen = len - CTR_RFC3686_NONCE_SIZE;
144654f9e8faSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, keylen);
144754f9e8faSPascal van Leeuwen 	if (ret) {
144854f9e8faSPascal van Leeuwen 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
144954f9e8faSPascal van Leeuwen 		return ret;
145054f9e8faSPascal van Leeuwen 	}
145154f9e8faSPascal van Leeuwen 
145254f9e8faSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
145354f9e8faSPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
145413a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
145554f9e8faSPascal van Leeuwen 				ctx->base.needs_inv = true;
145654f9e8faSPascal van Leeuwen 				break;
145754f9e8faSPascal van Leeuwen 			}
145854f9e8faSPascal van Leeuwen 		}
145954f9e8faSPascal van Leeuwen 	}
146054f9e8faSPascal van Leeuwen 
146154f9e8faSPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
146254f9e8faSPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
146354f9e8faSPascal van Leeuwen 
146454f9e8faSPascal van Leeuwen 	ctx->key_len = keylen;
146554f9e8faSPascal van Leeuwen 
146654f9e8faSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
146754f9e8faSPascal van Leeuwen 	return 0;
146854f9e8faSPascal van Leeuwen }
146954f9e8faSPascal van Leeuwen 
147093369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_ctr_cra_init(struct crypto_tfm *tfm)
147193369b5dSPascal van Leeuwen {
147293369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
147393369b5dSPascal van Leeuwen 
147493369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
147593369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1476098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
147793369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
147893369b5dSPascal van Leeuwen 	return 0;
147993369b5dSPascal van Leeuwen }
148093369b5dSPascal van Leeuwen 
148154f9e8faSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ctr_aes = {
148254f9e8faSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1483062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
148454f9e8faSPascal van Leeuwen 	.alg.skcipher = {
148554f9e8faSPascal van Leeuwen 		.setkey = safexcel_skcipher_aesctr_setkey,
148693369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
148793369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1488f26882a3SPascal van Leeuwen 		/* Add nonce size */
1489f26882a3SPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
1490f26882a3SPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
1491f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
149254f9e8faSPascal van Leeuwen 		.base = {
149354f9e8faSPascal van Leeuwen 			.cra_name = "rfc3686(ctr(aes))",
149454f9e8faSPascal van Leeuwen 			.cra_driver_name = "safexcel-ctr-aes",
1495aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
149654f9e8faSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
149754f9e8faSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
149854f9e8faSPascal van Leeuwen 			.cra_blocksize = 1,
149954f9e8faSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
150054f9e8faSPascal van Leeuwen 			.cra_alignmask = 0,
150193369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ctr_cra_init,
150254f9e8faSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
150354f9e8faSPascal van Leeuwen 			.cra_module = THIS_MODULE,
150454f9e8faSPascal van Leeuwen 		},
150554f9e8faSPascal van Leeuwen 	},
150654f9e8faSPascal van Leeuwen };
150754f9e8faSPascal van Leeuwen 
1508a7dea8c0SOfer Heifetz static int safexcel_des_setkey(struct crypto_skcipher *ctfm, const u8 *key,
1509a7dea8c0SOfer Heifetz 			       unsigned int len)
1510a7dea8c0SOfer Heifetz {
151121f5a15eSArd Biesheuvel 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
1512177e358cSPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
1513a7dea8c0SOfer Heifetz 	int ret;
1514a7dea8c0SOfer Heifetz 
151521f5a15eSArd Biesheuvel 	ret = verify_skcipher_des_key(ctfm, key);
151621f5a15eSArd Biesheuvel 	if (ret)
151721f5a15eSArd Biesheuvel 		return ret;
1518a7dea8c0SOfer Heifetz 
1519a7dea8c0SOfer Heifetz 	/* if context exits and key changed, need to invalidate it */
1520177e358cSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
1521a7dea8c0SOfer Heifetz 		if (memcmp(ctx->key, key, len))
1522a7dea8c0SOfer Heifetz 			ctx->base.needs_inv = true;
1523a7dea8c0SOfer Heifetz 
1524a7dea8c0SOfer Heifetz 	memcpy(ctx->key, key, len);
1525a7dea8c0SOfer Heifetz 	ctx->key_len = len;
1526a7dea8c0SOfer Heifetz 
1527a7dea8c0SOfer Heifetz 	return 0;
1528a7dea8c0SOfer Heifetz }
1529a7dea8c0SOfer Heifetz 
153093369b5dSPascal van Leeuwen static int safexcel_skcipher_des_cbc_cra_init(struct crypto_tfm *tfm)
153193369b5dSPascal van Leeuwen {
153293369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
153393369b5dSPascal van Leeuwen 
153493369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
153593369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_DES;
1536098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
1537098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
153893369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
153993369b5dSPascal van Leeuwen 	return 0;
154093369b5dSPascal van Leeuwen }
154193369b5dSPascal van Leeuwen 
1542a7dea8c0SOfer Heifetz struct safexcel_alg_template safexcel_alg_cbc_des = {
1543a7dea8c0SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1544062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
1545a7dea8c0SOfer Heifetz 	.alg.skcipher = {
1546a7dea8c0SOfer Heifetz 		.setkey = safexcel_des_setkey,
154793369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
154893369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1549a7dea8c0SOfer Heifetz 		.min_keysize = DES_KEY_SIZE,
1550a7dea8c0SOfer Heifetz 		.max_keysize = DES_KEY_SIZE,
1551a7dea8c0SOfer Heifetz 		.ivsize = DES_BLOCK_SIZE,
1552a7dea8c0SOfer Heifetz 		.base = {
1553a7dea8c0SOfer Heifetz 			.cra_name = "cbc(des)",
1554a7dea8c0SOfer Heifetz 			.cra_driver_name = "safexcel-cbc-des",
1555aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
15562b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1557a7dea8c0SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1558a7dea8c0SOfer Heifetz 			.cra_blocksize = DES_BLOCK_SIZE,
1559a7dea8c0SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1560a7dea8c0SOfer Heifetz 			.cra_alignmask = 0,
156193369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des_cbc_cra_init,
1562a7dea8c0SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
1563a7dea8c0SOfer Heifetz 			.cra_module = THIS_MODULE,
1564a7dea8c0SOfer Heifetz 		},
1565a7dea8c0SOfer Heifetz 	},
1566a7dea8c0SOfer Heifetz };
1567a7dea8c0SOfer Heifetz 
156893369b5dSPascal van Leeuwen static int safexcel_skcipher_des_ecb_cra_init(struct crypto_tfm *tfm)
1569a7dea8c0SOfer Heifetz {
157093369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1571a7dea8c0SOfer Heifetz 
157293369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
157393369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_DES;
157493369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1575098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1576098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
157793369b5dSPascal van Leeuwen 	return 0;
1578a7dea8c0SOfer Heifetz }
1579a7dea8c0SOfer Heifetz 
1580a7dea8c0SOfer Heifetz struct safexcel_alg_template safexcel_alg_ecb_des = {
1581a7dea8c0SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1582062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
1583a7dea8c0SOfer Heifetz 	.alg.skcipher = {
1584a7dea8c0SOfer Heifetz 		.setkey = safexcel_des_setkey,
158593369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
158693369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1587a7dea8c0SOfer Heifetz 		.min_keysize = DES_KEY_SIZE,
1588a7dea8c0SOfer Heifetz 		.max_keysize = DES_KEY_SIZE,
1589a7dea8c0SOfer Heifetz 		.base = {
1590a7dea8c0SOfer Heifetz 			.cra_name = "ecb(des)",
1591a7dea8c0SOfer Heifetz 			.cra_driver_name = "safexcel-ecb-des",
1592aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
15932b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1594a7dea8c0SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1595a7dea8c0SOfer Heifetz 			.cra_blocksize = DES_BLOCK_SIZE,
1596a7dea8c0SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1597a7dea8c0SOfer Heifetz 			.cra_alignmask = 0,
159893369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des_ecb_cra_init,
1599a7dea8c0SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
1600a7dea8c0SOfer Heifetz 			.cra_module = THIS_MODULE,
1601a7dea8c0SOfer Heifetz 		},
1602a7dea8c0SOfer Heifetz 	},
1603a7dea8c0SOfer Heifetz };
160462469879SOfer Heifetz 
160562469879SOfer Heifetz static int safexcel_des3_ede_setkey(struct crypto_skcipher *ctfm,
160662469879SOfer Heifetz 				   const u8 *key, unsigned int len)
160762469879SOfer Heifetz {
160867ac62bfSHerbert Xu 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
1609177e358cSPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
161067ac62bfSHerbert Xu 	int err;
161162469879SOfer Heifetz 
161221f5a15eSArd Biesheuvel 	err = verify_skcipher_des3_key(ctfm, key);
161321f5a15eSArd Biesheuvel 	if (err)
161467ac62bfSHerbert Xu 		return err;
161562469879SOfer Heifetz 
161662469879SOfer Heifetz 	/* if context exits and key changed, need to invalidate it */
1617177e358cSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
161862469879SOfer Heifetz 		if (memcmp(ctx->key, key, len))
161962469879SOfer Heifetz 			ctx->base.needs_inv = true;
162062469879SOfer Heifetz 
162162469879SOfer Heifetz 	memcpy(ctx->key, key, len);
162262469879SOfer Heifetz 	ctx->key_len = len;
162362469879SOfer Heifetz 
162462469879SOfer Heifetz 	return 0;
162562469879SOfer Heifetz }
162662469879SOfer Heifetz 
162793369b5dSPascal van Leeuwen static int safexcel_skcipher_des3_cbc_cra_init(struct crypto_tfm *tfm)
162893369b5dSPascal van Leeuwen {
162993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
163093369b5dSPascal van Leeuwen 
163193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
163293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_3DES;
1633098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1634098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
163593369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
163693369b5dSPascal van Leeuwen 	return 0;
163793369b5dSPascal van Leeuwen }
163893369b5dSPascal van Leeuwen 
163962469879SOfer Heifetz struct safexcel_alg_template safexcel_alg_cbc_des3_ede = {
164062469879SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1641062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
164262469879SOfer Heifetz 	.alg.skcipher = {
164362469879SOfer Heifetz 		.setkey = safexcel_des3_ede_setkey,
164493369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
164593369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
164662469879SOfer Heifetz 		.min_keysize = DES3_EDE_KEY_SIZE,
164762469879SOfer Heifetz 		.max_keysize = DES3_EDE_KEY_SIZE,
164862469879SOfer Heifetz 		.ivsize = DES3_EDE_BLOCK_SIZE,
164962469879SOfer Heifetz 		.base = {
165062469879SOfer Heifetz 			.cra_name = "cbc(des3_ede)",
165162469879SOfer Heifetz 			.cra_driver_name = "safexcel-cbc-des3_ede",
1652aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
16532b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
165462469879SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
165562469879SOfer Heifetz 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
165662469879SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
165762469879SOfer Heifetz 			.cra_alignmask = 0,
165893369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des3_cbc_cra_init,
165962469879SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
166062469879SOfer Heifetz 			.cra_module = THIS_MODULE,
166162469879SOfer Heifetz 		},
166262469879SOfer Heifetz 	},
166362469879SOfer Heifetz };
166462469879SOfer Heifetz 
166593369b5dSPascal van Leeuwen static int safexcel_skcipher_des3_ecb_cra_init(struct crypto_tfm *tfm)
166662469879SOfer Heifetz {
166793369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
166862469879SOfer Heifetz 
166993369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
167093369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_3DES;
167193369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1672098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1673098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
167493369b5dSPascal van Leeuwen 	return 0;
167562469879SOfer Heifetz }
167662469879SOfer Heifetz 
167762469879SOfer Heifetz struct safexcel_alg_template safexcel_alg_ecb_des3_ede = {
167862469879SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1679062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
168062469879SOfer Heifetz 	.alg.skcipher = {
168162469879SOfer Heifetz 		.setkey = safexcel_des3_ede_setkey,
168293369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
168393369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
168462469879SOfer Heifetz 		.min_keysize = DES3_EDE_KEY_SIZE,
168562469879SOfer Heifetz 		.max_keysize = DES3_EDE_KEY_SIZE,
168662469879SOfer Heifetz 		.base = {
168762469879SOfer Heifetz 			.cra_name = "ecb(des3_ede)",
168862469879SOfer Heifetz 			.cra_driver_name = "safexcel-ecb-des3_ede",
1689aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
16902b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
169162469879SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
169262469879SOfer Heifetz 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
169362469879SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
169462469879SOfer Heifetz 			.cra_alignmask = 0,
169593369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des3_ecb_cra_init,
169662469879SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
169762469879SOfer Heifetz 			.cra_module = THIS_MODULE,
169862469879SOfer Heifetz 		},
169962469879SOfer Heifetz 	},
170062469879SOfer Heifetz };
170162469879SOfer Heifetz 
170293369b5dSPascal van Leeuwen static int safexcel_aead_encrypt(struct aead_request *req)
1703f6beaea3SAntoine Tenart {
1704f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
1705f6beaea3SAntoine Tenart 
170693369b5dSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
1707f6beaea3SAntoine Tenart }
1708f6beaea3SAntoine Tenart 
170993369b5dSPascal van Leeuwen static int safexcel_aead_decrypt(struct aead_request *req)
1710f6beaea3SAntoine Tenart {
1711f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
1712f6beaea3SAntoine Tenart 
171393369b5dSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
1714f6beaea3SAntoine Tenart }
1715f6beaea3SAntoine Tenart 
1716f6beaea3SAntoine Tenart static int safexcel_aead_cra_init(struct crypto_tfm *tfm)
1717f6beaea3SAntoine Tenart {
1718f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1719f6beaea3SAntoine Tenart 	struct safexcel_alg_template *tmpl =
1720f6beaea3SAntoine Tenart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
1721f6beaea3SAntoine Tenart 			     alg.aead.base);
1722f6beaea3SAntoine Tenart 
1723f6beaea3SAntoine Tenart 	crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
1724f6beaea3SAntoine Tenart 				sizeof(struct safexcel_cipher_req));
1725f6beaea3SAntoine Tenart 
1726f6beaea3SAntoine Tenart 	ctx->priv = tmpl->priv;
1727f6beaea3SAntoine Tenart 
17280e17e362SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES; /* default */
1729098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
1730098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD;
1731098e51e5SPascal van Leeuwen 	ctx->ctrinit = 1;
173293369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; /* default */
1733f6beaea3SAntoine Tenart 	ctx->aead = true;
1734f6beaea3SAntoine Tenart 	ctx->base.send = safexcel_aead_send;
1735f6beaea3SAntoine Tenart 	ctx->base.handle_result = safexcel_aead_handle_result;
1736f6beaea3SAntoine Tenart 	return 0;
1737f6beaea3SAntoine Tenart }
1738f6beaea3SAntoine Tenart 
173901ba061dSAntoine Tenart static int safexcel_aead_sha1_cra_init(struct crypto_tfm *tfm)
174001ba061dSAntoine Tenart {
174101ba061dSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
174201ba061dSAntoine Tenart 
174301ba061dSAntoine Tenart 	safexcel_aead_cra_init(tfm);
1744a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
174501ba061dSAntoine Tenart 	ctx->state_sz = SHA1_DIGEST_SIZE;
174601ba061dSAntoine Tenart 	return 0;
174701ba061dSAntoine Tenart }
174801ba061dSAntoine Tenart 
174901ba061dSAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_aes = {
175001ba061dSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1751062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA1,
175201ba061dSAntoine Tenart 	.alg.aead = {
175377cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
175493369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
175593369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
175601ba061dSAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
175701ba061dSAntoine Tenart 		.maxauthsize = SHA1_DIGEST_SIZE,
175801ba061dSAntoine Tenart 		.base = {
175901ba061dSAntoine Tenart 			.cra_name = "authenc(hmac(sha1),cbc(aes))",
176001ba061dSAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-aes",
1761aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
17623f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
176301ba061dSAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
176401ba061dSAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
176501ba061dSAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
176601ba061dSAntoine Tenart 			.cra_alignmask = 0,
176701ba061dSAntoine Tenart 			.cra_init = safexcel_aead_sha1_cra_init,
176801ba061dSAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
176901ba061dSAntoine Tenart 			.cra_module = THIS_MODULE,
177001ba061dSAntoine Tenart 		},
177101ba061dSAntoine Tenart 	},
177201ba061dSAntoine Tenart };
177301ba061dSAntoine Tenart 
1774f6beaea3SAntoine Tenart static int safexcel_aead_sha256_cra_init(struct crypto_tfm *tfm)
1775f6beaea3SAntoine Tenart {
1776f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1777f6beaea3SAntoine Tenart 
1778f6beaea3SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1779a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1780f6beaea3SAntoine Tenart 	ctx->state_sz = SHA256_DIGEST_SIZE;
1781f6beaea3SAntoine Tenart 	return 0;
1782f6beaea3SAntoine Tenart }
1783f6beaea3SAntoine Tenart 
1784f6beaea3SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_aes = {
1785f6beaea3SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1786062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
1787f6beaea3SAntoine Tenart 	.alg.aead = {
178877cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
178993369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
179093369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1791f6beaea3SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1792f6beaea3SAntoine Tenart 		.maxauthsize = SHA256_DIGEST_SIZE,
1793f6beaea3SAntoine Tenart 		.base = {
1794f6beaea3SAntoine Tenart 			.cra_name = "authenc(hmac(sha256),cbc(aes))",
1795f6beaea3SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-aes",
1796aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
17973f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1798f6beaea3SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1799f6beaea3SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1800f6beaea3SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1801f6beaea3SAntoine Tenart 			.cra_alignmask = 0,
1802f6beaea3SAntoine Tenart 			.cra_init = safexcel_aead_sha256_cra_init,
1803f6beaea3SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1804f6beaea3SAntoine Tenart 			.cra_module = THIS_MODULE,
1805f6beaea3SAntoine Tenart 		},
1806f6beaea3SAntoine Tenart 	},
1807f6beaea3SAntoine Tenart };
1808678b2878SAntoine Tenart 
1809678b2878SAntoine Tenart static int safexcel_aead_sha224_cra_init(struct crypto_tfm *tfm)
1810678b2878SAntoine Tenart {
1811678b2878SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1812678b2878SAntoine Tenart 
1813678b2878SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1814a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1815678b2878SAntoine Tenart 	ctx->state_sz = SHA256_DIGEST_SIZE;
1816678b2878SAntoine Tenart 	return 0;
1817678b2878SAntoine Tenart }
1818678b2878SAntoine Tenart 
1819678b2878SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_aes = {
1820678b2878SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1821062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
1822678b2878SAntoine Tenart 	.alg.aead = {
182377cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
182493369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
182593369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1826678b2878SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1827678b2878SAntoine Tenart 		.maxauthsize = SHA224_DIGEST_SIZE,
1828678b2878SAntoine Tenart 		.base = {
1829678b2878SAntoine Tenart 			.cra_name = "authenc(hmac(sha224),cbc(aes))",
1830678b2878SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-aes",
1831aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18323f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1833678b2878SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1834678b2878SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1835678b2878SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1836678b2878SAntoine Tenart 			.cra_alignmask = 0,
1837678b2878SAntoine Tenart 			.cra_init = safexcel_aead_sha224_cra_init,
1838678b2878SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1839678b2878SAntoine Tenart 			.cra_module = THIS_MODULE,
1840678b2878SAntoine Tenart 		},
1841678b2878SAntoine Tenart 	},
1842678b2878SAntoine Tenart };
184387eee125SAntoine Tenart 
184487eee125SAntoine Tenart static int safexcel_aead_sha512_cra_init(struct crypto_tfm *tfm)
184587eee125SAntoine Tenart {
184687eee125SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
184787eee125SAntoine Tenart 
184887eee125SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1849a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
185087eee125SAntoine Tenart 	ctx->state_sz = SHA512_DIGEST_SIZE;
185187eee125SAntoine Tenart 	return 0;
185287eee125SAntoine Tenart }
185387eee125SAntoine Tenart 
185487eee125SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_aes = {
185587eee125SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1856062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
185787eee125SAntoine Tenart 	.alg.aead = {
185877cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
185993369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
186093369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
186187eee125SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
186287eee125SAntoine Tenart 		.maxauthsize = SHA512_DIGEST_SIZE,
186387eee125SAntoine Tenart 		.base = {
186487eee125SAntoine Tenart 			.cra_name = "authenc(hmac(sha512),cbc(aes))",
186587eee125SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-aes",
1866aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18673f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
186887eee125SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
186987eee125SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
187087eee125SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
187187eee125SAntoine Tenart 			.cra_alignmask = 0,
187287eee125SAntoine Tenart 			.cra_init = safexcel_aead_sha512_cra_init,
187387eee125SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
187487eee125SAntoine Tenart 			.cra_module = THIS_MODULE,
187587eee125SAntoine Tenart 		},
187687eee125SAntoine Tenart 	},
187787eee125SAntoine Tenart };
1878ea23cb53SAntoine Tenart 
1879ea23cb53SAntoine Tenart static int safexcel_aead_sha384_cra_init(struct crypto_tfm *tfm)
1880ea23cb53SAntoine Tenart {
1881ea23cb53SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1882ea23cb53SAntoine Tenart 
1883ea23cb53SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1884a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
1885ea23cb53SAntoine Tenart 	ctx->state_sz = SHA512_DIGEST_SIZE;
1886ea23cb53SAntoine Tenart 	return 0;
1887ea23cb53SAntoine Tenart }
1888ea23cb53SAntoine Tenart 
1889ea23cb53SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_aes = {
1890ea23cb53SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1891062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
1892ea23cb53SAntoine Tenart 	.alg.aead = {
189377cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
189493369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
189593369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1896ea23cb53SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1897ea23cb53SAntoine Tenart 		.maxauthsize = SHA384_DIGEST_SIZE,
1898ea23cb53SAntoine Tenart 		.base = {
1899ea23cb53SAntoine Tenart 			.cra_name = "authenc(hmac(sha384),cbc(aes))",
1900ea23cb53SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-aes",
1901aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
19023f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1903ea23cb53SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1904ea23cb53SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1905ea23cb53SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1906ea23cb53SAntoine Tenart 			.cra_alignmask = 0,
1907ea23cb53SAntoine Tenart 			.cra_init = safexcel_aead_sha384_cra_init,
1908ea23cb53SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1909ea23cb53SAntoine Tenart 			.cra_module = THIS_MODULE,
1910ea23cb53SAntoine Tenart 		},
1911ea23cb53SAntoine Tenart 	},
1912ea23cb53SAntoine Tenart };
191377cdd4efSPascal van Leeuwen 
19140e17e362SPascal van Leeuwen static int safexcel_aead_sha1_des3_cra_init(struct crypto_tfm *tfm)
19150e17e362SPascal van Leeuwen {
19160e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
19170e17e362SPascal van Leeuwen 
19180e17e362SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
19190e17e362SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1920098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1921098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
19220e17e362SPascal van Leeuwen 	return 0;
19230e17e362SPascal van Leeuwen }
19240e17e362SPascal van Leeuwen 
192577cdd4efSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des3_ede = {
192677cdd4efSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1927062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1,
192877cdd4efSPascal van Leeuwen 	.alg.aead = {
192977cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
193093369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
193193369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
193277cdd4efSPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
193377cdd4efSPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
193477cdd4efSPascal van Leeuwen 		.base = {
193577cdd4efSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
193677cdd4efSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des3_ede",
1937aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
193877cdd4efSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
193977cdd4efSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
194077cdd4efSPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
194177cdd4efSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
194277cdd4efSPascal van Leeuwen 			.cra_alignmask = 0,
19430e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_des3_cra_init,
19440e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
19450e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
19460e17e362SPascal van Leeuwen 		},
19470e17e362SPascal van Leeuwen 	},
19480e17e362SPascal van Leeuwen };
19490e17e362SPascal van Leeuwen 
1950f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha256_des3_cra_init(struct crypto_tfm *tfm)
1951f0a8bdf0SPascal van Leeuwen {
1952f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1953f0a8bdf0SPascal van Leeuwen 
1954f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
1955f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1956098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1957098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
1958f0a8bdf0SPascal van Leeuwen 	return 0;
1959f0a8bdf0SPascal van Leeuwen }
1960f0a8bdf0SPascal van Leeuwen 
1961f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des3_ede = {
1962f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1963f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
1964f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
1965f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
1966f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
1967f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1968f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
1969f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
1970f0a8bdf0SPascal van Leeuwen 		.base = {
1971f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
1972f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des3_ede",
1973f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
1974f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1975f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1976f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1977f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1978f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
1979f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_des3_cra_init,
1980f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
1981f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
1982f0a8bdf0SPascal van Leeuwen 		},
1983f0a8bdf0SPascal van Leeuwen 	},
1984f0a8bdf0SPascal van Leeuwen };
1985f0a8bdf0SPascal van Leeuwen 
1986f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha224_des3_cra_init(struct crypto_tfm *tfm)
1987f0a8bdf0SPascal van Leeuwen {
1988f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1989f0a8bdf0SPascal van Leeuwen 
1990f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
1991f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1992098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1993098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
1994f0a8bdf0SPascal van Leeuwen 	return 0;
1995f0a8bdf0SPascal van Leeuwen }
1996f0a8bdf0SPascal van Leeuwen 
1997f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des3_ede = {
1998f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1999f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2000f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2001f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2002f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2003f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2004f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2005f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
2006f0a8bdf0SPascal van Leeuwen 		.base = {
2007f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),cbc(des3_ede))",
2008f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des3_ede",
2009f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2010f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2011f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2012f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2013f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2014f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2015f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_des3_cra_init,
2016f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2017f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2018f0a8bdf0SPascal van Leeuwen 		},
2019f0a8bdf0SPascal van Leeuwen 	},
2020f0a8bdf0SPascal van Leeuwen };
2021f0a8bdf0SPascal van Leeuwen 
2022f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha512_des3_cra_init(struct crypto_tfm *tfm)
2023f0a8bdf0SPascal van Leeuwen {
2024f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2025f0a8bdf0SPascal van Leeuwen 
2026f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
2027f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
2028098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
2029098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2030f0a8bdf0SPascal van Leeuwen 	return 0;
2031f0a8bdf0SPascal van Leeuwen }
2032f0a8bdf0SPascal van Leeuwen 
2033f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des3_ede = {
2034f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2035f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2036f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2037f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2038f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2039f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2040f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2041f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
2042f0a8bdf0SPascal van Leeuwen 		.base = {
2043f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),cbc(des3_ede))",
2044f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des3_ede",
2045f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2046f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2047f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2048f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2049f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2050f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2051f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_des3_cra_init,
2052f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2053f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2054f0a8bdf0SPascal van Leeuwen 		},
2055f0a8bdf0SPascal van Leeuwen 	},
2056f0a8bdf0SPascal van Leeuwen };
2057f0a8bdf0SPascal van Leeuwen 
2058f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha384_des3_cra_init(struct crypto_tfm *tfm)
2059f0a8bdf0SPascal van Leeuwen {
2060f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2061f0a8bdf0SPascal van Leeuwen 
2062f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
2063f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
2064098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
2065098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2066f0a8bdf0SPascal van Leeuwen 	return 0;
2067f0a8bdf0SPascal van Leeuwen }
2068f0a8bdf0SPascal van Leeuwen 
2069f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des3_ede = {
2070f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2071f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2072f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2073f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2074f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2075f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2076f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2077f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
2078f0a8bdf0SPascal van Leeuwen 		.base = {
2079f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),cbc(des3_ede))",
2080f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des3_ede",
2081f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2082f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2083f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2084f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2085f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2086f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2087f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_des3_cra_init,
2088f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2089f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2090f0a8bdf0SPascal van Leeuwen 		},
2091f0a8bdf0SPascal van Leeuwen 	},
2092f0a8bdf0SPascal van Leeuwen };
2093f0a8bdf0SPascal van Leeuwen 
2094bb7679b8SPascal van Leeuwen static int safexcel_aead_sha1_des_cra_init(struct crypto_tfm *tfm)
2095bb7679b8SPascal van Leeuwen {
2096bb7679b8SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2097bb7679b8SPascal van Leeuwen 
2098bb7679b8SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
2099bb7679b8SPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2100098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2101098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2102bb7679b8SPascal van Leeuwen 	return 0;
2103bb7679b8SPascal van Leeuwen }
2104bb7679b8SPascal van Leeuwen 
2105bb7679b8SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des = {
2106bb7679b8SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2107bb7679b8SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1,
2108bb7679b8SPascal van Leeuwen 	.alg.aead = {
2109bb7679b8SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2110bb7679b8SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2111bb7679b8SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2112bb7679b8SPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2113bb7679b8SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
2114bb7679b8SPascal van Leeuwen 		.base = {
2115bb7679b8SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(des))",
2116bb7679b8SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des",
2117bb7679b8SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2118bb7679b8SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2119bb7679b8SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2120bb7679b8SPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2121bb7679b8SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2122bb7679b8SPascal van Leeuwen 			.cra_alignmask = 0,
2123bb7679b8SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_des_cra_init,
2124bb7679b8SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2125bb7679b8SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2126bb7679b8SPascal van Leeuwen 		},
2127bb7679b8SPascal van Leeuwen 	},
2128bb7679b8SPascal van Leeuwen };
2129bb7679b8SPascal van Leeuwen 
2130457a6fdfSPascal van Leeuwen static int safexcel_aead_sha256_des_cra_init(struct crypto_tfm *tfm)
2131457a6fdfSPascal van Leeuwen {
2132457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2133457a6fdfSPascal van Leeuwen 
2134457a6fdfSPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
2135457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2136098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2137098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2138457a6fdfSPascal van Leeuwen 	return 0;
2139457a6fdfSPascal van Leeuwen }
2140457a6fdfSPascal van Leeuwen 
2141457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des = {
2142457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2143457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2144457a6fdfSPascal van Leeuwen 	.alg.aead = {
2145457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2146457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2147457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2148457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2149457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
2150457a6fdfSPascal van Leeuwen 		.base = {
2151457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),cbc(des))",
2152457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des",
2153457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2154457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2155457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2156457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2157457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2158457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2159457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_des_cra_init,
2160457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2161457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2162457a6fdfSPascal van Leeuwen 		},
2163457a6fdfSPascal van Leeuwen 	},
2164457a6fdfSPascal van Leeuwen };
2165457a6fdfSPascal van Leeuwen 
2166457a6fdfSPascal van Leeuwen static int safexcel_aead_sha224_des_cra_init(struct crypto_tfm *tfm)
2167457a6fdfSPascal van Leeuwen {
2168457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2169457a6fdfSPascal van Leeuwen 
2170457a6fdfSPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
2171457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2172098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2173098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2174457a6fdfSPascal van Leeuwen 	return 0;
2175457a6fdfSPascal van Leeuwen }
2176457a6fdfSPascal van Leeuwen 
2177457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des = {
2178457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2179457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2180457a6fdfSPascal van Leeuwen 	.alg.aead = {
2181457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2182457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2183457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2184457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2185457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
2186457a6fdfSPascal van Leeuwen 		.base = {
2187457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),cbc(des))",
2188457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des",
2189457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2190457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2191457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2192457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2193457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2194457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2195457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_des_cra_init,
2196457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2197457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2198457a6fdfSPascal van Leeuwen 		},
2199457a6fdfSPascal van Leeuwen 	},
2200457a6fdfSPascal van Leeuwen };
2201457a6fdfSPascal van Leeuwen 
2202457a6fdfSPascal van Leeuwen static int safexcel_aead_sha512_des_cra_init(struct crypto_tfm *tfm)
2203457a6fdfSPascal van Leeuwen {
2204457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2205457a6fdfSPascal van Leeuwen 
2206457a6fdfSPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
2207457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2208098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2209098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2210457a6fdfSPascal van Leeuwen 	return 0;
2211457a6fdfSPascal van Leeuwen }
2212457a6fdfSPascal van Leeuwen 
2213457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des = {
2214457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2215457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2216457a6fdfSPascal van Leeuwen 	.alg.aead = {
2217457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2218457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2219457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2220457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2221457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
2222457a6fdfSPascal van Leeuwen 		.base = {
2223457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),cbc(des))",
2224457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des",
2225457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2226457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2227457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2228457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2229457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2230457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2231457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_des_cra_init,
2232457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2233457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2234457a6fdfSPascal van Leeuwen 		},
2235457a6fdfSPascal van Leeuwen 	},
2236457a6fdfSPascal van Leeuwen };
2237457a6fdfSPascal van Leeuwen 
2238457a6fdfSPascal van Leeuwen static int safexcel_aead_sha384_des_cra_init(struct crypto_tfm *tfm)
2239457a6fdfSPascal van Leeuwen {
2240457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2241457a6fdfSPascal van Leeuwen 
2242457a6fdfSPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
2243457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2244098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2245098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2246457a6fdfSPascal van Leeuwen 	return 0;
2247457a6fdfSPascal van Leeuwen }
2248457a6fdfSPascal van Leeuwen 
2249457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des = {
2250457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2251457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2252457a6fdfSPascal van Leeuwen 	.alg.aead = {
2253457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2254457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2255457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2256457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2257457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
2258457a6fdfSPascal van Leeuwen 		.base = {
2259457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),cbc(des))",
2260457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des",
2261457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2262457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2263457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2264457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2265457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2266457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2267457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_des_cra_init,
2268457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2269457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2270457a6fdfSPascal van Leeuwen 		},
2271457a6fdfSPascal van Leeuwen 	},
2272457a6fdfSPascal van Leeuwen };
2273457a6fdfSPascal van Leeuwen 
22740e17e362SPascal van Leeuwen static int safexcel_aead_sha1_ctr_cra_init(struct crypto_tfm *tfm)
22750e17e362SPascal van Leeuwen {
22760e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
22770e17e362SPascal van Leeuwen 
22780e17e362SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
22790e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
22800e17e362SPascal van Leeuwen 	return 0;
22810e17e362SPascal van Leeuwen }
22820e17e362SPascal van Leeuwen 
22830e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_aes = {
22840e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2285062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA1,
22860e17e362SPascal van Leeuwen 	.alg.aead = {
22870e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
228893369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
228993369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2290f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
22910e17e362SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
22920e17e362SPascal van Leeuwen 		.base = {
22930e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
22940e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-aes",
2295aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
22960e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
22970e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
22980e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
22990e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23000e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23010e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_ctr_cra_init,
23020e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23030e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23040e17e362SPascal van Leeuwen 		},
23050e17e362SPascal van Leeuwen 	},
23060e17e362SPascal van Leeuwen };
23070e17e362SPascal van Leeuwen 
23080e17e362SPascal van Leeuwen static int safexcel_aead_sha256_ctr_cra_init(struct crypto_tfm *tfm)
23090e17e362SPascal van Leeuwen {
23100e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23110e17e362SPascal van Leeuwen 
23120e17e362SPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
23130e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23140e17e362SPascal van Leeuwen 	return 0;
23150e17e362SPascal van Leeuwen }
23160e17e362SPascal van Leeuwen 
23170e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_ctr_aes = {
23180e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2319062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
23200e17e362SPascal van Leeuwen 	.alg.aead = {
23210e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
232293369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
232393369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2324f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23250e17e362SPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
23260e17e362SPascal van Leeuwen 		.base = {
23270e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
23280e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-ctr-aes",
2329aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23300e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
23310e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23320e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23330e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23340e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23350e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_ctr_cra_init,
23360e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23370e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23380e17e362SPascal van Leeuwen 		},
23390e17e362SPascal van Leeuwen 	},
23400e17e362SPascal van Leeuwen };
23410e17e362SPascal van Leeuwen 
23420e17e362SPascal van Leeuwen static int safexcel_aead_sha224_ctr_cra_init(struct crypto_tfm *tfm)
23430e17e362SPascal van Leeuwen {
23440e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23450e17e362SPascal van Leeuwen 
23460e17e362SPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
23470e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23480e17e362SPascal van Leeuwen 	return 0;
23490e17e362SPascal van Leeuwen }
23500e17e362SPascal van Leeuwen 
23510e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_ctr_aes = {
23520e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2353062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
23540e17e362SPascal van Leeuwen 	.alg.aead = {
23550e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
235693369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
235793369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2358f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23590e17e362SPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
23600e17e362SPascal van Leeuwen 		.base = {
23610e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))",
23620e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-ctr-aes",
2363aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23640e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
23650e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23660e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23670e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23680e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23690e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_ctr_cra_init,
23700e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23710e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23720e17e362SPascal van Leeuwen 		},
23730e17e362SPascal van Leeuwen 	},
23740e17e362SPascal van Leeuwen };
23750e17e362SPascal van Leeuwen 
23760e17e362SPascal van Leeuwen static int safexcel_aead_sha512_ctr_cra_init(struct crypto_tfm *tfm)
23770e17e362SPascal van Leeuwen {
23780e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23790e17e362SPascal van Leeuwen 
23800e17e362SPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
23810e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23820e17e362SPascal van Leeuwen 	return 0;
23830e17e362SPascal van Leeuwen }
23840e17e362SPascal van Leeuwen 
23850e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_ctr_aes = {
23860e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2387062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
23880e17e362SPascal van Leeuwen 	.alg.aead = {
23890e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
239093369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
239193369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2392f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23930e17e362SPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
23940e17e362SPascal van Leeuwen 		.base = {
23950e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
23960e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-ctr-aes",
2397aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23980e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
23990e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
24000e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
24010e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
24020e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
24030e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_ctr_cra_init,
24040e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
24050e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
24060e17e362SPascal van Leeuwen 		},
24070e17e362SPascal van Leeuwen 	},
24080e17e362SPascal van Leeuwen };
24090e17e362SPascal van Leeuwen 
24100e17e362SPascal van Leeuwen static int safexcel_aead_sha384_ctr_cra_init(struct crypto_tfm *tfm)
24110e17e362SPascal van Leeuwen {
24120e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
24130e17e362SPascal van Leeuwen 
24140e17e362SPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
24150e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
24160e17e362SPascal van Leeuwen 	return 0;
24170e17e362SPascal van Leeuwen }
24180e17e362SPascal van Leeuwen 
24190e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_ctr_aes = {
24200e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2421062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
24220e17e362SPascal van Leeuwen 	.alg.aead = {
24230e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
242493369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
242593369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2426f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
24270e17e362SPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
24280e17e362SPascal van Leeuwen 		.base = {
24290e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
24300e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-ctr-aes",
2431aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
24320e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
24330e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
24340e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
24350e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
24360e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
24370e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_ctr_cra_init,
243877cdd4efSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
243977cdd4efSPascal van Leeuwen 			.cra_module = THIS_MODULE,
244077cdd4efSPascal van Leeuwen 		},
244177cdd4efSPascal van Leeuwen 	},
244277cdd4efSPascal van Leeuwen };
2443c7da38a7SPascal van Leeuwen 
2444c7da38a7SPascal van Leeuwen static int safexcel_skcipher_aesxts_setkey(struct crypto_skcipher *ctfm,
2445c7da38a7SPascal van Leeuwen 					   const u8 *key, unsigned int len)
2446c7da38a7SPascal van Leeuwen {
2447c7da38a7SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
2448c7da38a7SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2449c7da38a7SPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
2450c7da38a7SPascal van Leeuwen 	struct crypto_aes_ctx aes;
2451c7da38a7SPascal van Leeuwen 	int ret, i;
2452c7da38a7SPascal van Leeuwen 	unsigned int keylen;
2453c7da38a7SPascal van Leeuwen 
2454c7da38a7SPascal van Leeuwen 	/* Check for illegal XTS keys */
2455c7da38a7SPascal van Leeuwen 	ret = xts_verify_key(ctfm, key, len);
2456c7da38a7SPascal van Leeuwen 	if (ret)
2457c7da38a7SPascal van Leeuwen 		return ret;
2458c7da38a7SPascal van Leeuwen 
2459c7da38a7SPascal van Leeuwen 	/* Only half of the key data is cipher key */
2460c7da38a7SPascal van Leeuwen 	keylen = (len >> 1);
2461c7da38a7SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, keylen);
2462c7da38a7SPascal van Leeuwen 	if (ret) {
2463c7da38a7SPascal van Leeuwen 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2464c7da38a7SPascal van Leeuwen 		return ret;
2465c7da38a7SPascal van Leeuwen 	}
2466c7da38a7SPascal van Leeuwen 
2467c7da38a7SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
2468c7da38a7SPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
246913a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
2470c7da38a7SPascal van Leeuwen 				ctx->base.needs_inv = true;
2471c7da38a7SPascal van Leeuwen 				break;
2472c7da38a7SPascal van Leeuwen 			}
2473c7da38a7SPascal van Leeuwen 		}
2474c7da38a7SPascal van Leeuwen 	}
2475c7da38a7SPascal van Leeuwen 
2476c7da38a7SPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
2477c7da38a7SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
2478c7da38a7SPascal van Leeuwen 
2479c7da38a7SPascal van Leeuwen 	/* The other half is the tweak key */
2480c7da38a7SPascal van Leeuwen 	ret = aes_expandkey(&aes, (u8 *)(key + keylen), keylen);
2481c7da38a7SPascal van Leeuwen 	if (ret) {
2482c7da38a7SPascal van Leeuwen 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2483c7da38a7SPascal van Leeuwen 		return ret;
2484c7da38a7SPascal van Leeuwen 	}
2485c7da38a7SPascal van Leeuwen 
2486c7da38a7SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
2487c7da38a7SPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
248813a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i + keylen / sizeof(u32)]) !=
248913a1bb93SPascal van Leeuwen 			    aes.key_enc[i]) {
2490c7da38a7SPascal van Leeuwen 				ctx->base.needs_inv = true;
2491c7da38a7SPascal van Leeuwen 				break;
2492c7da38a7SPascal van Leeuwen 			}
2493c7da38a7SPascal van Leeuwen 		}
2494c7da38a7SPascal van Leeuwen 	}
2495c7da38a7SPascal van Leeuwen 
2496c7da38a7SPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
2497c7da38a7SPascal van Leeuwen 		ctx->key[i + keylen / sizeof(u32)] =
2498c7da38a7SPascal van Leeuwen 			cpu_to_le32(aes.key_enc[i]);
2499c7da38a7SPascal van Leeuwen 
2500c7da38a7SPascal van Leeuwen 	ctx->key_len = keylen << 1;
2501c7da38a7SPascal van Leeuwen 
2502c7da38a7SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
2503c7da38a7SPascal van Leeuwen 	return 0;
2504c7da38a7SPascal van Leeuwen }
2505c7da38a7SPascal van Leeuwen 
2506c7da38a7SPascal van Leeuwen static int safexcel_skcipher_aes_xts_cra_init(struct crypto_tfm *tfm)
2507c7da38a7SPascal van Leeuwen {
2508c7da38a7SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2509c7da38a7SPascal van Leeuwen 
2510c7da38a7SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
2511c7da38a7SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
2512098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
2513c7da38a7SPascal van Leeuwen 	ctx->xts  = 1;
2514c7da38a7SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XTS;
2515c7da38a7SPascal van Leeuwen 	return 0;
2516c7da38a7SPascal van Leeuwen }
2517c7da38a7SPascal van Leeuwen 
2518c7da38a7SPascal van Leeuwen static int safexcel_encrypt_xts(struct skcipher_request *req)
2519c7da38a7SPascal van Leeuwen {
2520c7da38a7SPascal van Leeuwen 	if (req->cryptlen < XTS_BLOCK_SIZE)
2521c7da38a7SPascal van Leeuwen 		return -EINVAL;
2522c7da38a7SPascal van Leeuwen 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2523c7da38a7SPascal van Leeuwen 				  SAFEXCEL_ENCRYPT);
2524c7da38a7SPascal van Leeuwen }
2525c7da38a7SPascal van Leeuwen 
2526c7da38a7SPascal van Leeuwen static int safexcel_decrypt_xts(struct skcipher_request *req)
2527c7da38a7SPascal van Leeuwen {
2528c7da38a7SPascal van Leeuwen 	if (req->cryptlen < XTS_BLOCK_SIZE)
2529c7da38a7SPascal van Leeuwen 		return -EINVAL;
2530c7da38a7SPascal van Leeuwen 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2531c7da38a7SPascal van Leeuwen 				  SAFEXCEL_DECRYPT);
2532c7da38a7SPascal van Leeuwen }
2533c7da38a7SPascal van Leeuwen 
2534c7da38a7SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xts_aes = {
2535c7da38a7SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
2536062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XTS,
2537c7da38a7SPascal van Leeuwen 	.alg.skcipher = {
2538c7da38a7SPascal van Leeuwen 		.setkey = safexcel_skcipher_aesxts_setkey,
2539c7da38a7SPascal van Leeuwen 		.encrypt = safexcel_encrypt_xts,
2540c7da38a7SPascal van Leeuwen 		.decrypt = safexcel_decrypt_xts,
2541c7da38a7SPascal van Leeuwen 		/* XTS actually uses 2 AES keys glued together */
2542c7da38a7SPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE * 2,
2543c7da38a7SPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE * 2,
2544c7da38a7SPascal van Leeuwen 		.ivsize = XTS_BLOCK_SIZE,
2545c7da38a7SPascal van Leeuwen 		.base = {
2546c7da38a7SPascal van Leeuwen 			.cra_name = "xts(aes)",
2547c7da38a7SPascal van Leeuwen 			.cra_driver_name = "safexcel-xts-aes",
2548aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2549c7da38a7SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2550c7da38a7SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2551c7da38a7SPascal van Leeuwen 			.cra_blocksize = XTS_BLOCK_SIZE,
2552c7da38a7SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2553c7da38a7SPascal van Leeuwen 			.cra_alignmask = 0,
2554c7da38a7SPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_xts_cra_init,
2555c7da38a7SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
2556c7da38a7SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2557c7da38a7SPascal van Leeuwen 		},
2558c7da38a7SPascal van Leeuwen 	},
2559c7da38a7SPascal van Leeuwen };
25603e450886SPascal van Leeuwen 
25613e450886SPascal van Leeuwen static int safexcel_aead_gcm_setkey(struct crypto_aead *ctfm, const u8 *key,
25623e450886SPascal van Leeuwen 				    unsigned int len)
25633e450886SPascal van Leeuwen {
25643e450886SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
25653e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
25663e450886SPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
25673e450886SPascal van Leeuwen 	struct crypto_aes_ctx aes;
25683e450886SPascal van Leeuwen 	u32 hashkey[AES_BLOCK_SIZE >> 2];
25693e450886SPascal van Leeuwen 	int ret, i;
25703e450886SPascal van Leeuwen 
25713e450886SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
25723e450886SPascal van Leeuwen 	if (ret) {
25733e450886SPascal van Leeuwen 		crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
25743e450886SPascal van Leeuwen 		memzero_explicit(&aes, sizeof(aes));
25753e450886SPascal van Leeuwen 		return ret;
25763e450886SPascal van Leeuwen 	}
25773e450886SPascal van Leeuwen 
25783e450886SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
25793e450886SPascal van Leeuwen 		for (i = 0; i < len / sizeof(u32); i++) {
258013a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
25813e450886SPascal van Leeuwen 				ctx->base.needs_inv = true;
25823e450886SPascal van Leeuwen 				break;
25833e450886SPascal van Leeuwen 			}
25843e450886SPascal van Leeuwen 		}
25853e450886SPascal van Leeuwen 	}
25863e450886SPascal van Leeuwen 
25873e450886SPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
25883e450886SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
25893e450886SPascal van Leeuwen 
25903e450886SPascal van Leeuwen 	ctx->key_len = len;
25913e450886SPascal van Leeuwen 
25923e450886SPascal van Leeuwen 	/* Compute hash key by encrypting zeroes with cipher key */
25933e450886SPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->hkaes, CRYPTO_TFM_REQ_MASK);
25943e450886SPascal van Leeuwen 	crypto_cipher_set_flags(ctx->hkaes, crypto_aead_get_flags(ctfm) &
25953e450886SPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
25963e450886SPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->hkaes, key, len);
25973e450886SPascal van Leeuwen 	crypto_aead_set_flags(ctfm, crypto_cipher_get_flags(ctx->hkaes) &
25983e450886SPascal van Leeuwen 			      CRYPTO_TFM_RES_MASK);
25993e450886SPascal van Leeuwen 	if (ret)
26003e450886SPascal van Leeuwen 		return ret;
26013e450886SPascal van Leeuwen 
26023e450886SPascal van Leeuwen 	memset(hashkey, 0, AES_BLOCK_SIZE);
26033e450886SPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->hkaes, (u8 *)hashkey, (u8 *)hashkey);
26043e450886SPascal van Leeuwen 
26053e450886SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
26063e450886SPascal van Leeuwen 		for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) {
260713a1bb93SPascal van Leeuwen 			if (be32_to_cpu(ctx->ipad[i]) != hashkey[i]) {
26083e450886SPascal van Leeuwen 				ctx->base.needs_inv = true;
26093e450886SPascal van Leeuwen 				break;
26103e450886SPascal van Leeuwen 			}
26113e450886SPascal van Leeuwen 		}
26123e450886SPascal van Leeuwen 	}
26133e450886SPascal van Leeuwen 
26143e450886SPascal van Leeuwen 	for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
26153e450886SPascal van Leeuwen 		ctx->ipad[i] = cpu_to_be32(hashkey[i]);
26163e450886SPascal van Leeuwen 
26173e450886SPascal van Leeuwen 	memzero_explicit(hashkey, AES_BLOCK_SIZE);
26183e450886SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
26193e450886SPascal van Leeuwen 	return 0;
26203e450886SPascal van Leeuwen }
26213e450886SPascal van Leeuwen 
26223e450886SPascal van Leeuwen static int safexcel_aead_gcm_cra_init(struct crypto_tfm *tfm)
26233e450886SPascal van Leeuwen {
26243e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
26253e450886SPascal van Leeuwen 
26263e450886SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
26273e450886SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_GHASH;
26283e450886SPascal van Leeuwen 	ctx->state_sz = GHASH_BLOCK_SIZE;
26294eb76fafSPascal van Leeuwen 	ctx->xcm = EIP197_XCM_MODE_GCM;
26303e450886SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */
26313e450886SPascal van Leeuwen 
26323e450886SPascal van Leeuwen 	ctx->hkaes = crypto_alloc_cipher("aes", 0, 0);
26333f61b052Szhengbin 	return PTR_ERR_OR_ZERO(ctx->hkaes);
26343e450886SPascal van Leeuwen }
26353e450886SPascal van Leeuwen 
26363e450886SPascal van Leeuwen static void safexcel_aead_gcm_cra_exit(struct crypto_tfm *tfm)
26373e450886SPascal van Leeuwen {
26383e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
26393e450886SPascal van Leeuwen 
26403e450886SPascal van Leeuwen 	crypto_free_cipher(ctx->hkaes);
26413e450886SPascal van Leeuwen 	safexcel_aead_cra_exit(tfm);
26423e450886SPascal van Leeuwen }
26433e450886SPascal van Leeuwen 
26443e450886SPascal van Leeuwen static int safexcel_aead_gcm_setauthsize(struct crypto_aead *tfm,
26453e450886SPascal van Leeuwen 					 unsigned int authsize)
26463e450886SPascal van Leeuwen {
26473e450886SPascal van Leeuwen 	return crypto_gcm_check_authsize(authsize);
26483e450886SPascal van Leeuwen }
26493e450886SPascal van Leeuwen 
26503e450886SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_gcm = {
26513e450886SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
26523e450886SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
26533e450886SPascal van Leeuwen 	.alg.aead = {
26543e450886SPascal van Leeuwen 		.setkey = safexcel_aead_gcm_setkey,
26553e450886SPascal van Leeuwen 		.setauthsize = safexcel_aead_gcm_setauthsize,
26563e450886SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
26573e450886SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
26583e450886SPascal van Leeuwen 		.ivsize = GCM_AES_IV_SIZE,
26593e450886SPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
26603e450886SPascal van Leeuwen 		.base = {
26613e450886SPascal van Leeuwen 			.cra_name = "gcm(aes)",
26623e450886SPascal van Leeuwen 			.cra_driver_name = "safexcel-gcm-aes",
26633e450886SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
26643e450886SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
26653e450886SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
26663e450886SPascal van Leeuwen 			.cra_blocksize = 1,
26673e450886SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
26683e450886SPascal van Leeuwen 			.cra_alignmask = 0,
26693e450886SPascal van Leeuwen 			.cra_init = safexcel_aead_gcm_cra_init,
26703e450886SPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
26713e450886SPascal van Leeuwen 			.cra_module = THIS_MODULE,
26723e450886SPascal van Leeuwen 		},
26733e450886SPascal van Leeuwen 	},
26743e450886SPascal van Leeuwen };
26754eb76fafSPascal van Leeuwen 
26764eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_setkey(struct crypto_aead *ctfm, const u8 *key,
26774eb76fafSPascal van Leeuwen 				    unsigned int len)
26784eb76fafSPascal van Leeuwen {
26794eb76fafSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
26804eb76fafSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
26814eb76fafSPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
26824eb76fafSPascal van Leeuwen 	struct crypto_aes_ctx aes;
26834eb76fafSPascal van Leeuwen 	int ret, i;
26844eb76fafSPascal van Leeuwen 
26854eb76fafSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
26864eb76fafSPascal van Leeuwen 	if (ret) {
26874eb76fafSPascal van Leeuwen 		crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
26884eb76fafSPascal van Leeuwen 		memzero_explicit(&aes, sizeof(aes));
26894eb76fafSPascal van Leeuwen 		return ret;
26904eb76fafSPascal van Leeuwen 	}
26914eb76fafSPascal van Leeuwen 
26924eb76fafSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
26934eb76fafSPascal van Leeuwen 		for (i = 0; i < len / sizeof(u32); i++) {
269413a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
26954eb76fafSPascal van Leeuwen 				ctx->base.needs_inv = true;
26964eb76fafSPascal van Leeuwen 				break;
26974eb76fafSPascal van Leeuwen 			}
26984eb76fafSPascal van Leeuwen 		}
26994eb76fafSPascal van Leeuwen 	}
27004eb76fafSPascal van Leeuwen 
27014eb76fafSPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++) {
27024eb76fafSPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
27034eb76fafSPascal van Leeuwen 		ctx->ipad[i + 2 * AES_BLOCK_SIZE / sizeof(u32)] =
27044eb76fafSPascal van Leeuwen 			cpu_to_be32(aes.key_enc[i]);
27054eb76fafSPascal van Leeuwen 	}
27064eb76fafSPascal van Leeuwen 
27074eb76fafSPascal van Leeuwen 	ctx->key_len = len;
27084eb76fafSPascal van Leeuwen 	ctx->state_sz = 2 * AES_BLOCK_SIZE + len;
27094eb76fafSPascal van Leeuwen 
27104eb76fafSPascal van Leeuwen 	if (len == AES_KEYSIZE_192)
27114eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
27124eb76fafSPascal van Leeuwen 	else if (len == AES_KEYSIZE_256)
27134eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
27144eb76fafSPascal van Leeuwen 	else
27154eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
27164eb76fafSPascal van Leeuwen 
27174eb76fafSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
27184eb76fafSPascal van Leeuwen 	return 0;
27194eb76fafSPascal van Leeuwen }
27204eb76fafSPascal van Leeuwen 
27214eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_cra_init(struct crypto_tfm *tfm)
27224eb76fafSPascal van Leeuwen {
27234eb76fafSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
27244eb76fafSPascal van Leeuwen 
27254eb76fafSPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
27264eb76fafSPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
27274eb76fafSPascal van Leeuwen 	ctx->state_sz = 3 * AES_BLOCK_SIZE;
27284eb76fafSPascal van Leeuwen 	ctx->xcm = EIP197_XCM_MODE_CCM;
27294eb76fafSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */
2730098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
27314eb76fafSPascal van Leeuwen 	return 0;
27324eb76fafSPascal van Leeuwen }
27334eb76fafSPascal van Leeuwen 
27344eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_setauthsize(struct crypto_aead *tfm,
27354eb76fafSPascal van Leeuwen 					 unsigned int authsize)
27364eb76fafSPascal van Leeuwen {
27374eb76fafSPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
27384eb76fafSPascal van Leeuwen 	switch (authsize) {
27394eb76fafSPascal van Leeuwen 	case 4:
27404eb76fafSPascal van Leeuwen 	case 6:
27414eb76fafSPascal van Leeuwen 	case 8:
27424eb76fafSPascal van Leeuwen 	case 10:
27434eb76fafSPascal van Leeuwen 	case 12:
27444eb76fafSPascal van Leeuwen 	case 14:
27454eb76fafSPascal van Leeuwen 	case 16:
27464eb76fafSPascal van Leeuwen 		break;
27474eb76fafSPascal van Leeuwen 	default:
27484eb76fafSPascal van Leeuwen 		return -EINVAL;
27494eb76fafSPascal van Leeuwen 	}
27504eb76fafSPascal van Leeuwen 
27514eb76fafSPascal van Leeuwen 	return 0;
27524eb76fafSPascal van Leeuwen }
27534eb76fafSPascal van Leeuwen 
27544eb76fafSPascal van Leeuwen static int safexcel_ccm_encrypt(struct aead_request *req)
27554eb76fafSPascal van Leeuwen {
27564eb76fafSPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
27574eb76fafSPascal van Leeuwen 
27584eb76fafSPascal van Leeuwen 	if (req->iv[0] < 1 || req->iv[0] > 7)
27594eb76fafSPascal van Leeuwen 		return -EINVAL;
27604eb76fafSPascal van Leeuwen 
27614eb76fafSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
27624eb76fafSPascal van Leeuwen }
27634eb76fafSPascal van Leeuwen 
27644eb76fafSPascal van Leeuwen static int safexcel_ccm_decrypt(struct aead_request *req)
27654eb76fafSPascal van Leeuwen {
27664eb76fafSPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
27674eb76fafSPascal van Leeuwen 
27684eb76fafSPascal van Leeuwen 	if (req->iv[0] < 1 || req->iv[0] > 7)
27694eb76fafSPascal van Leeuwen 		return -EINVAL;
27704eb76fafSPascal van Leeuwen 
27714eb76fafSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
27724eb76fafSPascal van Leeuwen }
27734eb76fafSPascal van Leeuwen 
27744eb76fafSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ccm = {
27754eb76fafSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
27764eb76fafSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL,
27774eb76fafSPascal van Leeuwen 	.alg.aead = {
27784eb76fafSPascal van Leeuwen 		.setkey = safexcel_aead_ccm_setkey,
27794eb76fafSPascal van Leeuwen 		.setauthsize = safexcel_aead_ccm_setauthsize,
27804eb76fafSPascal van Leeuwen 		.encrypt = safexcel_ccm_encrypt,
27814eb76fafSPascal van Leeuwen 		.decrypt = safexcel_ccm_decrypt,
27824eb76fafSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
27834eb76fafSPascal van Leeuwen 		.maxauthsize = AES_BLOCK_SIZE,
27844eb76fafSPascal van Leeuwen 		.base = {
27854eb76fafSPascal van Leeuwen 			.cra_name = "ccm(aes)",
27864eb76fafSPascal van Leeuwen 			.cra_driver_name = "safexcel-ccm-aes",
27874eb76fafSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
27884eb76fafSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
27894eb76fafSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
27904eb76fafSPascal van Leeuwen 			.cra_blocksize = 1,
27914eb76fafSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
27924eb76fafSPascal van Leeuwen 			.cra_alignmask = 0,
27934eb76fafSPascal van Leeuwen 			.cra_init = safexcel_aead_ccm_cra_init,
27944eb76fafSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
27954eb76fafSPascal van Leeuwen 			.cra_module = THIS_MODULE,
27964eb76fafSPascal van Leeuwen 		},
27974eb76fafSPascal van Leeuwen 	},
27984eb76fafSPascal van Leeuwen };
27994a593fb3SPascal van Leeuwen 
2800a6061921SPascal van Leeuwen static void safexcel_chacha20_setkey(struct safexcel_cipher_ctx *ctx,
2801a6061921SPascal van Leeuwen 				     const u8 *key)
28024a593fb3SPascal van Leeuwen {
28034a593fb3SPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
28044a593fb3SPascal van Leeuwen 
280513a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
280613a1bb93SPascal van Leeuwen 		if (memcmp(ctx->key, key, CHACHA_KEY_SIZE))
28074a593fb3SPascal van Leeuwen 			ctx->base.needs_inv = true;
28084a593fb3SPascal van Leeuwen 
280913a1bb93SPascal van Leeuwen 	memcpy(ctx->key, key, CHACHA_KEY_SIZE);
28104a593fb3SPascal van Leeuwen 	ctx->key_len = CHACHA_KEY_SIZE;
2811a6061921SPascal van Leeuwen }
2812a6061921SPascal van Leeuwen 
2813a6061921SPascal van Leeuwen static int safexcel_skcipher_chacha20_setkey(struct crypto_skcipher *ctfm,
2814a6061921SPascal van Leeuwen 					     const u8 *key, unsigned int len)
2815a6061921SPascal van Leeuwen {
2816a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
2817a6061921SPascal van Leeuwen 
2818a6061921SPascal van Leeuwen 	if (len != CHACHA_KEY_SIZE) {
2819a6061921SPascal van Leeuwen 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2820a6061921SPascal van Leeuwen 		return -EINVAL;
2821a6061921SPascal van Leeuwen 	}
2822a6061921SPascal van Leeuwen 	safexcel_chacha20_setkey(ctx, key);
28234a593fb3SPascal van Leeuwen 
28244a593fb3SPascal van Leeuwen 	return 0;
28254a593fb3SPascal van Leeuwen }
28264a593fb3SPascal van Leeuwen 
28274a593fb3SPascal van Leeuwen static int safexcel_skcipher_chacha20_cra_init(struct crypto_tfm *tfm)
28284a593fb3SPascal van Leeuwen {
28294a593fb3SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
28304a593fb3SPascal van Leeuwen 
28314a593fb3SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
28324a593fb3SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_CHACHA20;
2833098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
28344a593fb3SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32;
28354a593fb3SPascal van Leeuwen 	return 0;
28364a593fb3SPascal van Leeuwen }
28374a593fb3SPascal van Leeuwen 
28384a593fb3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chacha20 = {
28394a593fb3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
28404a593fb3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20,
28414a593fb3SPascal van Leeuwen 	.alg.skcipher = {
28424a593fb3SPascal van Leeuwen 		.setkey = safexcel_skcipher_chacha20_setkey,
28434a593fb3SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
28444a593fb3SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
28454a593fb3SPascal van Leeuwen 		.min_keysize = CHACHA_KEY_SIZE,
28464a593fb3SPascal van Leeuwen 		.max_keysize = CHACHA_KEY_SIZE,
28474a593fb3SPascal van Leeuwen 		.ivsize = CHACHA_IV_SIZE,
28484a593fb3SPascal van Leeuwen 		.base = {
28494a593fb3SPascal van Leeuwen 			.cra_name = "chacha20",
28504a593fb3SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20",
28514a593fb3SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
28524a593fb3SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
28534a593fb3SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
28544a593fb3SPascal van Leeuwen 			.cra_blocksize = 1,
28554a593fb3SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
28564a593fb3SPascal van Leeuwen 			.cra_alignmask = 0,
28574a593fb3SPascal van Leeuwen 			.cra_init = safexcel_skcipher_chacha20_cra_init,
28584a593fb3SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
28594a593fb3SPascal van Leeuwen 			.cra_module = THIS_MODULE,
28604a593fb3SPascal van Leeuwen 		},
28614a593fb3SPascal van Leeuwen 	},
28624a593fb3SPascal van Leeuwen };
2863a6061921SPascal van Leeuwen 
2864a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_setkey(struct crypto_aead *ctfm,
2865a6061921SPascal van Leeuwen 				    const u8 *key, unsigned int len)
2866a6061921SPascal van Leeuwen {
2867a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_aead_ctx(ctfm);
2868a6061921SPascal van Leeuwen 
2869a6061921SPascal van Leeuwen 	if (ctx->aead  == EIP197_AEAD_TYPE_IPSEC_ESP &&
2870a6061921SPascal van Leeuwen 	    len > EIP197_AEAD_IPSEC_NONCE_SIZE) {
2871a6061921SPascal van Leeuwen 		/* ESP variant has nonce appended to key */
2872a6061921SPascal van Leeuwen 		len -= EIP197_AEAD_IPSEC_NONCE_SIZE;
2873a6061921SPascal van Leeuwen 		ctx->nonce = *(u32 *)(key + len);
2874a6061921SPascal van Leeuwen 	}
2875a6061921SPascal van Leeuwen 	if (len != CHACHA_KEY_SIZE) {
2876a6061921SPascal van Leeuwen 		crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2877a6061921SPascal van Leeuwen 		return -EINVAL;
2878a6061921SPascal van Leeuwen 	}
2879a6061921SPascal van Leeuwen 	safexcel_chacha20_setkey(ctx, key);
2880a6061921SPascal van Leeuwen 
2881a6061921SPascal van Leeuwen 	return 0;
2882a6061921SPascal van Leeuwen }
2883a6061921SPascal van Leeuwen 
2884a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_setauthsize(struct crypto_aead *tfm,
2885a6061921SPascal van Leeuwen 					 unsigned int authsize)
2886a6061921SPascal van Leeuwen {
2887a6061921SPascal van Leeuwen 	if (authsize != POLY1305_DIGEST_SIZE)
2888a6061921SPascal van Leeuwen 		return -EINVAL;
2889a6061921SPascal van Leeuwen 	return 0;
2890a6061921SPascal van Leeuwen }
2891a6061921SPascal van Leeuwen 
2892a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_crypt(struct aead_request *req,
2893a6061921SPascal van Leeuwen 					  enum safexcel_cipher_direction dir)
2894a6061921SPascal van Leeuwen {
2895a6061921SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
2896a6061921SPascal van Leeuwen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2897a6061921SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
2898a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2899a6061921SPascal van Leeuwen 	struct aead_request *subreq = aead_request_ctx(req);
2900a6061921SPascal van Leeuwen 	u32 key[CHACHA_KEY_SIZE / sizeof(u32) + 1];
290113a1bb93SPascal van Leeuwen 	int ret = 0;
2902a6061921SPascal van Leeuwen 
2903a6061921SPascal van Leeuwen 	/*
2904a6061921SPascal van Leeuwen 	 * Instead of wasting time detecting umpteen silly corner cases,
2905a6061921SPascal van Leeuwen 	 * just dump all "small" requests to the fallback implementation.
2906a6061921SPascal van Leeuwen 	 * HW would not be faster on such small requests anyway.
2907a6061921SPascal van Leeuwen 	 */
2908a6061921SPascal van Leeuwen 	if (likely((ctx->aead != EIP197_AEAD_TYPE_IPSEC_ESP ||
2909a6061921SPascal van Leeuwen 		    req->assoclen >= EIP197_AEAD_IPSEC_IV_SIZE) &&
2910a6061921SPascal van Leeuwen 		   req->cryptlen > POLY1305_DIGEST_SIZE)) {
2911a6061921SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, dir);
2912a6061921SPascal van Leeuwen 	}
2913a6061921SPascal van Leeuwen 
2914a6061921SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
291513a1bb93SPascal van Leeuwen 	memcpy(key, ctx->key, CHACHA_KEY_SIZE);
2916a6061921SPascal van Leeuwen 	if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
2917a6061921SPascal van Leeuwen 		/* ESP variant has nonce appended to the key */
2918a6061921SPascal van Leeuwen 		key[CHACHA_KEY_SIZE / sizeof(u32)] = ctx->nonce;
2919a6061921SPascal van Leeuwen 		ret = crypto_aead_setkey(ctx->fback, (u8 *)key,
2920a6061921SPascal van Leeuwen 					 CHACHA_KEY_SIZE +
2921a6061921SPascal van Leeuwen 					 EIP197_AEAD_IPSEC_NONCE_SIZE);
2922a6061921SPascal van Leeuwen 	} else {
2923a6061921SPascal van Leeuwen 		ret = crypto_aead_setkey(ctx->fback, (u8 *)key,
2924a6061921SPascal van Leeuwen 					 CHACHA_KEY_SIZE);
2925a6061921SPascal van Leeuwen 	}
2926a6061921SPascal van Leeuwen 	if (ret) {
2927a6061921SPascal van Leeuwen 		crypto_aead_clear_flags(aead, CRYPTO_TFM_REQ_MASK);
2928a6061921SPascal van Leeuwen 		crypto_aead_set_flags(aead, crypto_aead_get_flags(ctx->fback) &
2929a6061921SPascal van Leeuwen 					    CRYPTO_TFM_REQ_MASK);
2930a6061921SPascal van Leeuwen 		return ret;
2931a6061921SPascal van Leeuwen 	}
2932a6061921SPascal van Leeuwen 
2933a6061921SPascal van Leeuwen 	aead_request_set_tfm(subreq, ctx->fback);
2934a6061921SPascal van Leeuwen 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
2935a6061921SPascal van Leeuwen 				  req->base.data);
2936a6061921SPascal van Leeuwen 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
2937a6061921SPascal van Leeuwen 			       req->iv);
2938a6061921SPascal van Leeuwen 	aead_request_set_ad(subreq, req->assoclen);
2939a6061921SPascal van Leeuwen 
2940a6061921SPascal van Leeuwen 	return (dir ==  SAFEXCEL_ENCRYPT) ?
2941a6061921SPascal van Leeuwen 		crypto_aead_encrypt(subreq) :
2942a6061921SPascal van Leeuwen 		crypto_aead_decrypt(subreq);
2943a6061921SPascal van Leeuwen }
2944a6061921SPascal van Leeuwen 
2945a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_encrypt(struct aead_request *req)
2946a6061921SPascal van Leeuwen {
2947a6061921SPascal van Leeuwen 	return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_ENCRYPT);
2948a6061921SPascal van Leeuwen }
2949a6061921SPascal van Leeuwen 
2950a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_decrypt(struct aead_request *req)
2951a6061921SPascal van Leeuwen {
2952a6061921SPascal van Leeuwen 	return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_DECRYPT);
2953a6061921SPascal van Leeuwen }
2954a6061921SPascal van Leeuwen 
29551769f704SPascal van Leeuwen static int safexcel_aead_fallback_cra_init(struct crypto_tfm *tfm)
2956a6061921SPascal van Leeuwen {
2957a6061921SPascal van Leeuwen 	struct crypto_aead *aead = __crypto_aead_cast(tfm);
2958a6061921SPascal van Leeuwen 	struct aead_alg *alg = crypto_aead_alg(aead);
2959a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2960a6061921SPascal van Leeuwen 
2961a6061921SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
2962a6061921SPascal van Leeuwen 
2963a6061921SPascal van Leeuwen 	/* Allocate fallback implementation */
2964a6061921SPascal van Leeuwen 	ctx->fback = crypto_alloc_aead(alg->base.cra_name, 0,
2965a6061921SPascal van Leeuwen 				       CRYPTO_ALG_ASYNC |
2966a6061921SPascal van Leeuwen 				       CRYPTO_ALG_NEED_FALLBACK);
2967a6061921SPascal van Leeuwen 	if (IS_ERR(ctx->fback))
2968a6061921SPascal van Leeuwen 		return PTR_ERR(ctx->fback);
2969a6061921SPascal van Leeuwen 
2970a6061921SPascal van Leeuwen 	crypto_aead_set_reqsize(aead, max(sizeof(struct safexcel_cipher_req),
2971a6061921SPascal van Leeuwen 					  sizeof(struct aead_request) +
2972a6061921SPascal van Leeuwen 					  crypto_aead_reqsize(ctx->fback)));
2973a6061921SPascal van Leeuwen 
2974a6061921SPascal van Leeuwen 	return 0;
2975a6061921SPascal van Leeuwen }
2976a6061921SPascal van Leeuwen 
29771769f704SPascal van Leeuwen static int safexcel_aead_chachapoly_cra_init(struct crypto_tfm *tfm)
29781769f704SPascal van Leeuwen {
29791769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
29801769f704SPascal van Leeuwen 
29811769f704SPascal van Leeuwen 	safexcel_aead_fallback_cra_init(tfm);
29821769f704SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_CHACHA20;
29831769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32 |
29841769f704SPascal van Leeuwen 		    CONTEXT_CONTROL_CHACHA20_MODE_CALC_OTK;
2985098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
29861769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_POLY1305;
29871769f704SPascal van Leeuwen 	ctx->state_sz = 0; /* Precomputed by HW */
29881769f704SPascal van Leeuwen 	return 0;
29891769f704SPascal van Leeuwen }
29901769f704SPascal van Leeuwen 
29911769f704SPascal van Leeuwen static void safexcel_aead_fallback_cra_exit(struct crypto_tfm *tfm)
2992a6061921SPascal van Leeuwen {
2993a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2994a6061921SPascal van Leeuwen 
2995a6061921SPascal van Leeuwen 	crypto_free_aead(ctx->fback);
2996a6061921SPascal van Leeuwen 	safexcel_aead_cra_exit(tfm);
2997a6061921SPascal van Leeuwen }
2998a6061921SPascal van Leeuwen 
2999a6061921SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chachapoly = {
3000a6061921SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3001a6061921SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305,
3002a6061921SPascal van Leeuwen 	.alg.aead = {
3003a6061921SPascal van Leeuwen 		.setkey = safexcel_aead_chachapoly_setkey,
3004a6061921SPascal van Leeuwen 		.setauthsize = safexcel_aead_chachapoly_setauthsize,
3005a6061921SPascal van Leeuwen 		.encrypt = safexcel_aead_chachapoly_encrypt,
3006a6061921SPascal van Leeuwen 		.decrypt = safexcel_aead_chachapoly_decrypt,
3007a6061921SPascal van Leeuwen 		.ivsize = CHACHAPOLY_IV_SIZE,
3008a6061921SPascal van Leeuwen 		.maxauthsize = POLY1305_DIGEST_SIZE,
3009a6061921SPascal van Leeuwen 		.base = {
3010a6061921SPascal van Leeuwen 			.cra_name = "rfc7539(chacha20,poly1305)",
3011a6061921SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20-poly1305",
3012a6061921SPascal van Leeuwen 			/* +1 to put it above HW chacha + SW poly */
3013a6061921SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY + 1,
3014a6061921SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3015a6061921SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
3016a6061921SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
3017a6061921SPascal van Leeuwen 			.cra_blocksize = 1,
3018a6061921SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3019a6061921SPascal van Leeuwen 			.cra_alignmask = 0,
3020a6061921SPascal van Leeuwen 			.cra_init = safexcel_aead_chachapoly_cra_init,
30211769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
3022a6061921SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3023a6061921SPascal van Leeuwen 		},
3024a6061921SPascal van Leeuwen 	},
3025a6061921SPascal van Leeuwen };
3026a6061921SPascal van Leeuwen 
3027a6061921SPascal van Leeuwen static int safexcel_aead_chachapolyesp_cra_init(struct crypto_tfm *tfm)
3028a6061921SPascal van Leeuwen {
3029a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3030a6061921SPascal van Leeuwen 	int ret;
3031a6061921SPascal van Leeuwen 
3032a6061921SPascal van Leeuwen 	ret = safexcel_aead_chachapoly_cra_init(tfm);
3033a6061921SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3034098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3035a6061921SPascal van Leeuwen 	return ret;
3036a6061921SPascal van Leeuwen }
3037a6061921SPascal van Leeuwen 
3038a6061921SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chachapoly_esp = {
3039a6061921SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3040a6061921SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305,
3041a6061921SPascal van Leeuwen 	.alg.aead = {
3042a6061921SPascal van Leeuwen 		.setkey = safexcel_aead_chachapoly_setkey,
3043a6061921SPascal van Leeuwen 		.setauthsize = safexcel_aead_chachapoly_setauthsize,
3044a6061921SPascal van Leeuwen 		.encrypt = safexcel_aead_chachapoly_encrypt,
3045a6061921SPascal van Leeuwen 		.decrypt = safexcel_aead_chachapoly_decrypt,
3046a6061921SPascal van Leeuwen 		.ivsize = CHACHAPOLY_IV_SIZE - EIP197_AEAD_IPSEC_NONCE_SIZE,
3047a6061921SPascal van Leeuwen 		.maxauthsize = POLY1305_DIGEST_SIZE,
3048a6061921SPascal van Leeuwen 		.base = {
3049a6061921SPascal van Leeuwen 			.cra_name = "rfc7539esp(chacha20,poly1305)",
3050a6061921SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20-poly1305-esp",
3051a6061921SPascal van Leeuwen 			/* +1 to put it above HW chacha + SW poly */
3052a6061921SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY + 1,
3053a6061921SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3054a6061921SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
3055a6061921SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
3056a6061921SPascal van Leeuwen 			.cra_blocksize = 1,
3057a6061921SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3058a6061921SPascal van Leeuwen 			.cra_alignmask = 0,
3059a6061921SPascal van Leeuwen 			.cra_init = safexcel_aead_chachapolyesp_cra_init,
30601769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
3061a6061921SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3062a6061921SPascal van Leeuwen 		},
3063a6061921SPascal van Leeuwen 	},
3064a6061921SPascal van Leeuwen };
3065fcca797dSPascal van Leeuwen 
3066fcca797dSPascal van Leeuwen static int safexcel_skcipher_sm4_setkey(struct crypto_skcipher *ctfm,
3067fcca797dSPascal van Leeuwen 					const u8 *key, unsigned int len)
3068fcca797dSPascal van Leeuwen {
3069fcca797dSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3070fcca797dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3071fcca797dSPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
3072fcca797dSPascal van Leeuwen 
3073fcca797dSPascal van Leeuwen 	if (len != SM4_KEY_SIZE) {
3074fcca797dSPascal van Leeuwen 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
3075fcca797dSPascal van Leeuwen 		return -EINVAL;
3076fcca797dSPascal van Leeuwen 	}
3077fcca797dSPascal van Leeuwen 
307813a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
307913a1bb93SPascal van Leeuwen 		if (memcmp(ctx->key, key, SM4_KEY_SIZE))
3080fcca797dSPascal van Leeuwen 			ctx->base.needs_inv = true;
3081fcca797dSPascal van Leeuwen 
308213a1bb93SPascal van Leeuwen 	memcpy(ctx->key, key, SM4_KEY_SIZE);
3083fcca797dSPascal van Leeuwen 	ctx->key_len = SM4_KEY_SIZE;
3084fcca797dSPascal van Leeuwen 
3085fcca797dSPascal van Leeuwen 	return 0;
3086fcca797dSPascal van Leeuwen }
3087fcca797dSPascal van Leeuwen 
3088fcca797dSPascal van Leeuwen static int safexcel_sm4_blk_encrypt(struct skcipher_request *req)
3089fcca797dSPascal van Leeuwen {
3090fcca797dSPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
3091fcca797dSPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
3092fcca797dSPascal van Leeuwen 		return -EINVAL;
3093fcca797dSPascal van Leeuwen 	else
3094fcca797dSPascal van Leeuwen 		return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
3095fcca797dSPascal van Leeuwen 					  SAFEXCEL_ENCRYPT);
3096fcca797dSPascal van Leeuwen }
3097fcca797dSPascal van Leeuwen 
3098fcca797dSPascal van Leeuwen static int safexcel_sm4_blk_decrypt(struct skcipher_request *req)
3099fcca797dSPascal van Leeuwen {
3100fcca797dSPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
3101fcca797dSPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
3102fcca797dSPascal van Leeuwen 		return -EINVAL;
3103fcca797dSPascal van Leeuwen 	else
3104fcca797dSPascal van Leeuwen 		return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
3105fcca797dSPascal van Leeuwen 					  SAFEXCEL_DECRYPT);
3106fcca797dSPascal van Leeuwen }
3107fcca797dSPascal van Leeuwen 
3108fcca797dSPascal van Leeuwen static int safexcel_skcipher_sm4_ecb_cra_init(struct crypto_tfm *tfm)
3109fcca797dSPascal van Leeuwen {
3110fcca797dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3111fcca797dSPascal van Leeuwen 
3112fcca797dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
3113fcca797dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3114fcca797dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
3115098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
3116098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
3117fcca797dSPascal van Leeuwen 	return 0;
3118fcca797dSPascal van Leeuwen }
3119fcca797dSPascal van Leeuwen 
3120fcca797dSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ecb_sm4 = {
3121fcca797dSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
3122fcca797dSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
3123fcca797dSPascal van Leeuwen 	.alg.skcipher = {
3124fcca797dSPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
3125fcca797dSPascal van Leeuwen 		.encrypt = safexcel_sm4_blk_encrypt,
3126fcca797dSPascal van Leeuwen 		.decrypt = safexcel_sm4_blk_decrypt,
3127fcca797dSPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
3128fcca797dSPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
3129fcca797dSPascal van Leeuwen 		.base = {
3130fcca797dSPascal van Leeuwen 			.cra_name = "ecb(sm4)",
3131fcca797dSPascal van Leeuwen 			.cra_driver_name = "safexcel-ecb-sm4",
3132fcca797dSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3133fcca797dSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3134fcca797dSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3135fcca797dSPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
3136fcca797dSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3137fcca797dSPascal van Leeuwen 			.cra_alignmask = 0,
3138fcca797dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ecb_cra_init,
3139fcca797dSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
3140fcca797dSPascal van Leeuwen 			.cra_module = THIS_MODULE,
3141fcca797dSPascal van Leeuwen 		},
3142fcca797dSPascal van Leeuwen 	},
3143fcca797dSPascal van Leeuwen };
31446f2d1428SPascal van Leeuwen 
31456f2d1428SPascal van Leeuwen static int safexcel_skcipher_sm4_cbc_cra_init(struct crypto_tfm *tfm)
31466f2d1428SPascal van Leeuwen {
31476f2d1428SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
31486f2d1428SPascal van Leeuwen 
31496f2d1428SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
31506f2d1428SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3151098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
31526f2d1428SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
31536f2d1428SPascal van Leeuwen 	return 0;
31546f2d1428SPascal van Leeuwen }
31556f2d1428SPascal van Leeuwen 
31566f2d1428SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbc_sm4 = {
31576f2d1428SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
31586f2d1428SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
31596f2d1428SPascal van Leeuwen 	.alg.skcipher = {
31606f2d1428SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
31616f2d1428SPascal van Leeuwen 		.encrypt = safexcel_sm4_blk_encrypt,
31626f2d1428SPascal van Leeuwen 		.decrypt = safexcel_sm4_blk_decrypt,
31636f2d1428SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
31646f2d1428SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
31656f2d1428SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
31666f2d1428SPascal van Leeuwen 		.base = {
31676f2d1428SPascal van Leeuwen 			.cra_name = "cbc(sm4)",
31686f2d1428SPascal van Leeuwen 			.cra_driver_name = "safexcel-cbc-sm4",
31696f2d1428SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
31706f2d1428SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
31716f2d1428SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
31726f2d1428SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
31736f2d1428SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
31746f2d1428SPascal van Leeuwen 			.cra_alignmask = 0,
31756f2d1428SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_cbc_cra_init,
31766f2d1428SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
31776f2d1428SPascal van Leeuwen 			.cra_module = THIS_MODULE,
31786f2d1428SPascal van Leeuwen 		},
31796f2d1428SPascal van Leeuwen 	},
31806f2d1428SPascal van Leeuwen };
318103a6cfb9SPascal van Leeuwen 
318203a6cfb9SPascal van Leeuwen static int safexcel_skcipher_sm4_ofb_cra_init(struct crypto_tfm *tfm)
318303a6cfb9SPascal van Leeuwen {
318403a6cfb9SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
318503a6cfb9SPascal van Leeuwen 
318603a6cfb9SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
318703a6cfb9SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3188098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
318903a6cfb9SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB;
319003a6cfb9SPascal van Leeuwen 	return 0;
319103a6cfb9SPascal van Leeuwen }
319203a6cfb9SPascal van Leeuwen 
319303a6cfb9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ofb_sm4 = {
319403a6cfb9SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
319503a6cfb9SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB,
319603a6cfb9SPascal van Leeuwen 	.alg.skcipher = {
319703a6cfb9SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
319803a6cfb9SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
319903a6cfb9SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
320003a6cfb9SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
320103a6cfb9SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
320203a6cfb9SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
320303a6cfb9SPascal van Leeuwen 		.base = {
320403a6cfb9SPascal van Leeuwen 			.cra_name = "ofb(sm4)",
320503a6cfb9SPascal van Leeuwen 			.cra_driver_name = "safexcel-ofb-sm4",
320603a6cfb9SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
320703a6cfb9SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
320803a6cfb9SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
320903a6cfb9SPascal van Leeuwen 			.cra_blocksize = 1,
321003a6cfb9SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
321103a6cfb9SPascal van Leeuwen 			.cra_alignmask = 0,
321203a6cfb9SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ofb_cra_init,
321303a6cfb9SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
321403a6cfb9SPascal van Leeuwen 			.cra_module = THIS_MODULE,
321503a6cfb9SPascal van Leeuwen 		},
321603a6cfb9SPascal van Leeuwen 	},
321703a6cfb9SPascal van Leeuwen };
32187468ab22SPascal van Leeuwen 
32197468ab22SPascal van Leeuwen static int safexcel_skcipher_sm4_cfb_cra_init(struct crypto_tfm *tfm)
32207468ab22SPascal van Leeuwen {
32217468ab22SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
32227468ab22SPascal van Leeuwen 
32237468ab22SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
32247468ab22SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3225098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
32267468ab22SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB;
32277468ab22SPascal van Leeuwen 	return 0;
32287468ab22SPascal van Leeuwen }
32297468ab22SPascal van Leeuwen 
32307468ab22SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cfb_sm4 = {
32317468ab22SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
32327468ab22SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB,
32337468ab22SPascal van Leeuwen 	.alg.skcipher = {
32347468ab22SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
32357468ab22SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
32367468ab22SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
32377468ab22SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
32387468ab22SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
32397468ab22SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
32407468ab22SPascal van Leeuwen 		.base = {
32417468ab22SPascal van Leeuwen 			.cra_name = "cfb(sm4)",
32427468ab22SPascal van Leeuwen 			.cra_driver_name = "safexcel-cfb-sm4",
32437468ab22SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
32447468ab22SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
32457468ab22SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
32467468ab22SPascal van Leeuwen 			.cra_blocksize = 1,
32477468ab22SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
32487468ab22SPascal van Leeuwen 			.cra_alignmask = 0,
32497468ab22SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_cfb_cra_init,
32507468ab22SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
32517468ab22SPascal van Leeuwen 			.cra_module = THIS_MODULE,
32527468ab22SPascal van Leeuwen 		},
32537468ab22SPascal van Leeuwen 	},
32547468ab22SPascal van Leeuwen };
3255f77e5dc0SPascal van Leeuwen 
3256f77e5dc0SPascal van Leeuwen static int safexcel_skcipher_sm4ctr_setkey(struct crypto_skcipher *ctfm,
3257f77e5dc0SPascal van Leeuwen 					   const u8 *key, unsigned int len)
3258f77e5dc0SPascal van Leeuwen {
3259f77e5dc0SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3260f77e5dc0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3261f77e5dc0SPascal van Leeuwen 
3262f77e5dc0SPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
3263f77e5dc0SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
3264f77e5dc0SPascal van Leeuwen 	/* exclude the nonce here */
3265f77e5dc0SPascal van Leeuwen 	len -= CTR_RFC3686_NONCE_SIZE;
3266f77e5dc0SPascal van Leeuwen 
3267f77e5dc0SPascal van Leeuwen 	return safexcel_skcipher_sm4_setkey(ctfm, key, len);
3268f77e5dc0SPascal van Leeuwen }
3269f77e5dc0SPascal van Leeuwen 
3270f77e5dc0SPascal van Leeuwen static int safexcel_skcipher_sm4_ctr_cra_init(struct crypto_tfm *tfm)
3271f77e5dc0SPascal van Leeuwen {
3272f77e5dc0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3273f77e5dc0SPascal van Leeuwen 
3274f77e5dc0SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
3275f77e5dc0SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3276098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
3277f77e5dc0SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
3278f77e5dc0SPascal van Leeuwen 	return 0;
3279f77e5dc0SPascal van Leeuwen }
3280f77e5dc0SPascal van Leeuwen 
3281f77e5dc0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ctr_sm4 = {
3282f77e5dc0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
3283f77e5dc0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
3284f77e5dc0SPascal van Leeuwen 	.alg.skcipher = {
3285f77e5dc0SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4ctr_setkey,
3286f77e5dc0SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
3287f77e5dc0SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
3288f77e5dc0SPascal van Leeuwen 		/* Add nonce size */
3289f77e5dc0SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
3290f77e5dc0SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
3291f77e5dc0SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
3292f77e5dc0SPascal van Leeuwen 		.base = {
3293f77e5dc0SPascal van Leeuwen 			.cra_name = "rfc3686(ctr(sm4))",
3294f77e5dc0SPascal van Leeuwen 			.cra_driver_name = "safexcel-ctr-sm4",
3295f77e5dc0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3296f77e5dc0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3297f77e5dc0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3298f77e5dc0SPascal van Leeuwen 			.cra_blocksize = 1,
3299f77e5dc0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3300f77e5dc0SPascal van Leeuwen 			.cra_alignmask = 0,
3301f77e5dc0SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ctr_cra_init,
3302f77e5dc0SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
3303f77e5dc0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3304f77e5dc0SPascal van Leeuwen 		},
3305f77e5dc0SPascal van Leeuwen 	},
3306f77e5dc0SPascal van Leeuwen };
33071769f704SPascal van Leeuwen 
33081769f704SPascal van Leeuwen static int safexcel_aead_sm4_blk_encrypt(struct aead_request *req)
33091769f704SPascal van Leeuwen {
33101769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
33111769f704SPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
33121769f704SPascal van Leeuwen 		return -EINVAL;
33131769f704SPascal van Leeuwen 
33141769f704SPascal van Leeuwen 	return safexcel_queue_req(&req->base, aead_request_ctx(req),
33151769f704SPascal van Leeuwen 				  SAFEXCEL_ENCRYPT);
33161769f704SPascal van Leeuwen }
33171769f704SPascal van Leeuwen 
33181769f704SPascal van Leeuwen static int safexcel_aead_sm4_blk_decrypt(struct aead_request *req)
33191769f704SPascal van Leeuwen {
33201769f704SPascal van Leeuwen 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
33211769f704SPascal van Leeuwen 
33221769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
33231769f704SPascal van Leeuwen 	if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1))
33241769f704SPascal van Leeuwen 		return -EINVAL;
33251769f704SPascal van Leeuwen 
33261769f704SPascal van Leeuwen 	return safexcel_queue_req(&req->base, aead_request_ctx(req),
33271769f704SPascal van Leeuwen 				  SAFEXCEL_DECRYPT);
33281769f704SPascal van Leeuwen }
33291769f704SPascal van Leeuwen 
33301769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sha1_cra_init(struct crypto_tfm *tfm)
33311769f704SPascal van Leeuwen {
33321769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33331769f704SPascal van Leeuwen 
33341769f704SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
33351769f704SPascal van Leeuwen 	ctx->alg = SAFEXCEL_SM4;
3336098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
33371769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
33381769f704SPascal van Leeuwen 	ctx->state_sz = SHA1_DIGEST_SIZE;
33391769f704SPascal van Leeuwen 	return 0;
33401769f704SPascal van Leeuwen }
33411769f704SPascal van Leeuwen 
33421769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_sm4 = {
33431769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
33441769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1,
33451769f704SPascal van Leeuwen 	.alg.aead = {
33461769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
33471769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_sm4_blk_encrypt,
33481769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_sm4_blk_decrypt,
33491769f704SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
33501769f704SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
33511769f704SPascal van Leeuwen 		.base = {
33521769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(sm4))",
33531769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-sm4",
33541769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
33551769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
33561769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
33571769f704SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
33581769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
33591769f704SPascal van Leeuwen 			.cra_alignmask = 0,
33601769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4cbc_sha1_cra_init,
33611769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
33621769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
33631769f704SPascal van Leeuwen 		},
33641769f704SPascal van Leeuwen 	},
33651769f704SPascal van Leeuwen };
33661769f704SPascal van Leeuwen 
33671769f704SPascal van Leeuwen static int safexcel_aead_fallback_setkey(struct crypto_aead *ctfm,
33681769f704SPascal van Leeuwen 					 const u8 *key, unsigned int len)
33691769f704SPascal van Leeuwen {
33701769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
33711769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33721769f704SPascal van Leeuwen 
33731769f704SPascal van Leeuwen 	/* Keep fallback cipher synchronized */
33741769f704SPascal van Leeuwen 	return crypto_aead_setkey(ctx->fback, (u8 *)key, len) ?:
33751769f704SPascal van Leeuwen 	       safexcel_aead_setkey(ctfm, key, len);
33761769f704SPascal van Leeuwen }
33771769f704SPascal van Leeuwen 
33781769f704SPascal van Leeuwen static int safexcel_aead_fallback_setauthsize(struct crypto_aead *ctfm,
33791769f704SPascal van Leeuwen 					      unsigned int authsize)
33801769f704SPascal van Leeuwen {
33811769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
33821769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33831769f704SPascal van Leeuwen 
33841769f704SPascal van Leeuwen 	/* Keep fallback cipher synchronized */
33851769f704SPascal van Leeuwen 	return crypto_aead_setauthsize(ctx->fback, authsize);
33861769f704SPascal van Leeuwen }
33871769f704SPascal van Leeuwen 
33881769f704SPascal van Leeuwen static int safexcel_aead_fallback_crypt(struct aead_request *req,
33891769f704SPascal van Leeuwen 					enum safexcel_cipher_direction dir)
33901769f704SPascal van Leeuwen {
33911769f704SPascal van Leeuwen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
33921769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
33931769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33941769f704SPascal van Leeuwen 	struct aead_request *subreq = aead_request_ctx(req);
33951769f704SPascal van Leeuwen 
33961769f704SPascal van Leeuwen 	aead_request_set_tfm(subreq, ctx->fback);
33971769f704SPascal van Leeuwen 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
33981769f704SPascal van Leeuwen 				  req->base.data);
33991769f704SPascal van Leeuwen 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
34001769f704SPascal van Leeuwen 			       req->iv);
34011769f704SPascal van Leeuwen 	aead_request_set_ad(subreq, req->assoclen);
34021769f704SPascal van Leeuwen 
34031769f704SPascal van Leeuwen 	return (dir ==  SAFEXCEL_ENCRYPT) ?
34041769f704SPascal van Leeuwen 		crypto_aead_encrypt(subreq) :
34051769f704SPascal van Leeuwen 		crypto_aead_decrypt(subreq);
34061769f704SPascal van Leeuwen }
34071769f704SPascal van Leeuwen 
34081769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_encrypt(struct aead_request *req)
34091769f704SPascal van Leeuwen {
34101769f704SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
34111769f704SPascal van Leeuwen 
34121769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
34131769f704SPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
34141769f704SPascal van Leeuwen 		return -EINVAL;
34151769f704SPascal van Leeuwen 	else if (req->cryptlen || req->assoclen) /* If input length > 0 only */
34161769f704SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
34171769f704SPascal van Leeuwen 
34181769f704SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
34191769f704SPascal van Leeuwen 	return safexcel_aead_fallback_crypt(req, SAFEXCEL_ENCRYPT);
34201769f704SPascal van Leeuwen }
34211769f704SPascal van Leeuwen 
34221769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_decrypt(struct aead_request *req)
34231769f704SPascal van Leeuwen {
34241769f704SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
34251769f704SPascal van Leeuwen 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
34261769f704SPascal van Leeuwen 
34271769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
34281769f704SPascal van Leeuwen 	if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1))
34291769f704SPascal van Leeuwen 		return -EINVAL;
34301769f704SPascal van Leeuwen 	else if (req->cryptlen > crypto_aead_authsize(tfm) || req->assoclen)
34311769f704SPascal van Leeuwen 		/* If input length > 0 only */
34321769f704SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
34331769f704SPascal van Leeuwen 
34341769f704SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
34351769f704SPascal van Leeuwen 	return safexcel_aead_fallback_crypt(req, SAFEXCEL_DECRYPT);
34361769f704SPascal van Leeuwen }
34371769f704SPascal van Leeuwen 
34381769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_cra_init(struct crypto_tfm *tfm)
34391769f704SPascal van Leeuwen {
34401769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34411769f704SPascal van Leeuwen 
34421769f704SPascal van Leeuwen 	safexcel_aead_fallback_cra_init(tfm);
34431769f704SPascal van Leeuwen 	ctx->alg = SAFEXCEL_SM4;
3444098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
34451769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
34461769f704SPascal van Leeuwen 	ctx->state_sz = SM3_DIGEST_SIZE;
34471769f704SPascal van Leeuwen 	return 0;
34481769f704SPascal van Leeuwen }
34491769f704SPascal van Leeuwen 
34501769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_cbc_sm4 = {
34511769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
34521769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3,
34531769f704SPascal van Leeuwen 	.alg.aead = {
34541769f704SPascal van Leeuwen 		.setkey = safexcel_aead_fallback_setkey,
34551769f704SPascal van Leeuwen 		.setauthsize = safexcel_aead_fallback_setauthsize,
34561769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_sm4cbc_sm3_encrypt,
34571769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_sm4cbc_sm3_decrypt,
34581769f704SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
34591769f704SPascal van Leeuwen 		.maxauthsize = SM3_DIGEST_SIZE,
34601769f704SPascal van Leeuwen 		.base = {
34611769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sm3),cbc(sm4))",
34621769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sm3-cbc-sm4",
34631769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
34641769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
34651769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
34661769f704SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
34671769f704SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
34681769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
34691769f704SPascal van Leeuwen 			.cra_alignmask = 0,
34701769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4cbc_sm3_cra_init,
34711769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
34721769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
34731769f704SPascal van Leeuwen 		},
34741769f704SPascal van Leeuwen 	},
34751769f704SPascal van Leeuwen };
34761769f704SPascal van Leeuwen 
34771769f704SPascal van Leeuwen static int safexcel_aead_sm4ctr_sha1_cra_init(struct crypto_tfm *tfm)
34781769f704SPascal van Leeuwen {
34791769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34801769f704SPascal van Leeuwen 
34811769f704SPascal van Leeuwen 	safexcel_aead_sm4cbc_sha1_cra_init(tfm);
34821769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
34831769f704SPascal van Leeuwen 	return 0;
34841769f704SPascal van Leeuwen }
34851769f704SPascal van Leeuwen 
34861769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_sm4 = {
34871769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
34881769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1,
34891769f704SPascal van Leeuwen 	.alg.aead = {
34901769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
34911769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
34921769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
34931769f704SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
34941769f704SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
34951769f704SPascal van Leeuwen 		.base = {
34961769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),rfc3686(ctr(sm4)))",
34971769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-sm4",
34981769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
34991769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
35001769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
35011769f704SPascal van Leeuwen 			.cra_blocksize = 1,
35021769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
35031769f704SPascal van Leeuwen 			.cra_alignmask = 0,
35041769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4ctr_sha1_cra_init,
35051769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
35061769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
35071769f704SPascal van Leeuwen 		},
35081769f704SPascal van Leeuwen 	},
35091769f704SPascal van Leeuwen };
35101769f704SPascal van Leeuwen 
35111769f704SPascal van Leeuwen static int safexcel_aead_sm4ctr_sm3_cra_init(struct crypto_tfm *tfm)
35121769f704SPascal van Leeuwen {
35131769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
35141769f704SPascal van Leeuwen 
35151769f704SPascal van Leeuwen 	safexcel_aead_sm4cbc_sm3_cra_init(tfm);
35161769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
35171769f704SPascal van Leeuwen 	return 0;
35181769f704SPascal van Leeuwen }
35191769f704SPascal van Leeuwen 
35201769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_ctr_sm4 = {
35211769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
35221769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3,
35231769f704SPascal van Leeuwen 	.alg.aead = {
35241769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
35251769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
35261769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
35271769f704SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
35281769f704SPascal van Leeuwen 		.maxauthsize = SM3_DIGEST_SIZE,
35291769f704SPascal van Leeuwen 		.base = {
35301769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sm3),rfc3686(ctr(sm4)))",
35311769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sm3-ctr-sm4",
35321769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
35331769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
35341769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
35351769f704SPascal van Leeuwen 			.cra_blocksize = 1,
35361769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
35371769f704SPascal van Leeuwen 			.cra_alignmask = 0,
35381769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4ctr_sm3_cra_init,
35391769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
35401769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
35411769f704SPascal van Leeuwen 		},
35421769f704SPascal van Leeuwen 	},
35431769f704SPascal van Leeuwen };
3544a19052d4SPascal van Leeuwen 
3545a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_setkey(struct crypto_aead *ctfm, const u8 *key,
3546a19052d4SPascal van Leeuwen 				       unsigned int len)
3547a19052d4SPascal van Leeuwen {
3548a19052d4SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
3549a19052d4SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3550a19052d4SPascal van Leeuwen 
3551a19052d4SPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
3552a19052d4SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
3553a19052d4SPascal van Leeuwen 
3554a19052d4SPascal van Leeuwen 	len -= CTR_RFC3686_NONCE_SIZE;
3555a19052d4SPascal van Leeuwen 	return safexcel_aead_gcm_setkey(ctfm, key, len);
3556a19052d4SPascal van Leeuwen }
3557a19052d4SPascal van Leeuwen 
3558a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_setauthsize(struct crypto_aead *tfm,
3559a19052d4SPascal van Leeuwen 					    unsigned int authsize)
3560a19052d4SPascal van Leeuwen {
3561a19052d4SPascal van Leeuwen 	return crypto_rfc4106_check_authsize(authsize);
3562a19052d4SPascal van Leeuwen }
3563a19052d4SPascal van Leeuwen 
3564a19052d4SPascal van Leeuwen static int safexcel_rfc4106_encrypt(struct aead_request *req)
3565a19052d4SPascal van Leeuwen {
3566a19052d4SPascal van Leeuwen 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
3567a19052d4SPascal van Leeuwen 	       safexcel_aead_encrypt(req);
3568a19052d4SPascal van Leeuwen }
3569a19052d4SPascal van Leeuwen 
3570a19052d4SPascal van Leeuwen static int safexcel_rfc4106_decrypt(struct aead_request *req)
3571a19052d4SPascal van Leeuwen {
3572a19052d4SPascal van Leeuwen 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
3573a19052d4SPascal van Leeuwen 	       safexcel_aead_decrypt(req);
3574a19052d4SPascal van Leeuwen }
3575a19052d4SPascal van Leeuwen 
3576a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_cra_init(struct crypto_tfm *tfm)
3577a19052d4SPascal van Leeuwen {
3578a19052d4SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3579a19052d4SPascal van Leeuwen 	int ret;
3580a19052d4SPascal van Leeuwen 
3581a19052d4SPascal van Leeuwen 	ret = safexcel_aead_gcm_cra_init(tfm);
3582a19052d4SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3583098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3584a19052d4SPascal van Leeuwen 	return ret;
3585a19052d4SPascal van Leeuwen }
3586a19052d4SPascal van Leeuwen 
3587a19052d4SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4106_gcm = {
3588a19052d4SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3589a19052d4SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
3590a19052d4SPascal van Leeuwen 	.alg.aead = {
3591a19052d4SPascal van Leeuwen 		.setkey = safexcel_rfc4106_gcm_setkey,
3592a19052d4SPascal van Leeuwen 		.setauthsize = safexcel_rfc4106_gcm_setauthsize,
3593a19052d4SPascal van Leeuwen 		.encrypt = safexcel_rfc4106_encrypt,
3594a19052d4SPascal van Leeuwen 		.decrypt = safexcel_rfc4106_decrypt,
3595a19052d4SPascal van Leeuwen 		.ivsize = GCM_RFC4106_IV_SIZE,
3596a19052d4SPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
3597a19052d4SPascal van Leeuwen 		.base = {
3598a19052d4SPascal van Leeuwen 			.cra_name = "rfc4106(gcm(aes))",
3599a19052d4SPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4106-gcm-aes",
3600a19052d4SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3601a19052d4SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3602a19052d4SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3603a19052d4SPascal van Leeuwen 			.cra_blocksize = 1,
3604a19052d4SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3605a19052d4SPascal van Leeuwen 			.cra_alignmask = 0,
3606a19052d4SPascal van Leeuwen 			.cra_init = safexcel_rfc4106_gcm_cra_init,
3607a19052d4SPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
3608a19052d4SPascal van Leeuwen 		},
3609a19052d4SPascal van Leeuwen 	},
3610a19052d4SPascal van Leeuwen };
361192c60cefSPascal van Leeuwen 
361292c60cefSPascal van Leeuwen static int safexcel_rfc4543_gcm_setauthsize(struct crypto_aead *tfm,
361392c60cefSPascal van Leeuwen 					    unsigned int authsize)
361492c60cefSPascal van Leeuwen {
361592c60cefSPascal van Leeuwen 	if (authsize != GHASH_DIGEST_SIZE)
361692c60cefSPascal van Leeuwen 		return -EINVAL;
361792c60cefSPascal van Leeuwen 
361892c60cefSPascal van Leeuwen 	return 0;
361992c60cefSPascal van Leeuwen }
362092c60cefSPascal van Leeuwen 
362192c60cefSPascal van Leeuwen static int safexcel_rfc4543_gcm_cra_init(struct crypto_tfm *tfm)
362292c60cefSPascal van Leeuwen {
362392c60cefSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
362492c60cefSPascal van Leeuwen 	int ret;
362592c60cefSPascal van Leeuwen 
362692c60cefSPascal van Leeuwen 	ret = safexcel_aead_gcm_cra_init(tfm);
362792c60cefSPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP_GMAC;
362892c60cefSPascal van Leeuwen 	return ret;
362992c60cefSPascal van Leeuwen }
363092c60cefSPascal van Leeuwen 
363192c60cefSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4543_gcm = {
363292c60cefSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
363392c60cefSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
363492c60cefSPascal van Leeuwen 	.alg.aead = {
363592c60cefSPascal van Leeuwen 		.setkey = safexcel_rfc4106_gcm_setkey,
363692c60cefSPascal van Leeuwen 		.setauthsize = safexcel_rfc4543_gcm_setauthsize,
363792c60cefSPascal van Leeuwen 		.encrypt = safexcel_rfc4106_encrypt,
363892c60cefSPascal van Leeuwen 		.decrypt = safexcel_rfc4106_decrypt,
363992c60cefSPascal van Leeuwen 		.ivsize = GCM_RFC4543_IV_SIZE,
364092c60cefSPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
364192c60cefSPascal van Leeuwen 		.base = {
364292c60cefSPascal van Leeuwen 			.cra_name = "rfc4543(gcm(aes))",
364392c60cefSPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4543-gcm-aes",
364492c60cefSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
364592c60cefSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
364692c60cefSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
364792c60cefSPascal van Leeuwen 			.cra_blocksize = 1,
364892c60cefSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
364992c60cefSPascal van Leeuwen 			.cra_alignmask = 0,
365092c60cefSPascal van Leeuwen 			.cra_init = safexcel_rfc4543_gcm_cra_init,
365192c60cefSPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
365292c60cefSPascal van Leeuwen 		},
365392c60cefSPascal van Leeuwen 	},
365492c60cefSPascal van Leeuwen };
3655a9a89624SPascal van Leeuwen 
3656a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_setkey(struct crypto_aead *ctfm, const u8 *key,
3657a9a89624SPascal van Leeuwen 				       unsigned int len)
3658a9a89624SPascal van Leeuwen {
3659a9a89624SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
3660a9a89624SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3661a9a89624SPascal van Leeuwen 
3662a9a89624SPascal van Leeuwen 	/* First byte of the nonce = L = always 3 for RFC4309 (4 byte ctr) */
3663a9a89624SPascal van Leeuwen 	*(u8 *)&ctx->nonce = EIP197_AEAD_IPSEC_COUNTER_SIZE - 1;
3664a9a89624SPascal van Leeuwen 	/* last 3 bytes of key are the nonce! */
3665a9a89624SPascal van Leeuwen 	memcpy((u8 *)&ctx->nonce + 1, key + len -
3666a9a89624SPascal van Leeuwen 	       EIP197_AEAD_IPSEC_CCM_NONCE_SIZE,
3667a9a89624SPascal van Leeuwen 	       EIP197_AEAD_IPSEC_CCM_NONCE_SIZE);
3668a9a89624SPascal van Leeuwen 
3669a9a89624SPascal van Leeuwen 	len -= EIP197_AEAD_IPSEC_CCM_NONCE_SIZE;
3670a9a89624SPascal van Leeuwen 	return safexcel_aead_ccm_setkey(ctfm, key, len);
3671a9a89624SPascal van Leeuwen }
3672a9a89624SPascal van Leeuwen 
3673a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_setauthsize(struct crypto_aead *tfm,
3674a9a89624SPascal van Leeuwen 					    unsigned int authsize)
3675a9a89624SPascal van Leeuwen {
3676a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3677a9a89624SPascal van Leeuwen 	switch (authsize) {
3678a9a89624SPascal van Leeuwen 	case 8:
3679a9a89624SPascal van Leeuwen 	case 12:
3680a9a89624SPascal van Leeuwen 	case 16:
3681a9a89624SPascal van Leeuwen 		break;
3682a9a89624SPascal van Leeuwen 	default:
3683a9a89624SPascal van Leeuwen 		return -EINVAL;
3684a9a89624SPascal van Leeuwen 	}
3685a9a89624SPascal van Leeuwen 
3686a9a89624SPascal van Leeuwen 	return 0;
3687a9a89624SPascal van Leeuwen }
3688a9a89624SPascal van Leeuwen 
3689a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_encrypt(struct aead_request *req)
3690a9a89624SPascal van Leeuwen {
3691a9a89624SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
3692a9a89624SPascal van Leeuwen 
3693a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3694a9a89624SPascal van Leeuwen 	if (req->assoclen != 16 && req->assoclen != 20)
3695a9a89624SPascal van Leeuwen 		return -EINVAL;
3696a9a89624SPascal van Leeuwen 
3697a9a89624SPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
3698a9a89624SPascal van Leeuwen }
3699a9a89624SPascal van Leeuwen 
3700a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_decrypt(struct aead_request *req)
3701a9a89624SPascal van Leeuwen {
3702a9a89624SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
3703a9a89624SPascal van Leeuwen 
3704a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3705a9a89624SPascal van Leeuwen 	if (req->assoclen != 16 && req->assoclen != 20)
3706a9a89624SPascal van Leeuwen 		return -EINVAL;
3707a9a89624SPascal van Leeuwen 
3708a9a89624SPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
3709a9a89624SPascal van Leeuwen }
3710a9a89624SPascal van Leeuwen 
3711a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_cra_init(struct crypto_tfm *tfm)
3712a9a89624SPascal van Leeuwen {
3713a9a89624SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3714a9a89624SPascal van Leeuwen 	int ret;
3715a9a89624SPascal van Leeuwen 
3716a9a89624SPascal van Leeuwen 	ret = safexcel_aead_ccm_cra_init(tfm);
3717a9a89624SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3718098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3719a9a89624SPascal van Leeuwen 	return ret;
3720a9a89624SPascal van Leeuwen }
3721a9a89624SPascal van Leeuwen 
3722a9a89624SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4309_ccm = {
3723a9a89624SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3724a9a89624SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL,
3725a9a89624SPascal van Leeuwen 	.alg.aead = {
3726a9a89624SPascal van Leeuwen 		.setkey = safexcel_rfc4309_ccm_setkey,
3727a9a89624SPascal van Leeuwen 		.setauthsize = safexcel_rfc4309_ccm_setauthsize,
3728a9a89624SPascal van Leeuwen 		.encrypt = safexcel_rfc4309_ccm_encrypt,
3729a9a89624SPascal van Leeuwen 		.decrypt = safexcel_rfc4309_ccm_decrypt,
3730a9a89624SPascal van Leeuwen 		.ivsize = EIP197_AEAD_IPSEC_IV_SIZE,
3731a9a89624SPascal van Leeuwen 		.maxauthsize = AES_BLOCK_SIZE,
3732a9a89624SPascal van Leeuwen 		.base = {
3733a9a89624SPascal van Leeuwen 			.cra_name = "rfc4309(ccm(aes))",
3734a9a89624SPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4309-ccm-aes",
3735a9a89624SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3736a9a89624SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3737a9a89624SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3738a9a89624SPascal van Leeuwen 			.cra_blocksize = 1,
3739a9a89624SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3740a9a89624SPascal van Leeuwen 			.cra_alignmask = 0,
3741a9a89624SPascal van Leeuwen 			.cra_init = safexcel_rfc4309_ccm_cra_init,
3742a9a89624SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
3743a9a89624SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3744a9a89624SPascal van Leeuwen 		},
3745a9a89624SPascal van Leeuwen 	},
3746a9a89624SPascal van Leeuwen };
3747