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>
21a24d22b2SEric Biggers #include <crypto/sha1.h>
22a24d22b2SEric Biggers #include <crypto/sha2.h>
231769f704SPascal van Leeuwen #include <crypto/sm3.h>
24fcca797dSPascal van Leeuwen #include <crypto/sm4.h>
25c7da38a7SPascal van Leeuwen #include <crypto/xts.h>
261b44c5a6SAntoine Ténart #include <crypto/skcipher.h>
27f6beaea3SAntoine Tenart #include <crypto/internal/aead.h>
281eb7b403SOfer Heifetz #include <crypto/internal/skcipher.h>
291b44c5a6SAntoine Ténart 
301b44c5a6SAntoine Ténart #include "safexcel.h"
311b44c5a6SAntoine Ténart 
321b44c5a6SAntoine Ténart enum safexcel_cipher_direction {
331b44c5a6SAntoine Ténart 	SAFEXCEL_ENCRYPT,
341b44c5a6SAntoine Ténart 	SAFEXCEL_DECRYPT,
351b44c5a6SAntoine Ténart };
361b44c5a6SAntoine Ténart 
37a7dea8c0SOfer Heifetz enum safexcel_cipher_alg {
38a7dea8c0SOfer Heifetz 	SAFEXCEL_DES,
3962469879SOfer Heifetz 	SAFEXCEL_3DES,
40a7dea8c0SOfer Heifetz 	SAFEXCEL_AES,
414a593fb3SPascal van Leeuwen 	SAFEXCEL_CHACHA20,
42fcca797dSPascal van Leeuwen 	SAFEXCEL_SM4,
43a7dea8c0SOfer Heifetz };
44a7dea8c0SOfer Heifetz 
451b44c5a6SAntoine Ténart struct safexcel_cipher_ctx {
461b44c5a6SAntoine Ténart 	struct safexcel_context base;
471b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv;
481b44c5a6SAntoine Ténart 
491b44c5a6SAntoine Ténart 	u32 mode;
50a7dea8c0SOfer Heifetz 	enum safexcel_cipher_alg alg;
51098e51e5SPascal van Leeuwen 	u8 aead; /* !=0=AEAD, 2=IPSec ESP AEAD, 3=IPsec ESP GMAC */
52098e51e5SPascal van Leeuwen 	u8 xcm;  /* 0=authenc, 1=GCM, 2 reserved for CCM */
53098e51e5SPascal van Leeuwen 	u8 aadskip;
54098e51e5SPascal van Leeuwen 	u8 blocksz;
55098e51e5SPascal van Leeuwen 	u32 ivmask;
56098e51e5SPascal van Leeuwen 	u32 ctrinit;
571b44c5a6SAntoine Ténart 
58c7da38a7SPascal van Leeuwen 	__le32 key[16];
5954f9e8faSPascal van Leeuwen 	u32 nonce;
60c7da38a7SPascal van Leeuwen 	unsigned int key_len, xts;
61f6beaea3SAntoine Tenart 
62f6beaea3SAntoine Tenart 	/* All the below is AEAD specific */
63a7dea8c0SOfer Heifetz 	u32 hash_alg;
64f6beaea3SAntoine Tenart 	u32 state_sz;
653e450886SPascal van Leeuwen 
66a6061921SPascal van Leeuwen 	struct crypto_aead *fback;
671b44c5a6SAntoine Ténart };
681b44c5a6SAntoine Ténart 
691eb7b403SOfer Heifetz struct safexcel_cipher_req {
70847ccfc5SOfer Heifetz 	enum safexcel_cipher_direction direction;
7189332590SAntoine Tenart 	/* Number of result descriptors associated to the request */
7289332590SAntoine Tenart 	unsigned int rdescs;
731eb7b403SOfer Heifetz 	bool needs_inv;
7419b347b3SPascal van Leeuwen 	int  nr_src, nr_dst;
751eb7b403SOfer Heifetz };
761eb7b403SOfer Heifetz 
77098e51e5SPascal van Leeuwen static int safexcel_skcipher_iv(struct safexcel_cipher_ctx *ctx, u8 *iv,
780e17e362SPascal van Leeuwen 				struct safexcel_command_desc *cdesc)
791b44c5a6SAntoine Ténart {
80098e51e5SPascal van Leeuwen 	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) {
81493e289cSPascal van Leeuwen 		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
82493e289cSPascal van Leeuwen 		/* 32 bit nonce */
83493e289cSPascal van Leeuwen 		cdesc->control_data.token[0] = ctx->nonce;
84493e289cSPascal van Leeuwen 		/* 64 bit IV part */
85493e289cSPascal van Leeuwen 		memcpy(&cdesc->control_data.token[1], iv, 8);
86098e51e5SPascal van Leeuwen 		/* 32 bit counter, start at 0 or 1 (big endian!) */
8713a1bb93SPascal van Leeuwen 		cdesc->control_data.token[3] =
88098e51e5SPascal van Leeuwen 			(__force u32)cpu_to_be32(ctx->ctrinit);
89098e51e5SPascal van Leeuwen 		return 4;
90a19052d4SPascal van Leeuwen 	}
91a19052d4SPascal van Leeuwen 	if (ctx->alg == SAFEXCEL_CHACHA20) {
924a593fb3SPascal van Leeuwen 		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
934a593fb3SPascal van Leeuwen 		/* 96 bit nonce part */
944a593fb3SPascal van Leeuwen 		memcpy(&cdesc->control_data.token[0], &iv[4], 12);
954a593fb3SPascal van Leeuwen 		/* 32 bit counter */
964a593fb3SPascal van Leeuwen 		cdesc->control_data.token[3] = *(u32 *)iv;
97098e51e5SPascal van Leeuwen 		return 4;
98493e289cSPascal van Leeuwen 	}
99493e289cSPascal van Leeuwen 
100098e51e5SPascal van Leeuwen 	cdesc->control_data.options |= ctx->ivmask;
101098e51e5SPascal van Leeuwen 	memcpy(cdesc->control_data.token, iv, ctx->blocksz);
102098e51e5SPascal van Leeuwen 	return ctx->blocksz / sizeof(u32);
10354f9e8faSPascal van Leeuwen }
1040e17e362SPascal van Leeuwen 
1050e17e362SPascal van Leeuwen static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
1060e17e362SPascal van Leeuwen 				    struct safexcel_command_desc *cdesc,
107098e51e5SPascal van Leeuwen 				    struct safexcel_token *atoken,
1080e17e362SPascal van Leeuwen 				    u32 length)
1090e17e362SPascal van Leeuwen {
1100e17e362SPascal van Leeuwen 	struct safexcel_token *token;
111098e51e5SPascal van Leeuwen 	int ivlen;
1120e17e362SPascal van Leeuwen 
113098e51e5SPascal van Leeuwen 	ivlen = safexcel_skcipher_iv(ctx, iv, cdesc);
114098e51e5SPascal van Leeuwen 	if (ivlen == 4) {
115098e51e5SPascal van Leeuwen 		/* No space in cdesc, instruction moves to atoken */
116098e51e5SPascal van Leeuwen 		cdesc->additional_cdata_size = 1;
117098e51e5SPascal van Leeuwen 		token = atoken;
118098e51e5SPascal van Leeuwen 	} else {
119098e51e5SPascal van Leeuwen 		/* Everything fits in cdesc */
120098e51e5SPascal van Leeuwen 		token = (struct safexcel_token *)(cdesc->control_data.token + 2);
121098e51e5SPascal van Leeuwen 		/* Need to pad with NOP */
122098e51e5SPascal van Leeuwen 		eip197_noop_token(&token[1]);
123098e51e5SPascal van Leeuwen 	}
1241b44c5a6SAntoine Ténart 
125098e51e5SPascal van Leeuwen 	token->opcode = EIP197_TOKEN_OPCODE_DIRECTION;
126098e51e5SPascal van Leeuwen 	token->packet_length = length;
127098e51e5SPascal van Leeuwen 	token->stat = EIP197_TOKEN_STAT_LAST_PACKET |
12815f64ee0SAntoine Tenart 		      EIP197_TOKEN_STAT_LAST_HASH;
129098e51e5SPascal van Leeuwen 	token->instructions = EIP197_TOKEN_INS_LAST |
130a74d850fSPascal van Leeuwen 			      EIP197_TOKEN_INS_TYPE_CRYPTO |
1311b44c5a6SAntoine Ténart 			      EIP197_TOKEN_INS_TYPE_OUTPUT;
1321b44c5a6SAntoine Ténart }
1331b44c5a6SAntoine Ténart 
134098e51e5SPascal van Leeuwen static void safexcel_aead_iv(struct safexcel_cipher_ctx *ctx, u8 *iv,
135098e51e5SPascal van Leeuwen 			     struct safexcel_command_desc *cdesc)
136098e51e5SPascal van Leeuwen {
137098e51e5SPascal van Leeuwen 	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD ||
138098e51e5SPascal van Leeuwen 	    ctx->aead & EIP197_AEAD_TYPE_IPSEC_ESP) { /* _ESP and _ESP_GMAC */
139098e51e5SPascal van Leeuwen 		/* 32 bit nonce */
140098e51e5SPascal van Leeuwen 		cdesc->control_data.token[0] = ctx->nonce;
141098e51e5SPascal van Leeuwen 		/* 64 bit IV part */
142098e51e5SPascal van Leeuwen 		memcpy(&cdesc->control_data.token[1], iv, 8);
143098e51e5SPascal van Leeuwen 		/* 32 bit counter, start at 0 or 1 (big endian!) */
144098e51e5SPascal van Leeuwen 		cdesc->control_data.token[3] =
145098e51e5SPascal van Leeuwen 			(__force u32)cpu_to_be32(ctx->ctrinit);
146098e51e5SPascal van Leeuwen 		return;
147098e51e5SPascal van Leeuwen 	}
148098e51e5SPascal van Leeuwen 	if (ctx->xcm == EIP197_XCM_MODE_GCM || ctx->alg == SAFEXCEL_CHACHA20) {
149098e51e5SPascal van Leeuwen 		/* 96 bit IV part */
150098e51e5SPascal van Leeuwen 		memcpy(&cdesc->control_data.token[0], iv, 12);
151098e51e5SPascal van Leeuwen 		/* 32 bit counter, start at 0 or 1 (big endian!) */
152098e51e5SPascal van Leeuwen 		cdesc->control_data.token[3] =
153098e51e5SPascal van Leeuwen 			(__force u32)cpu_to_be32(ctx->ctrinit);
154098e51e5SPascal van Leeuwen 		return;
155098e51e5SPascal van Leeuwen 	}
156098e51e5SPascal van Leeuwen 	/* CBC */
157098e51e5SPascal van Leeuwen 	memcpy(cdesc->control_data.token, iv, ctx->blocksz);
158098e51e5SPascal van Leeuwen }
159098e51e5SPascal van Leeuwen 
160f6beaea3SAntoine Tenart static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
161f6beaea3SAntoine Tenart 				struct safexcel_command_desc *cdesc,
162098e51e5SPascal van Leeuwen 				struct safexcel_token *atoken,
163f6beaea3SAntoine Tenart 				enum safexcel_cipher_direction direction,
164f6beaea3SAntoine Tenart 				u32 cryptlen, u32 assoclen, u32 digestsize)
165f6beaea3SAntoine Tenart {
166098e51e5SPascal van Leeuwen 	struct safexcel_token *aadref;
167098e51e5SPascal van Leeuwen 	int atoksize = 2; /* Start with minimum size */
168098e51e5SPascal van Leeuwen 	int assocadj = assoclen - ctx->aadskip, aadalign;
169f6beaea3SAntoine Tenart 
170098e51e5SPascal van Leeuwen 	/* Always 4 dwords of embedded IV  for AEAD modes */
171098e51e5SPascal van Leeuwen 	cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
172f6beaea3SAntoine Tenart 
173098e51e5SPascal van Leeuwen 	if (direction == SAFEXCEL_DECRYPT)
174d2d9e6fdSPascal van Leeuwen 		cryptlen -= digestsize;
175d2d9e6fdSPascal van Leeuwen 
176098e51e5SPascal van Leeuwen 	if (unlikely(ctx->xcm == EIP197_XCM_MODE_CCM)) {
177098e51e5SPascal van Leeuwen 		/* Construct IV block B0 for the CBC-MAC */
178098e51e5SPascal van Leeuwen 		u8 *final_iv = (u8 *)cdesc->control_data.token;
179098e51e5SPascal van Leeuwen 		u8 *cbcmaciv = (u8 *)&atoken[1];
180098e51e5SPascal van Leeuwen 		__le32 *aadlen = (__le32 *)&atoken[5];
18154f9e8faSPascal van Leeuwen 
182098e51e5SPascal van Leeuwen 		if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
183098e51e5SPascal van Leeuwen 			/* Length + nonce */
184098e51e5SPascal van Leeuwen 			cdesc->control_data.token[0] = ctx->nonce;
185098e51e5SPascal van Leeuwen 			/* Fixup flags byte */
186098e51e5SPascal van Leeuwen 			*(__le32 *)cbcmaciv =
187098e51e5SPascal van Leeuwen 				cpu_to_le32(ctx->nonce |
188098e51e5SPascal van Leeuwen 					    ((assocadj > 0) << 6) |
189098e51e5SPascal van Leeuwen 					    ((digestsize - 2) << 2));
190098e51e5SPascal van Leeuwen 			/* 64 bit IV part */
191098e51e5SPascal van Leeuwen 			memcpy(&cdesc->control_data.token[1], iv, 8);
192098e51e5SPascal van Leeuwen 			memcpy(cbcmaciv + 4, iv, 8);
193098e51e5SPascal van Leeuwen 			/* Start counter at 0 */
194098e51e5SPascal van Leeuwen 			cdesc->control_data.token[3] = 0;
195098e51e5SPascal van Leeuwen 			/* Message length */
196098e51e5SPascal van Leeuwen 			*(__be32 *)(cbcmaciv + 12) = cpu_to_be32(cryptlen);
197098e51e5SPascal van Leeuwen 		} else {
198098e51e5SPascal van Leeuwen 			/* Variable length IV part */
199098e51e5SPascal van Leeuwen 			memcpy(final_iv, iv, 15 - iv[0]);
200098e51e5SPascal van Leeuwen 			memcpy(cbcmaciv, iv, 15 - iv[0]);
201098e51e5SPascal van Leeuwen 			/* Start variable length counter at 0 */
202098e51e5SPascal van Leeuwen 			memset(final_iv + 15 - iv[0], 0, iv[0] + 1);
203098e51e5SPascal van Leeuwen 			memset(cbcmaciv + 15 - iv[0], 0, iv[0] - 1);
204098e51e5SPascal van Leeuwen 			/* fixup flags byte */
205098e51e5SPascal van Leeuwen 			cbcmaciv[0] |= ((assocadj > 0) << 6) |
206098e51e5SPascal van Leeuwen 				       ((digestsize - 2) << 2);
207098e51e5SPascal van Leeuwen 			/* insert lower 2 bytes of message length */
208098e51e5SPascal van Leeuwen 			cbcmaciv[14] = cryptlen >> 8;
209098e51e5SPascal van Leeuwen 			cbcmaciv[15] = cryptlen & 255;
210f6beaea3SAntoine Tenart 		}
21154f9e8faSPascal van Leeuwen 
212098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
213098e51e5SPascal van Leeuwen 		atoken->packet_length = AES_BLOCK_SIZE +
214098e51e5SPascal van Leeuwen 					((assocadj > 0) << 1);
215098e51e5SPascal van Leeuwen 		atoken->stat = 0;
216098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_ORIGIN_TOKEN |
217098e51e5SPascal van Leeuwen 				       EIP197_TOKEN_INS_TYPE_HASH;
218098e51e5SPascal van Leeuwen 
219098e51e5SPascal van Leeuwen 		if (likely(assocadj)) {
220098e51e5SPascal van Leeuwen 			*aadlen = cpu_to_le32((assocadj >> 8) |
221098e51e5SPascal van Leeuwen 					      (assocadj & 255) << 8);
222098e51e5SPascal van Leeuwen 			atoken += 6;
223098e51e5SPascal van Leeuwen 			atoksize += 7;
224098e51e5SPascal van Leeuwen 		} else {
225098e51e5SPascal van Leeuwen 			atoken += 5;
226098e51e5SPascal van Leeuwen 			atoksize += 6;
227098e51e5SPascal van Leeuwen 		}
228098e51e5SPascal van Leeuwen 
229098e51e5SPascal van Leeuwen 		/* Process AAD data */
230098e51e5SPascal van Leeuwen 		aadref = atoken;
231098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION;
232098e51e5SPascal van Leeuwen 		atoken->packet_length = assocadj;
233098e51e5SPascal van Leeuwen 		atoken->stat = 0;
234098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH;
235098e51e5SPascal van Leeuwen 		atoken++;
236098e51e5SPascal van Leeuwen 
237098e51e5SPascal van Leeuwen 		/* For CCM only, align AAD data towards hash engine */
238098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
239098e51e5SPascal van Leeuwen 		aadalign = (assocadj + 2) & 15;
240098e51e5SPascal van Leeuwen 		atoken->packet_length = assocadj && aadalign ?
241098e51e5SPascal van Leeuwen 						16 - aadalign :
242098e51e5SPascal van Leeuwen 						0;
243098e51e5SPascal van Leeuwen 		if (likely(cryptlen)) {
244098e51e5SPascal van Leeuwen 			atoken->stat = 0;
245098e51e5SPascal van Leeuwen 			atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH;
246098e51e5SPascal van Leeuwen 		} else {
247098e51e5SPascal van Leeuwen 			atoken->stat = EIP197_TOKEN_STAT_LAST_HASH;
248098e51e5SPascal van Leeuwen 			atoken->instructions = EIP197_TOKEN_INS_LAST |
249098e51e5SPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_HASH;
250098e51e5SPascal van Leeuwen 		}
251098e51e5SPascal van Leeuwen 	} else {
252098e51e5SPascal van Leeuwen 		safexcel_aead_iv(ctx, iv, cdesc);
253098e51e5SPascal van Leeuwen 
254098e51e5SPascal van Leeuwen 		/* Process AAD data */
255098e51e5SPascal van Leeuwen 		aadref = atoken;
256098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION;
257098e51e5SPascal van Leeuwen 		atoken->packet_length = assocadj;
258098e51e5SPascal van Leeuwen 		atoken->stat = EIP197_TOKEN_STAT_LAST_HASH;
259098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_LAST |
260098e51e5SPascal van Leeuwen 				       EIP197_TOKEN_INS_TYPE_HASH;
261098e51e5SPascal van Leeuwen 	}
262098e51e5SPascal van Leeuwen 	atoken++;
263098e51e5SPascal van Leeuwen 
264a6061921SPascal van Leeuwen 	if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
26592c60cefSPascal van Leeuwen 		/* For ESP mode (and not GMAC), skip over the IV */
266098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION;
267098e51e5SPascal van Leeuwen 		atoken->packet_length = EIP197_AEAD_IPSEC_IV_SIZE;
268098e51e5SPascal van Leeuwen 		atoken->stat = 0;
269098e51e5SPascal van Leeuwen 		atoken->instructions = 0;
270098e51e5SPascal van Leeuwen 		atoken++;
271098e51e5SPascal van Leeuwen 		atoksize++;
272098e51e5SPascal van Leeuwen 	} else if (unlikely(ctx->alg == SAFEXCEL_CHACHA20 &&
273098e51e5SPascal van Leeuwen 			    direction == SAFEXCEL_DECRYPT)) {
274098e51e5SPascal van Leeuwen 		/* Poly-chacha decryption needs a dummy NOP here ... */
275098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
276098e51e5SPascal van Leeuwen 		atoken->packet_length = 16; /* According to Op Manual */
277098e51e5SPascal van Leeuwen 		atoken->stat = 0;
278098e51e5SPascal van Leeuwen 		atoken->instructions = 0;
279098e51e5SPascal van Leeuwen 		atoken++;
280098e51e5SPascal van Leeuwen 		atoksize++;
281a6061921SPascal van Leeuwen 	}
282a6061921SPascal van Leeuwen 
283098e51e5SPascal van Leeuwen 	if  (ctx->xcm) {
284098e51e5SPascal van Leeuwen 		/* For GCM and CCM, obtain enc(Y0) */
285098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT_REMRES;
286098e51e5SPascal van Leeuwen 		atoken->packet_length = 0;
287098e51e5SPascal van Leeuwen 		atoken->stat = 0;
288098e51e5SPascal van Leeuwen 		atoken->instructions = AES_BLOCK_SIZE;
289098e51e5SPascal van Leeuwen 		atoken++;
290098e51e5SPascal van Leeuwen 
291098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
292098e51e5SPascal van Leeuwen 		atoken->packet_length = AES_BLOCK_SIZE;
293098e51e5SPascal van Leeuwen 		atoken->stat = 0;
294098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
295098e51e5SPascal van Leeuwen 				       EIP197_TOKEN_INS_TYPE_CRYPTO;
296098e51e5SPascal van Leeuwen 		atoken++;
297098e51e5SPascal van Leeuwen 		atoksize += 2;
298098e51e5SPascal van Leeuwen 	}
29954f9e8faSPascal van Leeuwen 
300a6061921SPascal van Leeuwen 	if (likely(cryptlen || ctx->alg == SAFEXCEL_CHACHA20)) {
301098e51e5SPascal van Leeuwen 		/* Fixup stat field for AAD direction instruction */
302098e51e5SPascal van Leeuwen 		aadref->stat = 0;
303098e51e5SPascal van Leeuwen 
304098e51e5SPascal van Leeuwen 		/* Process crypto data */
305098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION;
306098e51e5SPascal van Leeuwen 		atoken->packet_length = cryptlen;
307098e51e5SPascal van Leeuwen 
30892c60cefSPascal van Leeuwen 		if (unlikely(ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP_GMAC)) {
309098e51e5SPascal van Leeuwen 			/* Fixup instruction field for AAD dir instruction */
310098e51e5SPascal van Leeuwen 			aadref->instructions = EIP197_TOKEN_INS_TYPE_HASH;
311098e51e5SPascal van Leeuwen 
31292c60cefSPascal van Leeuwen 			/* Do not send to crypt engine in case of GMAC */
313098e51e5SPascal van Leeuwen 			atoken->instructions = EIP197_TOKEN_INS_LAST |
31492c60cefSPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_HASH |
31592c60cefSPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_OUTPUT;
31692c60cefSPascal van Leeuwen 		} else {
317098e51e5SPascal van Leeuwen 			atoken->instructions = EIP197_TOKEN_INS_LAST |
31854f9e8faSPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_CRYPTO |
31954f9e8faSPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_HASH |
32054f9e8faSPascal van Leeuwen 					       EIP197_TOKEN_INS_TYPE_OUTPUT;
32192c60cefSPascal van Leeuwen 		}
3223e450886SPascal van Leeuwen 
3234eb76fafSPascal van Leeuwen 		cryptlen &= 15;
324098e51e5SPascal van Leeuwen 		if (unlikely(ctx->xcm == EIP197_XCM_MODE_CCM && cryptlen)) {
325098e51e5SPascal van Leeuwen 			atoken->stat = 0;
326098e51e5SPascal van Leeuwen 			/* For CCM only, pad crypto data to the hash engine */
327098e51e5SPascal van Leeuwen 			atoken++;
328098e51e5SPascal van Leeuwen 			atoksize++;
329098e51e5SPascal van Leeuwen 			atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
330098e51e5SPascal van Leeuwen 			atoken->packet_length = 16 - cryptlen;
331098e51e5SPascal van Leeuwen 			atoken->stat = EIP197_TOKEN_STAT_LAST_HASH;
332098e51e5SPascal van Leeuwen 			atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH;
3334eb76fafSPascal van Leeuwen 		} else {
334098e51e5SPascal van Leeuwen 			atoken->stat = EIP197_TOKEN_STAT_LAST_HASH;
3354eb76fafSPascal van Leeuwen 		}
336098e51e5SPascal van Leeuwen 		atoken++;
337098e51e5SPascal van Leeuwen 		atoksize++;
3383e450886SPascal van Leeuwen 	}
339098e51e5SPascal van Leeuwen 
340098e51e5SPascal van Leeuwen 	if (direction == SAFEXCEL_ENCRYPT) {
341098e51e5SPascal van Leeuwen 		/* Append ICV */
342098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_INSERT;
343098e51e5SPascal van Leeuwen 		atoken->packet_length = digestsize;
344098e51e5SPascal van Leeuwen 		atoken->stat = EIP197_TOKEN_STAT_LAST_HASH |
345098e51e5SPascal van Leeuwen 			       EIP197_TOKEN_STAT_LAST_PACKET;
346098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
347098e51e5SPascal van Leeuwen 				       EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
348098e51e5SPascal van Leeuwen 	} else {
349098e51e5SPascal van Leeuwen 		/* Extract ICV */
350098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_RETRIEVE;
351098e51e5SPascal van Leeuwen 		atoken->packet_length = digestsize;
352098e51e5SPascal van Leeuwen 		atoken->stat = EIP197_TOKEN_STAT_LAST_HASH |
353098e51e5SPascal van Leeuwen 			       EIP197_TOKEN_STAT_LAST_PACKET;
354098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
355098e51e5SPascal van Leeuwen 		atoken++;
356098e51e5SPascal van Leeuwen 		atoksize++;
357098e51e5SPascal van Leeuwen 
358098e51e5SPascal van Leeuwen 		/* Verify ICV */
359098e51e5SPascal van Leeuwen 		atoken->opcode = EIP197_TOKEN_OPCODE_VERIFY;
360098e51e5SPascal van Leeuwen 		atoken->packet_length = digestsize |
361098e51e5SPascal van Leeuwen 					EIP197_TOKEN_HASH_RESULT_VERIFY;
362098e51e5SPascal van Leeuwen 		atoken->stat = EIP197_TOKEN_STAT_LAST_HASH |
363098e51e5SPascal van Leeuwen 			       EIP197_TOKEN_STAT_LAST_PACKET;
364098e51e5SPascal van Leeuwen 		atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT;
365098e51e5SPascal van Leeuwen 	}
366098e51e5SPascal van Leeuwen 
367098e51e5SPascal van Leeuwen 	/* Fixup length of the token in the command descriptor */
368098e51e5SPascal van Leeuwen 	cdesc->additional_cdata_size = atoksize;
369f6beaea3SAntoine Tenart }
370f6beaea3SAntoine Tenart 
3718ac1283eSAntoine Tenart static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm,
3728ac1283eSAntoine Tenart 					const u8 *key, unsigned int len)
3731b44c5a6SAntoine Ténart {
3741b44c5a6SAntoine Ténart 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3751b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
37618e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
3771b44c5a6SAntoine Ténart 	struct crypto_aes_ctx aes;
3781b44c5a6SAntoine Ténart 	int ret, i;
3791b44c5a6SAntoine Ténart 
380363a90c2SArd Biesheuvel 	ret = aes_expandkey(&aes, key, len);
381674f368aSEric Biggers 	if (ret)
3821b44c5a6SAntoine Ténart 		return ret;
3831b44c5a6SAntoine Ténart 
38453c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
3851b44c5a6SAntoine Ténart 		for (i = 0; i < len / sizeof(u32); i++) {
38613a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
3871b44c5a6SAntoine Ténart 				ctx->base.needs_inv = true;
3881b44c5a6SAntoine Ténart 				break;
3891b44c5a6SAntoine Ténart 			}
3901b44c5a6SAntoine Ténart 		}
391c4daf4ccSOfer Heifetz 	}
3921b44c5a6SAntoine Ténart 
3931b44c5a6SAntoine Ténart 	for (i = 0; i < len / sizeof(u32); i++)
3941b44c5a6SAntoine Ténart 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
3951b44c5a6SAntoine Ténart 
3961b44c5a6SAntoine Ténart 	ctx->key_len = len;
3971b44c5a6SAntoine Ténart 
3981b44c5a6SAntoine Ténart 	memzero_explicit(&aes, sizeof(aes));
3991b44c5a6SAntoine Ténart 	return 0;
4001b44c5a6SAntoine Ténart }
4011b44c5a6SAntoine Ténart 
40277cdd4efSPascal van Leeuwen static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key,
403f6beaea3SAntoine Tenart 				unsigned int len)
404f6beaea3SAntoine Tenart {
405f6beaea3SAntoine Tenart 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
406f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
40718e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
408f6beaea3SAntoine Tenart 	struct crypto_authenc_keys keys;
4090e17e362SPascal van Leeuwen 	struct crypto_aes_ctx aes;
41013a1bb93SPascal van Leeuwen 	int err = -EINVAL, i;
41163cdd870SHerbert Xu 	const char *alg;
412f6beaea3SAntoine Tenart 
4131769f704SPascal van Leeuwen 	if (unlikely(crypto_authenc_extractkeys(&keys, key, len)))
414f6beaea3SAntoine Tenart 		goto badkey;
415f6beaea3SAntoine Tenart 
4160e17e362SPascal van Leeuwen 	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) {
4171769f704SPascal van Leeuwen 		/* Must have at least space for the nonce here */
4181769f704SPascal van Leeuwen 		if (unlikely(keys.enckeylen < CTR_RFC3686_NONCE_SIZE))
419f6beaea3SAntoine Tenart 			goto badkey;
4200e17e362SPascal van Leeuwen 		/* last 4 bytes of key are the nonce! */
421f26882a3SPascal van Leeuwen 		ctx->nonce = *(u32 *)(keys.enckey + keys.enckeylen -
422f26882a3SPascal van Leeuwen 				      CTR_RFC3686_NONCE_SIZE);
4230e17e362SPascal van Leeuwen 		/* exclude the nonce here */
4241769f704SPascal van Leeuwen 		keys.enckeylen -= CTR_RFC3686_NONCE_SIZE;
4250e17e362SPascal van Leeuwen 	}
426f6beaea3SAntoine Tenart 
427f6beaea3SAntoine Tenart 	/* Encryption key */
4280e17e362SPascal van Leeuwen 	switch (ctx->alg) {
429bb7679b8SPascal van Leeuwen 	case SAFEXCEL_DES:
430bb7679b8SPascal van Leeuwen 		err = verify_aead_des_key(ctfm, keys.enckey, keys.enckeylen);
431bb7679b8SPascal van Leeuwen 		if (unlikely(err))
432674f368aSEric Biggers 			goto badkey;
433bb7679b8SPascal van Leeuwen 		break;
4340e17e362SPascal van Leeuwen 	case SAFEXCEL_3DES:
43521f5a15eSArd Biesheuvel 		err = verify_aead_des3_key(ctfm, keys.enckey, keys.enckeylen);
43677cdd4efSPascal van Leeuwen 		if (unlikely(err))
437674f368aSEric Biggers 			goto badkey;
4380e17e362SPascal van Leeuwen 		break;
4390e17e362SPascal van Leeuwen 	case SAFEXCEL_AES:
4400e17e362SPascal van Leeuwen 		err = aes_expandkey(&aes, keys.enckey, keys.enckeylen);
4410e17e362SPascal van Leeuwen 		if (unlikely(err))
4420e17e362SPascal van Leeuwen 			goto badkey;
4430e17e362SPascal van Leeuwen 		break;
4441769f704SPascal van Leeuwen 	case SAFEXCEL_SM4:
4451769f704SPascal van Leeuwen 		if (unlikely(keys.enckeylen != SM4_KEY_SIZE))
4461769f704SPascal van Leeuwen 			goto badkey;
4471769f704SPascal van Leeuwen 		break;
4480e17e362SPascal van Leeuwen 	default:
4490e17e362SPascal van Leeuwen 		dev_err(priv->dev, "aead: unsupported cipher algorithm\n");
4500e17e362SPascal van Leeuwen 		goto badkey;
45177cdd4efSPascal van Leeuwen 	}
45277cdd4efSPascal van Leeuwen 
45313a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
45413a1bb93SPascal van Leeuwen 		for (i = 0; i < keys.enckeylen / sizeof(u32); i++) {
455b8151220SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) !=
456b8151220SPascal van Leeuwen 			    ((u32 *)keys.enckey)[i]) {
457f6beaea3SAntoine Tenart 				ctx->base.needs_inv = true;
45813a1bb93SPascal van Leeuwen 				break;
45913a1bb93SPascal van Leeuwen 			}
46013a1bb93SPascal van Leeuwen 		}
46113a1bb93SPascal van Leeuwen 	}
462f6beaea3SAntoine Tenart 
463f6beaea3SAntoine Tenart 	/* Auth key */
464a7dea8c0SOfer Heifetz 	switch (ctx->hash_alg) {
46501ba061dSAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA1:
46663cdd870SHerbert Xu 		alg = "safexcel-sha1";
46701ba061dSAntoine Tenart 		break;
468678b2878SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA224:
46963cdd870SHerbert Xu 		alg = "safexcel-sha224";
470678b2878SAntoine Tenart 		break;
471678b2878SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA256:
47263cdd870SHerbert Xu 		alg = "safexcel-sha256";
473678b2878SAntoine Tenart 		break;
474ea23cb53SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA384:
47563cdd870SHerbert Xu 		alg = "safexcel-sha384";
476ea23cb53SAntoine Tenart 		break;
47787eee125SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA512:
47863cdd870SHerbert Xu 		alg = "safexcel-sha512";
47987eee125SAntoine Tenart 		break;
4801769f704SPascal van Leeuwen 	case CONTEXT_CONTROL_CRYPTO_ALG_SM3:
48163cdd870SHerbert Xu 		alg = "safexcel-sm3";
4821769f704SPascal van Leeuwen 		break;
483678b2878SAntoine Tenart 	default:
4841a61af28SColin Ian King 		dev_err(priv->dev, "aead: unsupported hash algorithm\n");
485678b2878SAntoine Tenart 		goto badkey;
486678b2878SAntoine Tenart 	}
487f6beaea3SAntoine Tenart 
48863cdd870SHerbert Xu 	if (safexcel_hmac_setkey(&ctx->base, keys.authkey, keys.authkeylen,
48963cdd870SHerbert Xu 				 alg, ctx->state_sz))
49063cdd870SHerbert Xu 		goto badkey;
491f6beaea3SAntoine Tenart 
492f6beaea3SAntoine Tenart 	/* Now copy the keys into the context */
49313a1bb93SPascal van Leeuwen 	for (i = 0; i < keys.enckeylen / sizeof(u32); i++)
494b8151220SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(((u32 *)keys.enckey)[i]);
495f6beaea3SAntoine Tenart 	ctx->key_len = keys.enckeylen;
496f6beaea3SAntoine Tenart 
497f6beaea3SAntoine Tenart 	memzero_explicit(&keys, sizeof(keys));
498f6beaea3SAntoine Tenart 	return 0;
499f6beaea3SAntoine Tenart 
500f6beaea3SAntoine Tenart badkey:
501f6beaea3SAntoine Tenart 	memzero_explicit(&keys, sizeof(keys));
5020e17e362SPascal van Leeuwen 	return err;
503f6beaea3SAntoine Tenart }
504f6beaea3SAntoine Tenart 
5051b44c5a6SAntoine Ténart static int safexcel_context_control(struct safexcel_cipher_ctx *ctx,
506847ccfc5SOfer Heifetz 				    struct crypto_async_request *async,
5078ac1283eSAntoine Tenart 				    struct safexcel_cipher_req *sreq,
5081b44c5a6SAntoine Ténart 				    struct safexcel_command_desc *cdesc)
5091b44c5a6SAntoine Ténart {
51018e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
511d2d9e6fdSPascal van Leeuwen 	int ctrl_size = ctx->key_len / sizeof(u32);
512d2d9e6fdSPascal van Leeuwen 
513d2d9e6fdSPascal van Leeuwen 	cdesc->control_data.control1 = ctx->mode;
5141b44c5a6SAntoine Ténart 
515f6beaea3SAntoine Tenart 	if (ctx->aead) {
516d2d9e6fdSPascal van Leeuwen 		/* Take in account the ipad+opad digests */
5173e450886SPascal van Leeuwen 		if (ctx->xcm) {
5183e450886SPascal van Leeuwen 			ctrl_size += ctx->state_sz / sizeof(u32);
5193e450886SPascal van Leeuwen 			cdesc->control_data.control0 =
5203e450886SPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
5213e450886SPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
5223e450886SPascal van Leeuwen 				ctx->hash_alg |
5233e450886SPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
524a6061921SPascal van Leeuwen 		} else if (ctx->alg == SAFEXCEL_CHACHA20) {
525a6061921SPascal van Leeuwen 			/* Chacha20-Poly1305 */
526a6061921SPascal van Leeuwen 			cdesc->control_data.control0 =
527a6061921SPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
528a6061921SPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20 |
529a6061921SPascal van Leeuwen 				(sreq->direction == SAFEXCEL_ENCRYPT ?
530a6061921SPascal van Leeuwen 					CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT :
531a6061921SPascal van Leeuwen 					CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN) |
532a6061921SPascal van Leeuwen 				ctx->hash_alg |
533a6061921SPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
534a6061921SPascal van Leeuwen 			return 0;
5353e450886SPascal van Leeuwen 		} else {
536d2d9e6fdSPascal van Leeuwen 			ctrl_size += ctx->state_sz / sizeof(u32) * 2;
5373e450886SPascal van Leeuwen 			cdesc->control_data.control0 =
5383e450886SPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
5393e450886SPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_HMAC |
5403e450886SPascal van Leeuwen 				ctx->hash_alg |
5413e450886SPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
5423e450886SPascal van Leeuwen 		}
5434eb76fafSPascal van Leeuwen 
54492c60cefSPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_ENCRYPT &&
54592c60cefSPascal van Leeuwen 		    (ctx->xcm == EIP197_XCM_MODE_CCM ||
54692c60cefSPascal van Leeuwen 		     ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP_GMAC))
54792c60cefSPascal van Leeuwen 			cdesc->control_data.control0 |=
54892c60cefSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_ENCRYPT_OUT;
54992c60cefSPascal van Leeuwen 		else if (sreq->direction == SAFEXCEL_ENCRYPT)
55092c60cefSPascal van Leeuwen 			cdesc->control_data.control0 |=
55192c60cefSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT;
55292c60cefSPascal van Leeuwen 		else if (ctx->xcm == EIP197_XCM_MODE_CCM)
55392c60cefSPascal van Leeuwen 			cdesc->control_data.control0 |=
55492c60cefSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_DECRYPT_HASH_IN;
555d2d9e6fdSPascal van Leeuwen 		else
5563e450886SPascal van Leeuwen 			cdesc->control_data.control0 |=
5573e450886SPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN;
558d2d9e6fdSPascal van Leeuwen 	} else {
559d2d9e6fdSPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_ENCRYPT)
560d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 =
561d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_CRYPTO_OUT |
562d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
563d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
564d2d9e6fdSPascal van Leeuwen 		else
565d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 =
566d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_CRYPTO_IN |
567d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
568d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
569f6beaea3SAntoine Tenart 	}
5701b44c5a6SAntoine Ténart 
571a7dea8c0SOfer Heifetz 	if (ctx->alg == SAFEXCEL_DES) {
572d2d9e6fdSPascal van Leeuwen 		cdesc->control_data.control0 |=
573d2d9e6fdSPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_DES;
57462469879SOfer Heifetz 	} else if (ctx->alg == SAFEXCEL_3DES) {
575d2d9e6fdSPascal van Leeuwen 		cdesc->control_data.control0 |=
576d2d9e6fdSPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_3DES;
577a7dea8c0SOfer Heifetz 	} else if (ctx->alg == SAFEXCEL_AES) {
578c7da38a7SPascal van Leeuwen 		switch (ctx->key_len >> ctx->xts) {
5791b44c5a6SAntoine Ténart 		case AES_KEYSIZE_128:
580d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 |=
581d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_AES128;
5821b44c5a6SAntoine Ténart 			break;
5831b44c5a6SAntoine Ténart 		case AES_KEYSIZE_192:
584d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 |=
585d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_AES192;
5861b44c5a6SAntoine Ténart 			break;
5871b44c5a6SAntoine Ténart 		case AES_KEYSIZE_256:
588d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 |=
589d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_AES256;
5901b44c5a6SAntoine Ténart 			break;
5911b44c5a6SAntoine Ténart 		default:
5921b44c5a6SAntoine Ténart 			dev_err(priv->dev, "aes keysize not supported: %u\n",
593c7da38a7SPascal van Leeuwen 				ctx->key_len >> ctx->xts);
5941b44c5a6SAntoine Ténart 			return -EINVAL;
5951b44c5a6SAntoine Ténart 		}
5964a593fb3SPascal van Leeuwen 	} else if (ctx->alg == SAFEXCEL_CHACHA20) {
5974a593fb3SPascal van Leeuwen 		cdesc->control_data.control0 |=
5984a593fb3SPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20;
599fcca797dSPascal van Leeuwen 	} else if (ctx->alg == SAFEXCEL_SM4) {
600fcca797dSPascal van Leeuwen 		cdesc->control_data.control0 |=
601fcca797dSPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_SM4;
602a7dea8c0SOfer Heifetz 	}
603fef0cfe5SAntoine Tenart 
6041b44c5a6SAntoine Ténart 	return 0;
6051b44c5a6SAntoine Ténart }
6061b44c5a6SAntoine Ténart 
6071eb7b403SOfer Heifetz static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int ring,
6081b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
6098ac1283eSAntoine Tenart 				      struct scatterlist *src,
6108ac1283eSAntoine Tenart 				      struct scatterlist *dst,
6118ac1283eSAntoine Tenart 				      unsigned int cryptlen,
6128ac1283eSAntoine Tenart 				      struct safexcel_cipher_req *sreq,
6131b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
6141b44c5a6SAntoine Ténart {
6155bdb6e6aSPascal van Leeuwen 	struct skcipher_request *areq = skcipher_request_cast(async);
6165bdb6e6aSPascal van Leeuwen 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq);
6175bdb6e6aSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(skcipher);
6181b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
6191b44c5a6SAntoine Ténart 	int ndesc = 0;
6201b44c5a6SAntoine Ténart 
6211b44c5a6SAntoine Ténart 	*ret = 0;
6221b44c5a6SAntoine Ténart 
62389332590SAntoine Tenart 	if (unlikely(!sreq->rdescs))
62489332590SAntoine Tenart 		return 0;
62589332590SAntoine Tenart 
62689332590SAntoine Tenart 	while (sreq->rdescs--) {
6271b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
6281b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
6291b44c5a6SAntoine Ténart 			dev_err(priv->dev,
6301b44c5a6SAntoine Ténart 				"cipher: result: could not retrieve the result descriptor\n");
6311b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
6321b44c5a6SAntoine Ténart 			break;
6331b44c5a6SAntoine Ténart 		}
6341b44c5a6SAntoine Ténart 
635bdfd1909SAntoine Tenart 		if (likely(!*ret))
636bdfd1909SAntoine Tenart 			*ret = safexcel_rdesc_check_errors(priv, rdesc);
6371b44c5a6SAntoine Ténart 
6381b44c5a6SAntoine Ténart 		ndesc++;
63989332590SAntoine Tenart 	}
6401b44c5a6SAntoine Ténart 
6411b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
6421b44c5a6SAntoine Ténart 
6438ac1283eSAntoine Tenart 	if (src == dst) {
64449186a7dSPeter Harliman Liem 		if (sreq->nr_src > 0)
64549186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
64649186a7dSPeter Harliman Liem 				     DMA_BIDIRECTIONAL);
6471b44c5a6SAntoine Ténart 	} else {
64849186a7dSPeter Harliman Liem 		if (sreq->nr_src > 0)
64949186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
65049186a7dSPeter Harliman Liem 				     DMA_TO_DEVICE);
65149186a7dSPeter Harliman Liem 		if (sreq->nr_dst > 0)
65249186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, dst, sreq->nr_dst,
65349186a7dSPeter Harliman Liem 				     DMA_FROM_DEVICE);
6541b44c5a6SAntoine Ténart 	}
6551b44c5a6SAntoine Ténart 
6565bdb6e6aSPascal van Leeuwen 	/*
6575bdb6e6aSPascal van Leeuwen 	 * Update IV in req from last crypto output word for CBC modes
6585bdb6e6aSPascal van Leeuwen 	 */
6595bdb6e6aSPascal van Leeuwen 	if ((!ctx->aead) && (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) &&
6605bdb6e6aSPascal van Leeuwen 	    (sreq->direction == SAFEXCEL_ENCRYPT)) {
6615bdb6e6aSPascal van Leeuwen 		/* For encrypt take the last output word */
66219b347b3SPascal van Leeuwen 		sg_pcopy_to_buffer(dst, sreq->nr_dst, areq->iv,
6635bdb6e6aSPascal van Leeuwen 				   crypto_skcipher_ivsize(skcipher),
6645bdb6e6aSPascal van Leeuwen 				   (cryptlen -
6655bdb6e6aSPascal van Leeuwen 				    crypto_skcipher_ivsize(skcipher)));
6665bdb6e6aSPascal van Leeuwen 	}
6675bdb6e6aSPascal van Leeuwen 
6681b44c5a6SAntoine Ténart 	*should_complete = true;
6691b44c5a6SAntoine Ténart 
6701b44c5a6SAntoine Ténart 	return ndesc;
6711b44c5a6SAntoine Ténart }
6721b44c5a6SAntoine Ténart 
673a7dea8c0SOfer Heifetz static int safexcel_send_req(struct crypto_async_request *base, int ring,
6748ac1283eSAntoine Tenart 			     struct safexcel_cipher_req *sreq,
6758ac1283eSAntoine Tenart 			     struct scatterlist *src, struct scatterlist *dst,
676f6beaea3SAntoine Tenart 			     unsigned int cryptlen, unsigned int assoclen,
677f6beaea3SAntoine Tenart 			     unsigned int digestsize, u8 *iv, int *commands,
6788ac1283eSAntoine Tenart 			     int *results)
6791b44c5a6SAntoine Ténart {
6805bdb6e6aSPascal van Leeuwen 	struct skcipher_request *areq = skcipher_request_cast(base);
6815bdb6e6aSPascal van Leeuwen 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq);
6828ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
68318e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
6841b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc;
68519b347b3SPascal van Leeuwen 	struct safexcel_command_desc *first_cdesc = NULL;
686e5c8ee1fSAntoine Tenart 	struct safexcel_result_desc *rdesc, *first_rdesc = NULL;
6871b44c5a6SAntoine Ténart 	struct scatterlist *sg;
68819b347b3SPascal van Leeuwen 	unsigned int totlen;
68919b347b3SPascal van Leeuwen 	unsigned int totlen_src = cryptlen + assoclen;
69019b347b3SPascal van Leeuwen 	unsigned int totlen_dst = totlen_src;
691098e51e5SPascal van Leeuwen 	struct safexcel_token *atoken;
69219b347b3SPascal van Leeuwen 	int n_cdesc = 0, n_rdesc = 0;
69319b347b3SPascal van Leeuwen 	int queued, i, ret = 0;
69419b347b3SPascal van Leeuwen 	bool first = true;
6951b44c5a6SAntoine Ténart 
69619b347b3SPascal van Leeuwen 	sreq->nr_src = sg_nents_for_len(src, totlen_src);
69719b347b3SPascal van Leeuwen 
69819b347b3SPascal van Leeuwen 	if (ctx->aead) {
69919b347b3SPascal van Leeuwen 		/*
70019b347b3SPascal van Leeuwen 		 * AEAD has auth tag appended to output for encrypt and
70119b347b3SPascal van Leeuwen 		 * removed from the output for decrypt!
70219b347b3SPascal van Leeuwen 		 */
70319b347b3SPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_DECRYPT)
70419b347b3SPascal van Leeuwen 			totlen_dst -= digestsize;
70519b347b3SPascal van Leeuwen 		else
70619b347b3SPascal van Leeuwen 			totlen_dst += digestsize;
70719b347b3SPascal van Leeuwen 
70819b347b3SPascal van Leeuwen 		memcpy(ctx->base.ctxr->data + ctx->key_len / sizeof(u32),
70978cf1c8bSHerbert Xu 		       &ctx->base.ipad, ctx->state_sz);
7103e450886SPascal van Leeuwen 		if (!ctx->xcm)
7113e450886SPascal van Leeuwen 			memcpy(ctx->base.ctxr->data + (ctx->key_len +
71278cf1c8bSHerbert Xu 			       ctx->state_sz) / sizeof(u32), &ctx->base.opad,
7133e450886SPascal van Leeuwen 			       ctx->state_sz);
71419b347b3SPascal van Leeuwen 	} else if ((ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) &&
7155bdb6e6aSPascal van Leeuwen 		   (sreq->direction == SAFEXCEL_DECRYPT)) {
7165bdb6e6aSPascal van Leeuwen 		/*
7175bdb6e6aSPascal van Leeuwen 		 * Save IV from last crypto input word for CBC modes in decrypt
7185bdb6e6aSPascal van Leeuwen 		 * direction. Need to do this first in case of inplace operation
7195bdb6e6aSPascal van Leeuwen 		 * as it will be overwritten.
7205bdb6e6aSPascal van Leeuwen 		 */
72119b347b3SPascal van Leeuwen 		sg_pcopy_to_buffer(src, sreq->nr_src, areq->iv,
7225bdb6e6aSPascal van Leeuwen 				   crypto_skcipher_ivsize(skcipher),
72319b347b3SPascal van Leeuwen 				   (totlen_src -
7245bdb6e6aSPascal van Leeuwen 				    crypto_skcipher_ivsize(skcipher)));
7255bdb6e6aSPascal van Leeuwen 	}
7265bdb6e6aSPascal van Leeuwen 
72719b347b3SPascal van Leeuwen 	sreq->nr_dst = sg_nents_for_len(dst, totlen_dst);
7281b44c5a6SAntoine Ténart 
72919b347b3SPascal van Leeuwen 	/*
73019b347b3SPascal van Leeuwen 	 * Remember actual input length, source buffer length may be
73119b347b3SPascal van Leeuwen 	 * updated in case of inline operation below.
73219b347b3SPascal van Leeuwen 	 */
73319b347b3SPascal van Leeuwen 	totlen = totlen_src;
73419b347b3SPascal van Leeuwen 	queued = totlen_src;
73519b347b3SPascal van Leeuwen 
73619b347b3SPascal van Leeuwen 	if (src == dst) {
73719b347b3SPascal van Leeuwen 		sreq->nr_src = max(sreq->nr_src, sreq->nr_dst);
73819b347b3SPascal van Leeuwen 		sreq->nr_dst = sreq->nr_src;
73919b347b3SPascal van Leeuwen 		if (unlikely((totlen_src || totlen_dst) &&
74019b347b3SPascal van Leeuwen 		    (sreq->nr_src <= 0))) {
74119b347b3SPascal van Leeuwen 			dev_err(priv->dev, "In-place buffer not large enough (need %d bytes)!",
74219b347b3SPascal van Leeuwen 				max(totlen_src, totlen_dst));
7431b44c5a6SAntoine Ténart 			return -EINVAL;
7441b44c5a6SAntoine Ténart 		}
74549186a7dSPeter Harliman Liem 		if (sreq->nr_src > 0)
74649186a7dSPeter Harliman Liem 			dma_map_sg(priv->dev, src, sreq->nr_src,
74749186a7dSPeter Harliman Liem 				   DMA_BIDIRECTIONAL);
74819b347b3SPascal van Leeuwen 	} else {
74919b347b3SPascal van Leeuwen 		if (unlikely(totlen_src && (sreq->nr_src <= 0))) {
75019b347b3SPascal van Leeuwen 			dev_err(priv->dev, "Source buffer not large enough (need %d bytes)!",
75119b347b3SPascal van Leeuwen 				totlen_src);
75219b347b3SPascal van Leeuwen 			return -EINVAL;
75319b347b3SPascal van Leeuwen 		}
75449186a7dSPeter Harliman Liem 
75549186a7dSPeter Harliman Liem 		if (sreq->nr_src > 0)
75619b347b3SPascal van Leeuwen 			dma_map_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE);
75719b347b3SPascal van Leeuwen 
75819b347b3SPascal van Leeuwen 		if (unlikely(totlen_dst && (sreq->nr_dst <= 0))) {
75919b347b3SPascal van Leeuwen 			dev_err(priv->dev, "Dest buffer not large enough (need %d bytes)!",
76019b347b3SPascal van Leeuwen 				totlen_dst);
76149186a7dSPeter Harliman Liem 			ret = -EINVAL;
76249186a7dSPeter Harliman Liem 			goto unmap;
76319b347b3SPascal van Leeuwen 		}
76449186a7dSPeter Harliman Liem 
76549186a7dSPeter Harliman Liem 		if (sreq->nr_dst > 0)
76649186a7dSPeter Harliman Liem 			dma_map_sg(priv->dev, dst, sreq->nr_dst,
76749186a7dSPeter Harliman Liem 				   DMA_FROM_DEVICE);
7681b44c5a6SAntoine Ténart 	}
7691b44c5a6SAntoine Ténart 
7701b44c5a6SAntoine Ténart 	memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len);
7711b44c5a6SAntoine Ténart 
772cb97aa94SPascal van Leeuwen 	if (!totlen) {
773cb97aa94SPascal van Leeuwen 		/*
774cb97aa94SPascal van Leeuwen 		 * The EIP97 cannot deal with zero length input packets!
775cb97aa94SPascal van Leeuwen 		 * So stuff a dummy command descriptor indicating a 1 byte
776cb97aa94SPascal van Leeuwen 		 * (dummy) input packet, using the context record as source.
777cb97aa94SPascal van Leeuwen 		 */
778cb97aa94SPascal van Leeuwen 		first_cdesc = safexcel_add_cdesc(priv, ring,
779cb97aa94SPascal van Leeuwen 						 1, 1, ctx->base.ctxr_dma,
780cb97aa94SPascal van Leeuwen 						 1, 1, ctx->base.ctxr_dma,
781cb97aa94SPascal van Leeuwen 						 &atoken);
782cb97aa94SPascal van Leeuwen 		if (IS_ERR(first_cdesc)) {
783cb97aa94SPascal van Leeuwen 			/* No space left in the command descriptor ring */
784cb97aa94SPascal van Leeuwen 			ret = PTR_ERR(first_cdesc);
785cb97aa94SPascal van Leeuwen 			goto cdesc_rollback;
786cb97aa94SPascal van Leeuwen 		}
787cb97aa94SPascal van Leeuwen 		n_cdesc = 1;
788cb97aa94SPascal van Leeuwen 		goto skip_cdesc;
789cb97aa94SPascal van Leeuwen 	}
790f6beaea3SAntoine Tenart 
7911b44c5a6SAntoine Ténart 	/* command descriptors */
79219b347b3SPascal van Leeuwen 	for_each_sg(src, sg, sreq->nr_src, i) {
7931b44c5a6SAntoine Ténart 		int len = sg_dma_len(sg);
7941b44c5a6SAntoine Ténart 
7951b44c5a6SAntoine Ténart 		/* Do not overflow the request */
796cb97aa94SPascal van Leeuwen 		if (queued < len)
7971b44c5a6SAntoine Ténart 			len = queued;
7981b44c5a6SAntoine Ténart 
79919b347b3SPascal van Leeuwen 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
80019b347b3SPascal van Leeuwen 					   !(queued - len),
801f6beaea3SAntoine Tenart 					   sg_dma_address(sg), len, totlen,
802098e51e5SPascal van Leeuwen 					   ctx->base.ctxr_dma, &atoken);
8031b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
8041b44c5a6SAntoine Ténart 			/* No space left in the command descriptor ring */
8051b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
8061b44c5a6SAntoine Ténart 			goto cdesc_rollback;
8071b44c5a6SAntoine Ténart 		}
8081b44c5a6SAntoine Ténart 
809cb97aa94SPascal van Leeuwen 		if (!n_cdesc)
81019b347b3SPascal van Leeuwen 			first_cdesc = cdesc;
8111b44c5a6SAntoine Ténart 
812cb97aa94SPascal van Leeuwen 		n_cdesc++;
8131b44c5a6SAntoine Ténart 		queued -= len;
8141b44c5a6SAntoine Ténart 		if (!queued)
8151b44c5a6SAntoine Ténart 			break;
8161b44c5a6SAntoine Ténart 	}
817cb97aa94SPascal van Leeuwen skip_cdesc:
81819b347b3SPascal van Leeuwen 	/* Add context control words and token to first command descriptor */
81919b347b3SPascal van Leeuwen 	safexcel_context_control(ctx, base, sreq, first_cdesc);
82019b347b3SPascal van Leeuwen 	if (ctx->aead)
821098e51e5SPascal van Leeuwen 		safexcel_aead_token(ctx, iv, first_cdesc, atoken,
82219b347b3SPascal van Leeuwen 				    sreq->direction, cryptlen,
82319b347b3SPascal van Leeuwen 				    assoclen, digestsize);
82419b347b3SPascal van Leeuwen 	else
825098e51e5SPascal van Leeuwen 		safexcel_skcipher_token(ctx, iv, first_cdesc, atoken,
82619b347b3SPascal van Leeuwen 					cryptlen);
82719b347b3SPascal van Leeuwen 
8281b44c5a6SAntoine Ténart 	/* result descriptors */
82919b347b3SPascal van Leeuwen 	for_each_sg(dst, sg, sreq->nr_dst, i) {
83019b347b3SPascal van Leeuwen 		bool last = (i == sreq->nr_dst - 1);
8311b44c5a6SAntoine Ténart 		u32 len = sg_dma_len(sg);
8321b44c5a6SAntoine Ténart 
83319b347b3SPascal van Leeuwen 		/* only allow the part of the buffer we know we need */
83419b347b3SPascal van Leeuwen 		if (len > totlen_dst)
83519b347b3SPascal van Leeuwen 			len = totlen_dst;
83619b347b3SPascal van Leeuwen 		if (unlikely(!len))
83719b347b3SPascal van Leeuwen 			break;
83819b347b3SPascal van Leeuwen 		totlen_dst -= len;
83919b347b3SPascal van Leeuwen 
84019b347b3SPascal van Leeuwen 		/* skip over AAD space in buffer - not written */
84119b347b3SPascal van Leeuwen 		if (assoclen) {
84219b347b3SPascal van Leeuwen 			if (assoclen >= len) {
84319b347b3SPascal van Leeuwen 				assoclen -= len;
84419b347b3SPascal van Leeuwen 				continue;
84519b347b3SPascal van Leeuwen 			}
8461b44c5a6SAntoine Ténart 			rdesc = safexcel_add_rdesc(priv, ring, first, last,
84719b347b3SPascal van Leeuwen 						   sg_dma_address(sg) +
84819b347b3SPascal van Leeuwen 						   assoclen,
84919b347b3SPascal van Leeuwen 						   len - assoclen);
85019b347b3SPascal van Leeuwen 			assoclen = 0;
85119b347b3SPascal van Leeuwen 		} else {
85219b347b3SPascal van Leeuwen 			rdesc = safexcel_add_rdesc(priv, ring, first, last,
85319b347b3SPascal van Leeuwen 						   sg_dma_address(sg),
85419b347b3SPascal van Leeuwen 						   len);
85519b347b3SPascal van Leeuwen 		}
8561b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
8571b44c5a6SAntoine Ténart 			/* No space left in the result descriptor ring */
8581b44c5a6SAntoine Ténart 			ret = PTR_ERR(rdesc);
8591b44c5a6SAntoine Ténart 			goto rdesc_rollback;
8601b44c5a6SAntoine Ténart 		}
86119b347b3SPascal van Leeuwen 		if (first) {
8629744fec9SOfer Heifetz 			first_rdesc = rdesc;
86319b347b3SPascal van Leeuwen 			first = false;
86419b347b3SPascal van Leeuwen 		}
8651b44c5a6SAntoine Ténart 		n_rdesc++;
8661b44c5a6SAntoine Ténart 	}
8671b44c5a6SAntoine Ténart 
86819b347b3SPascal van Leeuwen 	if (unlikely(first)) {
86919b347b3SPascal van Leeuwen 		/*
87019b347b3SPascal van Leeuwen 		 * Special case: AEAD decrypt with only AAD data.
87119b347b3SPascal van Leeuwen 		 * In this case there is NO output data from the engine,
87219b347b3SPascal van Leeuwen 		 * but the engine still needs a result descriptor!
87319b347b3SPascal van Leeuwen 		 * Create a dummy one just for catching the result token.
87419b347b3SPascal van Leeuwen 		 */
87519b347b3SPascal van Leeuwen 		rdesc = safexcel_add_rdesc(priv, ring, true, true, 0, 0);
87619b347b3SPascal van Leeuwen 		if (IS_ERR(rdesc)) {
87719b347b3SPascal van Leeuwen 			/* No space left in the result descriptor ring */
87819b347b3SPascal van Leeuwen 			ret = PTR_ERR(rdesc);
87919b347b3SPascal van Leeuwen 			goto rdesc_rollback;
88019b347b3SPascal van Leeuwen 		}
88119b347b3SPascal van Leeuwen 		first_rdesc = rdesc;
88219b347b3SPascal van Leeuwen 		n_rdesc = 1;
88319b347b3SPascal van Leeuwen 	}
88419b347b3SPascal van Leeuwen 
8859744fec9SOfer Heifetz 	safexcel_rdr_req_set(priv, ring, first_rdesc, base);
88697858434SAntoine Ténart 
8871b44c5a6SAntoine Ténart 	*commands = n_cdesc;
888152bdf4cSOfer Heifetz 	*results = n_rdesc;
8891b44c5a6SAntoine Ténart 	return 0;
8901b44c5a6SAntoine Ténart 
8911b44c5a6SAntoine Ténart rdesc_rollback:
8921b44c5a6SAntoine Ténart 	for (i = 0; i < n_rdesc; i++)
8931b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].rdr);
8941b44c5a6SAntoine Ténart cdesc_rollback:
8951b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
8961b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
89749186a7dSPeter Harliman Liem unmap:
8988ac1283eSAntoine Tenart 	if (src == dst) {
89949186a7dSPeter Harliman Liem 		if (sreq->nr_src > 0)
90049186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
90149186a7dSPeter Harliman Liem 				     DMA_BIDIRECTIONAL);
9021b44c5a6SAntoine Ténart 	} else {
90349186a7dSPeter Harliman Liem 		if (sreq->nr_src > 0)
90449186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
90549186a7dSPeter Harliman Liem 				     DMA_TO_DEVICE);
90649186a7dSPeter Harliman Liem 		if (sreq->nr_dst > 0)
90749186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, dst, sreq->nr_dst,
90849186a7dSPeter Harliman Liem 				     DMA_FROM_DEVICE);
9091b44c5a6SAntoine Ténart 	}
9101b44c5a6SAntoine Ténart 
9111b44c5a6SAntoine Ténart 	return ret;
9121b44c5a6SAntoine Ténart }
9131b44c5a6SAntoine Ténart 
9141b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
9151b44c5a6SAntoine Ténart 				      int ring,
9168ac1283eSAntoine Tenart 				      struct crypto_async_request *base,
91789332590SAntoine Tenart 				      struct safexcel_cipher_req *sreq,
9181b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
9191b44c5a6SAntoine Ténart {
9208ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
9211b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
9221b44c5a6SAntoine Ténart 	int ndesc = 0, enq_ret;
9231b44c5a6SAntoine Ténart 
9241b44c5a6SAntoine Ténart 	*ret = 0;
9251b44c5a6SAntoine Ténart 
92689332590SAntoine Tenart 	if (unlikely(!sreq->rdescs))
92789332590SAntoine Tenart 		return 0;
92889332590SAntoine Tenart 
92989332590SAntoine Tenart 	while (sreq->rdescs--) {
9301b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
9311b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
9321b44c5a6SAntoine Ténart 			dev_err(priv->dev,
9331b44c5a6SAntoine Ténart 				"cipher: invalidate: could not retrieve the result descriptor\n");
9341b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
9351b44c5a6SAntoine Ténart 			break;
9361b44c5a6SAntoine Ténart 		}
9371b44c5a6SAntoine Ténart 
938cda3e73aSAntoine Tenart 		if (likely(!*ret))
939cda3e73aSAntoine Tenart 			*ret = safexcel_rdesc_check_errors(priv, rdesc);
9401b44c5a6SAntoine Ténart 
9411b44c5a6SAntoine Ténart 		ndesc++;
94289332590SAntoine Tenart 	}
9431b44c5a6SAntoine Ténart 
9441b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
9451b44c5a6SAntoine Ténart 
9461b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
9471b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
9481b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
9491b44c5a6SAntoine Ténart 
9501b44c5a6SAntoine Ténart 		*should_complete = true;
9511b44c5a6SAntoine Ténart 
9521b44c5a6SAntoine Ténart 		return ndesc;
9531b44c5a6SAntoine Ténart 	}
9541b44c5a6SAntoine Ténart 
95586671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
95686671abbSAntoine Ténart 	ctx->base.ring = ring;
9571b44c5a6SAntoine Ténart 
95886671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
9598ac1283eSAntoine Tenart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
96086671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
9611b44c5a6SAntoine Ténart 
9621b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
9631b44c5a6SAntoine Ténart 		*ret = enq_ret;
9641b44c5a6SAntoine Ténart 
9658472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
9668472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
96786671abbSAntoine Ténart 
9681b44c5a6SAntoine Ténart 	*should_complete = false;
9691b44c5a6SAntoine Ténart 
9701b44c5a6SAntoine Ténart 	return ndesc;
9711b44c5a6SAntoine Ténart }
9721b44c5a6SAntoine Ténart 
9738ac1283eSAntoine Tenart static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv,
9748ac1283eSAntoine Tenart 					   int ring,
9751eb7b403SOfer Heifetz 					   struct crypto_async_request *async,
9761eb7b403SOfer Heifetz 					   bool *should_complete, int *ret)
9771eb7b403SOfer Heifetz {
9781eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
9791eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
9801eb7b403SOfer Heifetz 	int err;
9811eb7b403SOfer Heifetz 
9821eb7b403SOfer Heifetz 	if (sreq->needs_inv) {
9831eb7b403SOfer Heifetz 		sreq->needs_inv = false;
98489332590SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async, sreq,
9851eb7b403SOfer Heifetz 						 should_complete, ret);
9861eb7b403SOfer Heifetz 	} else {
9878ac1283eSAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
9888ac1283eSAntoine Tenart 						 req->dst, req->cryptlen, sreq,
9891eb7b403SOfer Heifetz 						 should_complete, ret);
9901eb7b403SOfer Heifetz 	}
9911eb7b403SOfer Heifetz 
9921eb7b403SOfer Heifetz 	return err;
9931eb7b403SOfer Heifetz }
9941eb7b403SOfer Heifetz 
995f6beaea3SAntoine Tenart static int safexcel_aead_handle_result(struct safexcel_crypto_priv *priv,
996f6beaea3SAntoine Tenart 				       int ring,
997f6beaea3SAntoine Tenart 				       struct crypto_async_request *async,
998f6beaea3SAntoine Tenart 				       bool *should_complete, int *ret)
999f6beaea3SAntoine Tenart {
1000f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
1001f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1002f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
1003f6beaea3SAntoine Tenart 	int err;
1004f6beaea3SAntoine Tenart 
1005f6beaea3SAntoine Tenart 	if (sreq->needs_inv) {
1006f6beaea3SAntoine Tenart 		sreq->needs_inv = false;
100789332590SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async, sreq,
1008f6beaea3SAntoine Tenart 						 should_complete, ret);
1009f6beaea3SAntoine Tenart 	} else {
1010f6beaea3SAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
1011f6beaea3SAntoine Tenart 						 req->dst,
1012f6beaea3SAntoine Tenart 						 req->cryptlen + crypto_aead_authsize(tfm),
1013f6beaea3SAntoine Tenart 						 sreq, should_complete, ret);
1014f6beaea3SAntoine Tenart 	}
1015f6beaea3SAntoine Tenart 
1016f6beaea3SAntoine Tenart 	return err;
1017f6beaea3SAntoine Tenart }
1018f6beaea3SAntoine Tenart 
10198ac1283eSAntoine Tenart static int safexcel_cipher_send_inv(struct crypto_async_request *base,
10209744fec9SOfer Heifetz 				    int ring, int *commands, int *results)
10211b44c5a6SAntoine Ténart {
10228ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
102318e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
10241b44c5a6SAntoine Ténart 	int ret;
10251b44c5a6SAntoine Ténart 
10269744fec9SOfer Heifetz 	ret = safexcel_invalidate_cache(base, priv, ctx->base.ctxr_dma, ring);
10271b44c5a6SAntoine Ténart 	if (unlikely(ret))
10281b44c5a6SAntoine Ténart 		return ret;
10291b44c5a6SAntoine Ténart 
10301b44c5a6SAntoine Ténart 	*commands = 1;
10311b44c5a6SAntoine Ténart 	*results = 1;
10321b44c5a6SAntoine Ténart 
10331b44c5a6SAntoine Ténart 	return 0;
10341b44c5a6SAntoine Ténart }
10351b44c5a6SAntoine Ténart 
10368ac1283eSAntoine Tenart static int safexcel_skcipher_send(struct crypto_async_request *async, int ring,
10371eb7b403SOfer Heifetz 				  int *commands, int *results)
10381eb7b403SOfer Heifetz {
10391eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
1040871df319SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
10411eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
104218e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
10431eb7b403SOfer Heifetz 	int ret;
10441eb7b403SOfer Heifetz 
104553c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv);
1046871df319SAntoine Ténart 
10475bdb6e6aSPascal van Leeuwen 	if (sreq->needs_inv) {
10489744fec9SOfer Heifetz 		ret = safexcel_cipher_send_inv(async, ring, commands, results);
10495bdb6e6aSPascal van Leeuwen 	} else {
10505bdb6e6aSPascal van Leeuwen 		struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
10515bdb6e6aSPascal van Leeuwen 		u8 input_iv[AES_BLOCK_SIZE];
10525bdb6e6aSPascal van Leeuwen 
10535bdb6e6aSPascal van Leeuwen 		/*
10545bdb6e6aSPascal van Leeuwen 		 * Save input IV in case of CBC decrypt mode
10555bdb6e6aSPascal van Leeuwen 		 * Will be overwritten with output IV prior to use!
10565bdb6e6aSPascal van Leeuwen 		 */
10575bdb6e6aSPascal van Leeuwen 		memcpy(input_iv, req->iv, crypto_skcipher_ivsize(skcipher));
10585bdb6e6aSPascal van Leeuwen 
10599744fec9SOfer Heifetz 		ret = safexcel_send_req(async, ring, sreq, req->src,
10605bdb6e6aSPascal van Leeuwen 					req->dst, req->cryptlen, 0, 0, input_iv,
1061f6beaea3SAntoine Tenart 					commands, results);
10625bdb6e6aSPascal van Leeuwen 	}
106389332590SAntoine Tenart 
106489332590SAntoine Tenart 	sreq->rdescs = *results;
1065f6beaea3SAntoine Tenart 	return ret;
1066f6beaea3SAntoine Tenart }
1067f6beaea3SAntoine Tenart 
1068f6beaea3SAntoine Tenart static int safexcel_aead_send(struct crypto_async_request *async, int ring,
10699744fec9SOfer Heifetz 			      int *commands, int *results)
1070f6beaea3SAntoine Tenart {
1071f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
1072f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1073f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
1074f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
107518e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
1076f6beaea3SAntoine Tenart 	int ret;
1077f6beaea3SAntoine Tenart 
107853c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv);
1079f6beaea3SAntoine Tenart 
1080f6beaea3SAntoine Tenart 	if (sreq->needs_inv)
10819744fec9SOfer Heifetz 		ret = safexcel_cipher_send_inv(async, ring, commands, results);
1082f6beaea3SAntoine Tenart 	else
10839744fec9SOfer Heifetz 		ret = safexcel_send_req(async, ring, sreq, req->src, req->dst,
10849744fec9SOfer Heifetz 					req->cryptlen, req->assoclen,
1085f6beaea3SAntoine Tenart 					crypto_aead_authsize(tfm), req->iv,
10861eb7b403SOfer Heifetz 					commands, results);
108789332590SAntoine Tenart 	sreq->rdescs = *results;
10881eb7b403SOfer Heifetz 	return ret;
10891eb7b403SOfer Heifetz }
10901eb7b403SOfer Heifetz 
10918ac1283eSAntoine Tenart static int safexcel_cipher_exit_inv(struct crypto_tfm *tfm,
10928ac1283eSAntoine Tenart 				    struct crypto_async_request *base,
10938ac1283eSAntoine Tenart 				    struct safexcel_cipher_req *sreq,
1094*acc3f550SHerbert Xu 				    struct crypto_wait *result)
10951b44c5a6SAntoine Ténart {
10961b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
109718e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
109886671abbSAntoine Ténart 	int ring = ctx->base.ring;
1099*acc3f550SHerbert Xu 	int err;
11001b44c5a6SAntoine Ténart 
11018ac1283eSAntoine Tenart 	ctx = crypto_tfm_ctx(base->tfm);
11021b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
11031eb7b403SOfer Heifetz 	sreq->needs_inv = true;
11041b44c5a6SAntoine Ténart 
110586671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
11068ac1283eSAntoine Tenart 	crypto_enqueue_request(&priv->ring[ring].queue, base);
110786671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
11081b44c5a6SAntoine Ténart 
11098472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
11108472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
11111b44c5a6SAntoine Ténart 
1112*acc3f550SHerbert Xu 	err = crypto_wait_req(-EINPROGRESS, result);
11131b44c5a6SAntoine Ténart 
1114*acc3f550SHerbert Xu 	if (err) {
11151b44c5a6SAntoine Ténart 		dev_warn(priv->dev,
11161b44c5a6SAntoine Ténart 			"cipher: sync: invalidate: completion error %d\n",
1117*acc3f550SHerbert Xu 			 err);
1118*acc3f550SHerbert Xu 		return err;
11191b44c5a6SAntoine Ténart 	}
11201b44c5a6SAntoine Ténart 
11211b44c5a6SAntoine Ténart 	return 0;
11221b44c5a6SAntoine Ténart }
11231b44c5a6SAntoine Ténart 
11248ac1283eSAntoine Tenart static int safexcel_skcipher_exit_inv(struct crypto_tfm *tfm)
11258ac1283eSAntoine Tenart {
11268ac1283eSAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, skcipher, EIP197_SKCIPHER_REQ_SIZE);
11278ac1283eSAntoine Tenart 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
1128*acc3f550SHerbert Xu 	DECLARE_CRYPTO_WAIT(result);
11298ac1283eSAntoine Tenart 
11308ac1283eSAntoine Tenart 	memset(req, 0, sizeof(struct skcipher_request));
11318ac1283eSAntoine Tenart 
11328ac1283eSAntoine Tenart 	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1133*acc3f550SHerbert Xu 				      crypto_req_done, &result);
11348ac1283eSAntoine Tenart 	skcipher_request_set_tfm(req, __crypto_skcipher_cast(tfm));
11358ac1283eSAntoine Tenart 
11368ac1283eSAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
11378ac1283eSAntoine Tenart }
11388ac1283eSAntoine Tenart 
1139f6beaea3SAntoine Tenart static int safexcel_aead_exit_inv(struct crypto_tfm *tfm)
1140f6beaea3SAntoine Tenart {
1141f6beaea3SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, aead, EIP197_AEAD_REQ_SIZE);
1142f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
1143*acc3f550SHerbert Xu 	DECLARE_CRYPTO_WAIT(result);
1144f6beaea3SAntoine Tenart 
1145f6beaea3SAntoine Tenart 	memset(req, 0, sizeof(struct aead_request));
1146f6beaea3SAntoine Tenart 
1147f6beaea3SAntoine Tenart 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1148*acc3f550SHerbert Xu 				  crypto_req_done, &result);
1149f6beaea3SAntoine Tenart 	aead_request_set_tfm(req, __crypto_aead_cast(tfm));
1150f6beaea3SAntoine Tenart 
1151f6beaea3SAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
1152f6beaea3SAntoine Tenart }
1153f6beaea3SAntoine Tenart 
1154a7dea8c0SOfer Heifetz static int safexcel_queue_req(struct crypto_async_request *base,
11558ac1283eSAntoine Tenart 			struct safexcel_cipher_req *sreq,
115693369b5dSPascal van Leeuwen 			enum safexcel_cipher_direction dir)
11571b44c5a6SAntoine Ténart {
11588ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
115918e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
116086671abbSAntoine Ténart 	int ret, ring;
11611b44c5a6SAntoine Ténart 
11621eb7b403SOfer Heifetz 	sreq->needs_inv = false;
1163847ccfc5SOfer Heifetz 	sreq->direction = dir;
11641b44c5a6SAntoine Ténart 
11651b44c5a6SAntoine Ténart 	if (ctx->base.ctxr) {
116653c83e91SAntoine Tenart 		if (priv->flags & EIP197_TRC_CACHE && ctx->base.needs_inv) {
11671eb7b403SOfer Heifetz 			sreq->needs_inv = true;
11681eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
11691eb7b403SOfer Heifetz 		}
11701b44c5a6SAntoine Ténart 	} else {
11711b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
11721b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
11738ac1283eSAntoine Tenart 						 EIP197_GFP_FLAGS(*base),
11741b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
11751b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
11761b44c5a6SAntoine Ténart 			return -ENOMEM;
11771b44c5a6SAntoine Ténart 	}
11781b44c5a6SAntoine Ténart 
117986671abbSAntoine Ténart 	ring = ctx->base.ring;
11801b44c5a6SAntoine Ténart 
118186671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
11828ac1283eSAntoine Tenart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
118386671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
118486671abbSAntoine Ténart 
11858472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
11868472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
11871b44c5a6SAntoine Ténart 
11881b44c5a6SAntoine Ténart 	return ret;
11891b44c5a6SAntoine Ténart }
11901b44c5a6SAntoine Ténart 
119193369b5dSPascal van Leeuwen static int safexcel_encrypt(struct skcipher_request *req)
11921b44c5a6SAntoine Ténart {
1193a7dea8c0SOfer Heifetz 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
119493369b5dSPascal van Leeuwen 			SAFEXCEL_ENCRYPT);
11951b44c5a6SAntoine Ténart }
11961b44c5a6SAntoine Ténart 
119793369b5dSPascal van Leeuwen static int safexcel_decrypt(struct skcipher_request *req)
11981b44c5a6SAntoine Ténart {
1199a7dea8c0SOfer Heifetz 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
120093369b5dSPascal van Leeuwen 			SAFEXCEL_DECRYPT);
12011b44c5a6SAntoine Ténart }
12021b44c5a6SAntoine Ténart 
12031b44c5a6SAntoine Ténart static int safexcel_skcipher_cra_init(struct crypto_tfm *tfm)
12041b44c5a6SAntoine Ténart {
12051b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
12061b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
12071b44c5a6SAntoine Ténart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
12081b44c5a6SAntoine Ténart 			     alg.skcipher.base);
12091b44c5a6SAntoine Ténart 
12101eb7b403SOfer Heifetz 	crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm),
12111eb7b403SOfer Heifetz 				    sizeof(struct safexcel_cipher_req));
12121b44c5a6SAntoine Ténart 
121318e51895SHerbert Xu 	ctx->base.priv = tmpl->priv;
12148ac1283eSAntoine Tenart 
12158ac1283eSAntoine Tenart 	ctx->base.send = safexcel_skcipher_send;
12168ac1283eSAntoine Tenart 	ctx->base.handle_result = safexcel_skcipher_handle_result;
1217098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD;
1218098e51e5SPascal van Leeuwen 	ctx->ctrinit = 1;
12198ac1283eSAntoine Tenart 	return 0;
12208ac1283eSAntoine Tenart }
12218ac1283eSAntoine Tenart 
12228ac1283eSAntoine Tenart static int safexcel_cipher_cra_exit(struct crypto_tfm *tfm)
12238ac1283eSAntoine Tenart {
12248ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
12258ac1283eSAntoine Tenart 
1226ce679559SAntoine Tenart 	memzero_explicit(ctx->key, sizeof(ctx->key));
12278ac1283eSAntoine Tenart 
12288ac1283eSAntoine Tenart 	/* context not allocated, skip invalidation */
12298ac1283eSAntoine Tenart 	if (!ctx->base.ctxr)
12308ac1283eSAntoine Tenart 		return -ENOMEM;
12318ac1283eSAntoine Tenart 
1232ce679559SAntoine Tenart 	memzero_explicit(ctx->base.ctxr->data, sizeof(ctx->base.ctxr->data));
12331b44c5a6SAntoine Ténart 	return 0;
12341b44c5a6SAntoine Ténart }
12351b44c5a6SAntoine Ténart 
12361b44c5a6SAntoine Ténart static void safexcel_skcipher_cra_exit(struct crypto_tfm *tfm)
12371b44c5a6SAntoine Ténart {
12381b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
123918e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
12401b44c5a6SAntoine Ténart 	int ret;
12411b44c5a6SAntoine Ténart 
12428ac1283eSAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
12431b44c5a6SAntoine Ténart 		return;
12441b44c5a6SAntoine Ténart 
124553c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
12468ac1283eSAntoine Tenart 		ret = safexcel_skcipher_exit_inv(tfm);
12471b44c5a6SAntoine Ténart 		if (ret)
12488ac1283eSAntoine Tenart 			dev_warn(priv->dev, "skcipher: invalidation error %d\n",
12498ac1283eSAntoine Tenart 				 ret);
1250871df319SAntoine Ténart 	} else {
1251871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
1252871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
1253871df319SAntoine Ténart 	}
12541b44c5a6SAntoine Ténart }
12551b44c5a6SAntoine Ténart 
1256f6beaea3SAntoine Tenart static void safexcel_aead_cra_exit(struct crypto_tfm *tfm)
1257f6beaea3SAntoine Tenart {
1258f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
125918e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
1260f6beaea3SAntoine Tenart 	int ret;
1261f6beaea3SAntoine Tenart 
1262f6beaea3SAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
1263f6beaea3SAntoine Tenart 		return;
1264f6beaea3SAntoine Tenart 
126553c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
1266f6beaea3SAntoine Tenart 		ret = safexcel_aead_exit_inv(tfm);
1267f6beaea3SAntoine Tenart 		if (ret)
1268f6beaea3SAntoine Tenart 			dev_warn(priv->dev, "aead: invalidation error %d\n",
1269f6beaea3SAntoine Tenart 				 ret);
1270f6beaea3SAntoine Tenart 	} else {
1271f6beaea3SAntoine Tenart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
1272f6beaea3SAntoine Tenart 			      ctx->base.ctxr_dma);
1273f6beaea3SAntoine Tenart 	}
1274f6beaea3SAntoine Tenart }
1275f6beaea3SAntoine Tenart 
127693369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_ecb_cra_init(struct crypto_tfm *tfm)
127793369b5dSPascal van Leeuwen {
127893369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
127993369b5dSPascal van Leeuwen 
128093369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
128193369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
128293369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1283098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1284098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
128593369b5dSPascal van Leeuwen 	return 0;
128693369b5dSPascal van Leeuwen }
128793369b5dSPascal van Leeuwen 
12881b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_ecb_aes = {
12891b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1290062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
12911b44c5a6SAntoine Ténart 	.alg.skcipher = {
12928ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
129393369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
129493369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
12951b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
12961b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
12971b44c5a6SAntoine Ténart 		.base = {
12981b44c5a6SAntoine Ténart 			.cra_name = "ecb(aes)",
12991b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-ecb-aes",
1300aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
13012c95e6d9SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1302b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
13031b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
13041b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
13051b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
13061b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
130793369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ecb_cra_init,
13081b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
13091b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
13101b44c5a6SAntoine Ténart 		},
13111b44c5a6SAntoine Ténart 	},
13121b44c5a6SAntoine Ténart };
13131b44c5a6SAntoine Ténart 
131493369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_cbc_cra_init(struct crypto_tfm *tfm)
13151b44c5a6SAntoine Ténart {
131693369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
13171b44c5a6SAntoine Ténart 
131893369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
131993369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1320098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
132193369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
132293369b5dSPascal van Leeuwen 	return 0;
13231b44c5a6SAntoine Ténart }
13241b44c5a6SAntoine Ténart 
13251b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_cbc_aes = {
13261b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1327062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
13281b44c5a6SAntoine Ténart 	.alg.skcipher = {
13298ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
133093369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
133193369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
13321b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
13331b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
13341b44c5a6SAntoine Ténart 		.ivsize = AES_BLOCK_SIZE,
13351b44c5a6SAntoine Ténart 		.base = {
13361b44c5a6SAntoine Ténart 			.cra_name = "cbc(aes)",
13371b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-cbc-aes",
1338aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
13392c95e6d9SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1340b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
13411b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
13421b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
13431b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
13441b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
134593369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_cbc_cra_init,
13461b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
13471b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
13481b44c5a6SAntoine Ténart 		},
13491b44c5a6SAntoine Ténart 	},
13501b44c5a6SAntoine Ténart };
1351f6beaea3SAntoine Tenart 
135248e97afaSPascal van Leeuwen static int safexcel_skcipher_aes_cfb_cra_init(struct crypto_tfm *tfm)
135348e97afaSPascal van Leeuwen {
135448e97afaSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
135548e97afaSPascal van Leeuwen 
135648e97afaSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
135748e97afaSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1358098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
135948e97afaSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB;
136048e97afaSPascal van Leeuwen 	return 0;
136148e97afaSPascal van Leeuwen }
136248e97afaSPascal van Leeuwen 
136348e97afaSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cfb_aes = {
136448e97afaSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
136548e97afaSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XFB,
136648e97afaSPascal van Leeuwen 	.alg.skcipher = {
136748e97afaSPascal van Leeuwen 		.setkey = safexcel_skcipher_aes_setkey,
136848e97afaSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
136948e97afaSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
137048e97afaSPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE,
137148e97afaSPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE,
137248e97afaSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
137348e97afaSPascal van Leeuwen 		.base = {
137448e97afaSPascal van Leeuwen 			.cra_name = "cfb(aes)",
137548e97afaSPascal van Leeuwen 			.cra_driver_name = "safexcel-cfb-aes",
137648e97afaSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
137748e97afaSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1378b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
137948e97afaSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
138048e97afaSPascal van Leeuwen 			.cra_blocksize = 1,
138148e97afaSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
138248e97afaSPascal van Leeuwen 			.cra_alignmask = 0,
138348e97afaSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_cfb_cra_init,
138448e97afaSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
138548e97afaSPascal van Leeuwen 			.cra_module = THIS_MODULE,
138648e97afaSPascal van Leeuwen 		},
138748e97afaSPascal van Leeuwen 	},
138848e97afaSPascal van Leeuwen };
138948e97afaSPascal van Leeuwen 
139050485dfbSPascal van Leeuwen static int safexcel_skcipher_aes_ofb_cra_init(struct crypto_tfm *tfm)
139150485dfbSPascal van Leeuwen {
139250485dfbSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
139350485dfbSPascal van Leeuwen 
139450485dfbSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
139550485dfbSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1396098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
139750485dfbSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB;
139850485dfbSPascal van Leeuwen 	return 0;
139950485dfbSPascal van Leeuwen }
140050485dfbSPascal van Leeuwen 
140150485dfbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ofb_aes = {
140250485dfbSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
140350485dfbSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XFB,
140450485dfbSPascal van Leeuwen 	.alg.skcipher = {
140550485dfbSPascal van Leeuwen 		.setkey = safexcel_skcipher_aes_setkey,
140650485dfbSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
140750485dfbSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
140850485dfbSPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE,
140950485dfbSPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE,
141050485dfbSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
141150485dfbSPascal van Leeuwen 		.base = {
141250485dfbSPascal van Leeuwen 			.cra_name = "ofb(aes)",
141350485dfbSPascal van Leeuwen 			.cra_driver_name = "safexcel-ofb-aes",
141450485dfbSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
141550485dfbSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1416b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
141750485dfbSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
141850485dfbSPascal van Leeuwen 			.cra_blocksize = 1,
141950485dfbSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
142050485dfbSPascal van Leeuwen 			.cra_alignmask = 0,
142150485dfbSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ofb_cra_init,
142250485dfbSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
142350485dfbSPascal van Leeuwen 			.cra_module = THIS_MODULE,
142450485dfbSPascal van Leeuwen 		},
142550485dfbSPascal van Leeuwen 	},
142650485dfbSPascal van Leeuwen };
142750485dfbSPascal van Leeuwen 
142854f9e8faSPascal van Leeuwen static int safexcel_skcipher_aesctr_setkey(struct crypto_skcipher *ctfm,
142954f9e8faSPascal van Leeuwen 					   const u8 *key, unsigned int len)
143054f9e8faSPascal van Leeuwen {
143154f9e8faSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
143254f9e8faSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
143318e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
143454f9e8faSPascal van Leeuwen 	struct crypto_aes_ctx aes;
143554f9e8faSPascal van Leeuwen 	int ret, i;
143654f9e8faSPascal van Leeuwen 	unsigned int keylen;
143754f9e8faSPascal van Leeuwen 
143854f9e8faSPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
1439f26882a3SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
144054f9e8faSPascal van Leeuwen 	/* exclude the nonce here */
1441f26882a3SPascal van Leeuwen 	keylen = len - CTR_RFC3686_NONCE_SIZE;
144254f9e8faSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, keylen);
1443674f368aSEric Biggers 	if (ret)
144454f9e8faSPascal van Leeuwen 		return ret;
144554f9e8faSPascal van Leeuwen 
144654f9e8faSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
144754f9e8faSPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
144813a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
144954f9e8faSPascal van Leeuwen 				ctx->base.needs_inv = true;
145054f9e8faSPascal van Leeuwen 				break;
145154f9e8faSPascal van Leeuwen 			}
145254f9e8faSPascal van Leeuwen 		}
145354f9e8faSPascal van Leeuwen 	}
145454f9e8faSPascal van Leeuwen 
145554f9e8faSPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
145654f9e8faSPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
145754f9e8faSPascal van Leeuwen 
145854f9e8faSPascal van Leeuwen 	ctx->key_len = keylen;
145954f9e8faSPascal van Leeuwen 
146054f9e8faSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
146154f9e8faSPascal van Leeuwen 	return 0;
146254f9e8faSPascal van Leeuwen }
146354f9e8faSPascal van Leeuwen 
146493369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_ctr_cra_init(struct crypto_tfm *tfm)
146593369b5dSPascal van Leeuwen {
146693369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
146793369b5dSPascal van Leeuwen 
146893369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
146993369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1470098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
147193369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
147293369b5dSPascal van Leeuwen 	return 0;
147393369b5dSPascal van Leeuwen }
147493369b5dSPascal van Leeuwen 
147554f9e8faSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ctr_aes = {
147654f9e8faSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1477062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
147854f9e8faSPascal van Leeuwen 	.alg.skcipher = {
147954f9e8faSPascal van Leeuwen 		.setkey = safexcel_skcipher_aesctr_setkey,
148093369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
148193369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1482f26882a3SPascal van Leeuwen 		/* Add nonce size */
1483f26882a3SPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
1484f26882a3SPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
1485f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
148654f9e8faSPascal van Leeuwen 		.base = {
148754f9e8faSPascal van Leeuwen 			.cra_name = "rfc3686(ctr(aes))",
148854f9e8faSPascal van Leeuwen 			.cra_driver_name = "safexcel-ctr-aes",
1489aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
149054f9e8faSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1491b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
149254f9e8faSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
149354f9e8faSPascal van Leeuwen 			.cra_blocksize = 1,
149454f9e8faSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
149554f9e8faSPascal van Leeuwen 			.cra_alignmask = 0,
149693369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ctr_cra_init,
149754f9e8faSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
149854f9e8faSPascal van Leeuwen 			.cra_module = THIS_MODULE,
149954f9e8faSPascal van Leeuwen 		},
150054f9e8faSPascal van Leeuwen 	},
150154f9e8faSPascal van Leeuwen };
150254f9e8faSPascal van Leeuwen 
1503a7dea8c0SOfer Heifetz static int safexcel_des_setkey(struct crypto_skcipher *ctfm, const u8 *key,
1504a7dea8c0SOfer Heifetz 			       unsigned int len)
1505a7dea8c0SOfer Heifetz {
150621f5a15eSArd Biesheuvel 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
150718e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
1508a7dea8c0SOfer Heifetz 	int ret;
1509a7dea8c0SOfer Heifetz 
151021f5a15eSArd Biesheuvel 	ret = verify_skcipher_des_key(ctfm, key);
151121f5a15eSArd Biesheuvel 	if (ret)
151221f5a15eSArd Biesheuvel 		return ret;
1513a7dea8c0SOfer Heifetz 
1514a7dea8c0SOfer Heifetz 	/* if context exits and key changed, need to invalidate it */
1515177e358cSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
1516a7dea8c0SOfer Heifetz 		if (memcmp(ctx->key, key, len))
1517a7dea8c0SOfer Heifetz 			ctx->base.needs_inv = true;
1518a7dea8c0SOfer Heifetz 
1519a7dea8c0SOfer Heifetz 	memcpy(ctx->key, key, len);
1520a7dea8c0SOfer Heifetz 	ctx->key_len = len;
1521a7dea8c0SOfer Heifetz 
1522a7dea8c0SOfer Heifetz 	return 0;
1523a7dea8c0SOfer Heifetz }
1524a7dea8c0SOfer Heifetz 
152593369b5dSPascal van Leeuwen static int safexcel_skcipher_des_cbc_cra_init(struct crypto_tfm *tfm)
152693369b5dSPascal van Leeuwen {
152793369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
152893369b5dSPascal van Leeuwen 
152993369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
153093369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_DES;
1531098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
1532098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
153393369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
153493369b5dSPascal van Leeuwen 	return 0;
153593369b5dSPascal van Leeuwen }
153693369b5dSPascal van Leeuwen 
1537a7dea8c0SOfer Heifetz struct safexcel_alg_template safexcel_alg_cbc_des = {
1538a7dea8c0SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1539062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
1540a7dea8c0SOfer Heifetz 	.alg.skcipher = {
1541a7dea8c0SOfer Heifetz 		.setkey = safexcel_des_setkey,
154293369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
154393369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1544a7dea8c0SOfer Heifetz 		.min_keysize = DES_KEY_SIZE,
1545a7dea8c0SOfer Heifetz 		.max_keysize = DES_KEY_SIZE,
1546a7dea8c0SOfer Heifetz 		.ivsize = DES_BLOCK_SIZE,
1547a7dea8c0SOfer Heifetz 		.base = {
1548a7dea8c0SOfer Heifetz 			.cra_name = "cbc(des)",
1549a7dea8c0SOfer Heifetz 			.cra_driver_name = "safexcel-cbc-des",
1550aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
15512b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1552b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1553a7dea8c0SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1554a7dea8c0SOfer Heifetz 			.cra_blocksize = DES_BLOCK_SIZE,
1555a7dea8c0SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1556a7dea8c0SOfer Heifetz 			.cra_alignmask = 0,
155793369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des_cbc_cra_init,
1558a7dea8c0SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
1559a7dea8c0SOfer Heifetz 			.cra_module = THIS_MODULE,
1560a7dea8c0SOfer Heifetz 		},
1561a7dea8c0SOfer Heifetz 	},
1562a7dea8c0SOfer Heifetz };
1563a7dea8c0SOfer Heifetz 
156493369b5dSPascal van Leeuwen static int safexcel_skcipher_des_ecb_cra_init(struct crypto_tfm *tfm)
1565a7dea8c0SOfer Heifetz {
156693369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1567a7dea8c0SOfer Heifetz 
156893369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
156993369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_DES;
157093369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1571098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1572098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
157393369b5dSPascal van Leeuwen 	return 0;
1574a7dea8c0SOfer Heifetz }
1575a7dea8c0SOfer Heifetz 
1576a7dea8c0SOfer Heifetz struct safexcel_alg_template safexcel_alg_ecb_des = {
1577a7dea8c0SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1578062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
1579a7dea8c0SOfer Heifetz 	.alg.skcipher = {
1580a7dea8c0SOfer Heifetz 		.setkey = safexcel_des_setkey,
158193369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
158293369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1583a7dea8c0SOfer Heifetz 		.min_keysize = DES_KEY_SIZE,
1584a7dea8c0SOfer Heifetz 		.max_keysize = DES_KEY_SIZE,
1585a7dea8c0SOfer Heifetz 		.base = {
1586a7dea8c0SOfer Heifetz 			.cra_name = "ecb(des)",
1587a7dea8c0SOfer Heifetz 			.cra_driver_name = "safexcel-ecb-des",
1588aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
15892b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1590b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1591a7dea8c0SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1592a7dea8c0SOfer Heifetz 			.cra_blocksize = DES_BLOCK_SIZE,
1593a7dea8c0SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1594a7dea8c0SOfer Heifetz 			.cra_alignmask = 0,
159593369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des_ecb_cra_init,
1596a7dea8c0SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
1597a7dea8c0SOfer Heifetz 			.cra_module = THIS_MODULE,
1598a7dea8c0SOfer Heifetz 		},
1599a7dea8c0SOfer Heifetz 	},
1600a7dea8c0SOfer Heifetz };
160162469879SOfer Heifetz 
160262469879SOfer Heifetz static int safexcel_des3_ede_setkey(struct crypto_skcipher *ctfm,
160362469879SOfer Heifetz 				   const u8 *key, unsigned int len)
160462469879SOfer Heifetz {
160567ac62bfSHerbert Xu 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
160618e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
160767ac62bfSHerbert Xu 	int err;
160862469879SOfer Heifetz 
160921f5a15eSArd Biesheuvel 	err = verify_skcipher_des3_key(ctfm, key);
161021f5a15eSArd Biesheuvel 	if (err)
161167ac62bfSHerbert Xu 		return err;
161262469879SOfer Heifetz 
161362469879SOfer Heifetz 	/* if context exits and key changed, need to invalidate it */
1614177e358cSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
161562469879SOfer Heifetz 		if (memcmp(ctx->key, key, len))
161662469879SOfer Heifetz 			ctx->base.needs_inv = true;
161762469879SOfer Heifetz 
161862469879SOfer Heifetz 	memcpy(ctx->key, key, len);
161962469879SOfer Heifetz 	ctx->key_len = len;
162062469879SOfer Heifetz 
162162469879SOfer Heifetz 	return 0;
162262469879SOfer Heifetz }
162362469879SOfer Heifetz 
162493369b5dSPascal van Leeuwen static int safexcel_skcipher_des3_cbc_cra_init(struct crypto_tfm *tfm)
162593369b5dSPascal van Leeuwen {
162693369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
162793369b5dSPascal van Leeuwen 
162893369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
162993369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_3DES;
1630098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1631098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
163293369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
163393369b5dSPascal van Leeuwen 	return 0;
163493369b5dSPascal van Leeuwen }
163593369b5dSPascal van Leeuwen 
163662469879SOfer Heifetz struct safexcel_alg_template safexcel_alg_cbc_des3_ede = {
163762469879SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1638062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
163962469879SOfer Heifetz 	.alg.skcipher = {
164062469879SOfer Heifetz 		.setkey = safexcel_des3_ede_setkey,
164193369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
164293369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
164362469879SOfer Heifetz 		.min_keysize = DES3_EDE_KEY_SIZE,
164462469879SOfer Heifetz 		.max_keysize = DES3_EDE_KEY_SIZE,
164562469879SOfer Heifetz 		.ivsize = DES3_EDE_BLOCK_SIZE,
164662469879SOfer Heifetz 		.base = {
164762469879SOfer Heifetz 			.cra_name = "cbc(des3_ede)",
164862469879SOfer Heifetz 			.cra_driver_name = "safexcel-cbc-des3_ede",
1649aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
16502b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1651b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
165262469879SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
165362469879SOfer Heifetz 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
165462469879SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
165562469879SOfer Heifetz 			.cra_alignmask = 0,
165693369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des3_cbc_cra_init,
165762469879SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
165862469879SOfer Heifetz 			.cra_module = THIS_MODULE,
165962469879SOfer Heifetz 		},
166062469879SOfer Heifetz 	},
166162469879SOfer Heifetz };
166262469879SOfer Heifetz 
166393369b5dSPascal van Leeuwen static int safexcel_skcipher_des3_ecb_cra_init(struct crypto_tfm *tfm)
166462469879SOfer Heifetz {
166593369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
166662469879SOfer Heifetz 
166793369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
166893369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_3DES;
166993369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1670098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1671098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
167293369b5dSPascal van Leeuwen 	return 0;
167362469879SOfer Heifetz }
167462469879SOfer Heifetz 
167562469879SOfer Heifetz struct safexcel_alg_template safexcel_alg_ecb_des3_ede = {
167662469879SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1677062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
167862469879SOfer Heifetz 	.alg.skcipher = {
167962469879SOfer Heifetz 		.setkey = safexcel_des3_ede_setkey,
168093369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
168193369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
168262469879SOfer Heifetz 		.min_keysize = DES3_EDE_KEY_SIZE,
168362469879SOfer Heifetz 		.max_keysize = DES3_EDE_KEY_SIZE,
168462469879SOfer Heifetz 		.base = {
168562469879SOfer Heifetz 			.cra_name = "ecb(des3_ede)",
168662469879SOfer Heifetz 			.cra_driver_name = "safexcel-ecb-des3_ede",
1687aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
16882b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1689b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
169062469879SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
169162469879SOfer Heifetz 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
169262469879SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
169362469879SOfer Heifetz 			.cra_alignmask = 0,
169493369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des3_ecb_cra_init,
169562469879SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
169662469879SOfer Heifetz 			.cra_module = THIS_MODULE,
169762469879SOfer Heifetz 		},
169862469879SOfer Heifetz 	},
169962469879SOfer Heifetz };
170062469879SOfer Heifetz 
170193369b5dSPascal van Leeuwen static int safexcel_aead_encrypt(struct aead_request *req)
1702f6beaea3SAntoine Tenart {
1703f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
1704f6beaea3SAntoine Tenart 
170593369b5dSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
1706f6beaea3SAntoine Tenart }
1707f6beaea3SAntoine Tenart 
170893369b5dSPascal van Leeuwen static int safexcel_aead_decrypt(struct aead_request *req)
1709f6beaea3SAntoine Tenart {
1710f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
1711f6beaea3SAntoine Tenart 
171293369b5dSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
1713f6beaea3SAntoine Tenart }
1714f6beaea3SAntoine Tenart 
1715f6beaea3SAntoine Tenart static int safexcel_aead_cra_init(struct crypto_tfm *tfm)
1716f6beaea3SAntoine Tenart {
1717f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1718f6beaea3SAntoine Tenart 	struct safexcel_alg_template *tmpl =
1719f6beaea3SAntoine Tenart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
1720f6beaea3SAntoine Tenart 			     alg.aead.base);
1721f6beaea3SAntoine Tenart 
1722f6beaea3SAntoine Tenart 	crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
1723f6beaea3SAntoine Tenart 				sizeof(struct safexcel_cipher_req));
1724f6beaea3SAntoine Tenart 
172518e51895SHerbert Xu 	ctx->base.priv = tmpl->priv;
1726f6beaea3SAntoine Tenart 
17270e17e362SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES; /* default */
1728098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
1729098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD;
1730098e51e5SPascal van Leeuwen 	ctx->ctrinit = 1;
173193369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; /* default */
1732f6beaea3SAntoine Tenart 	ctx->aead = true;
1733f6beaea3SAntoine Tenart 	ctx->base.send = safexcel_aead_send;
1734f6beaea3SAntoine Tenart 	ctx->base.handle_result = safexcel_aead_handle_result;
1735f6beaea3SAntoine Tenart 	return 0;
1736f6beaea3SAntoine Tenart }
1737f6beaea3SAntoine Tenart 
173801ba061dSAntoine Tenart static int safexcel_aead_sha1_cra_init(struct crypto_tfm *tfm)
173901ba061dSAntoine Tenart {
174001ba061dSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
174101ba061dSAntoine Tenart 
174201ba061dSAntoine Tenart 	safexcel_aead_cra_init(tfm);
1743a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
174401ba061dSAntoine Tenart 	ctx->state_sz = SHA1_DIGEST_SIZE;
174501ba061dSAntoine Tenart 	return 0;
174601ba061dSAntoine Tenart }
174701ba061dSAntoine Tenart 
174801ba061dSAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_aes = {
174901ba061dSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1750062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA1,
175101ba061dSAntoine Tenart 	.alg.aead = {
175277cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
175393369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
175493369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
175501ba061dSAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
175601ba061dSAntoine Tenart 		.maxauthsize = SHA1_DIGEST_SIZE,
175701ba061dSAntoine Tenart 		.base = {
175801ba061dSAntoine Tenart 			.cra_name = "authenc(hmac(sha1),cbc(aes))",
175901ba061dSAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-aes",
1760aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
17613f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1762b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
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 |
1798b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1799f6beaea3SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1800f6beaea3SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1801f6beaea3SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1802f6beaea3SAntoine Tenart 			.cra_alignmask = 0,
1803f6beaea3SAntoine Tenart 			.cra_init = safexcel_aead_sha256_cra_init,
1804f6beaea3SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1805f6beaea3SAntoine Tenart 			.cra_module = THIS_MODULE,
1806f6beaea3SAntoine Tenart 		},
1807f6beaea3SAntoine Tenart 	},
1808f6beaea3SAntoine Tenart };
1809678b2878SAntoine Tenart 
1810678b2878SAntoine Tenart static int safexcel_aead_sha224_cra_init(struct crypto_tfm *tfm)
1811678b2878SAntoine Tenart {
1812678b2878SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1813678b2878SAntoine Tenart 
1814678b2878SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1815a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1816678b2878SAntoine Tenart 	ctx->state_sz = SHA256_DIGEST_SIZE;
1817678b2878SAntoine Tenart 	return 0;
1818678b2878SAntoine Tenart }
1819678b2878SAntoine Tenart 
1820678b2878SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_aes = {
1821678b2878SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1822062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
1823678b2878SAntoine Tenart 	.alg.aead = {
182477cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
182593369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
182693369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1827678b2878SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1828678b2878SAntoine Tenart 		.maxauthsize = SHA224_DIGEST_SIZE,
1829678b2878SAntoine Tenart 		.base = {
1830678b2878SAntoine Tenart 			.cra_name = "authenc(hmac(sha224),cbc(aes))",
1831678b2878SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-aes",
1832aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18333f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1834b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1835678b2878SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1836678b2878SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1837678b2878SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1838678b2878SAntoine Tenart 			.cra_alignmask = 0,
1839678b2878SAntoine Tenart 			.cra_init = safexcel_aead_sha224_cra_init,
1840678b2878SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1841678b2878SAntoine Tenart 			.cra_module = THIS_MODULE,
1842678b2878SAntoine Tenart 		},
1843678b2878SAntoine Tenart 	},
1844678b2878SAntoine Tenart };
184587eee125SAntoine Tenart 
184687eee125SAntoine Tenart static int safexcel_aead_sha512_cra_init(struct crypto_tfm *tfm)
184787eee125SAntoine Tenart {
184887eee125SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
184987eee125SAntoine Tenart 
185087eee125SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1851a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
185287eee125SAntoine Tenart 	ctx->state_sz = SHA512_DIGEST_SIZE;
185387eee125SAntoine Tenart 	return 0;
185487eee125SAntoine Tenart }
185587eee125SAntoine Tenart 
185687eee125SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_aes = {
185787eee125SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1858062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
185987eee125SAntoine Tenart 	.alg.aead = {
186077cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
186193369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
186293369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
186387eee125SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
186487eee125SAntoine Tenart 		.maxauthsize = SHA512_DIGEST_SIZE,
186587eee125SAntoine Tenart 		.base = {
186687eee125SAntoine Tenart 			.cra_name = "authenc(hmac(sha512),cbc(aes))",
186787eee125SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-aes",
1868aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18693f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1870b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
187187eee125SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
187287eee125SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
187387eee125SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
187487eee125SAntoine Tenart 			.cra_alignmask = 0,
187587eee125SAntoine Tenart 			.cra_init = safexcel_aead_sha512_cra_init,
187687eee125SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
187787eee125SAntoine Tenart 			.cra_module = THIS_MODULE,
187887eee125SAntoine Tenart 		},
187987eee125SAntoine Tenart 	},
188087eee125SAntoine Tenart };
1881ea23cb53SAntoine Tenart 
1882ea23cb53SAntoine Tenart static int safexcel_aead_sha384_cra_init(struct crypto_tfm *tfm)
1883ea23cb53SAntoine Tenart {
1884ea23cb53SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1885ea23cb53SAntoine Tenart 
1886ea23cb53SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1887a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
1888ea23cb53SAntoine Tenart 	ctx->state_sz = SHA512_DIGEST_SIZE;
1889ea23cb53SAntoine Tenart 	return 0;
1890ea23cb53SAntoine Tenart }
1891ea23cb53SAntoine Tenart 
1892ea23cb53SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_aes = {
1893ea23cb53SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1894062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
1895ea23cb53SAntoine Tenart 	.alg.aead = {
189677cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
189793369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
189893369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1899ea23cb53SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1900ea23cb53SAntoine Tenart 		.maxauthsize = SHA384_DIGEST_SIZE,
1901ea23cb53SAntoine Tenart 		.base = {
1902ea23cb53SAntoine Tenart 			.cra_name = "authenc(hmac(sha384),cbc(aes))",
1903ea23cb53SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-aes",
1904aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
19053f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1906b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1907ea23cb53SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1908ea23cb53SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1909ea23cb53SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1910ea23cb53SAntoine Tenart 			.cra_alignmask = 0,
1911ea23cb53SAntoine Tenart 			.cra_init = safexcel_aead_sha384_cra_init,
1912ea23cb53SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1913ea23cb53SAntoine Tenart 			.cra_module = THIS_MODULE,
1914ea23cb53SAntoine Tenart 		},
1915ea23cb53SAntoine Tenart 	},
1916ea23cb53SAntoine Tenart };
191777cdd4efSPascal van Leeuwen 
19180e17e362SPascal van Leeuwen static int safexcel_aead_sha1_des3_cra_init(struct crypto_tfm *tfm)
19190e17e362SPascal van Leeuwen {
19200e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
19210e17e362SPascal van Leeuwen 
19220e17e362SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
19230e17e362SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1924098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1925098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
19260e17e362SPascal van Leeuwen 	return 0;
19270e17e362SPascal van Leeuwen }
19280e17e362SPascal van Leeuwen 
192977cdd4efSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des3_ede = {
193077cdd4efSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1931062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1,
193277cdd4efSPascal van Leeuwen 	.alg.aead = {
193377cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
193493369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
193593369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
193677cdd4efSPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
193777cdd4efSPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
193877cdd4efSPascal van Leeuwen 		.base = {
193977cdd4efSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
194077cdd4efSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des3_ede",
1941aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
194277cdd4efSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1943b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
194477cdd4efSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
194577cdd4efSPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
194677cdd4efSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
194777cdd4efSPascal van Leeuwen 			.cra_alignmask = 0,
19480e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_des3_cra_init,
19490e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
19500e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
19510e17e362SPascal van Leeuwen 		},
19520e17e362SPascal van Leeuwen 	},
19530e17e362SPascal van Leeuwen };
19540e17e362SPascal van Leeuwen 
1955f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha256_des3_cra_init(struct crypto_tfm *tfm)
1956f0a8bdf0SPascal van Leeuwen {
1957f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1958f0a8bdf0SPascal van Leeuwen 
1959f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
1960f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1961098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1962098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
1963f0a8bdf0SPascal van Leeuwen 	return 0;
1964f0a8bdf0SPascal van Leeuwen }
1965f0a8bdf0SPascal van Leeuwen 
1966f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des3_ede = {
1967f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1968f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
1969f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
1970f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
1971f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
1972f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1973f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
1974f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
1975f0a8bdf0SPascal van Leeuwen 		.base = {
1976f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
1977f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des3_ede",
1978f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
1979f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1980b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1981f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1982f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1983f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1984f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
1985f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_des3_cra_init,
1986f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
1987f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
1988f0a8bdf0SPascal van Leeuwen 		},
1989f0a8bdf0SPascal van Leeuwen 	},
1990f0a8bdf0SPascal van Leeuwen };
1991f0a8bdf0SPascal van Leeuwen 
1992f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha224_des3_cra_init(struct crypto_tfm *tfm)
1993f0a8bdf0SPascal van Leeuwen {
1994f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1995f0a8bdf0SPascal van Leeuwen 
1996f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
1997f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1998098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1999098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2000f0a8bdf0SPascal van Leeuwen 	return 0;
2001f0a8bdf0SPascal van Leeuwen }
2002f0a8bdf0SPascal van Leeuwen 
2003f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des3_ede = {
2004f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2005f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2006f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2007f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2008f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2009f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2010f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2011f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
2012f0a8bdf0SPascal van Leeuwen 		.base = {
2013f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),cbc(des3_ede))",
2014f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des3_ede",
2015f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2016f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2017b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2018f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2019f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2020f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2021f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2022f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_des3_cra_init,
2023f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2024f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2025f0a8bdf0SPascal van Leeuwen 		},
2026f0a8bdf0SPascal van Leeuwen 	},
2027f0a8bdf0SPascal van Leeuwen };
2028f0a8bdf0SPascal van Leeuwen 
2029f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha512_des3_cra_init(struct crypto_tfm *tfm)
2030f0a8bdf0SPascal van Leeuwen {
2031f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2032f0a8bdf0SPascal van Leeuwen 
2033f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
2034f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
2035098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
2036098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2037f0a8bdf0SPascal van Leeuwen 	return 0;
2038f0a8bdf0SPascal van Leeuwen }
2039f0a8bdf0SPascal van Leeuwen 
2040f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des3_ede = {
2041f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2042f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2043f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2044f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2045f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2046f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2047f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2048f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
2049f0a8bdf0SPascal van Leeuwen 		.base = {
2050f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),cbc(des3_ede))",
2051f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des3_ede",
2052f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2053f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2054b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2055f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2056f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2057f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2058f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2059f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_des3_cra_init,
2060f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2061f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2062f0a8bdf0SPascal van Leeuwen 		},
2063f0a8bdf0SPascal van Leeuwen 	},
2064f0a8bdf0SPascal van Leeuwen };
2065f0a8bdf0SPascal van Leeuwen 
2066f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha384_des3_cra_init(struct crypto_tfm *tfm)
2067f0a8bdf0SPascal van Leeuwen {
2068f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2069f0a8bdf0SPascal van Leeuwen 
2070f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
2071f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
2072098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
2073098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2074f0a8bdf0SPascal van Leeuwen 	return 0;
2075f0a8bdf0SPascal van Leeuwen }
2076f0a8bdf0SPascal van Leeuwen 
2077f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des3_ede = {
2078f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2079f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2080f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2081f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2082f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2083f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2084f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2085f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
2086f0a8bdf0SPascal van Leeuwen 		.base = {
2087f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),cbc(des3_ede))",
2088f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des3_ede",
2089f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2090f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2091b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2092f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2093f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2094f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2095f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2096f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_des3_cra_init,
2097f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2098f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2099f0a8bdf0SPascal van Leeuwen 		},
2100f0a8bdf0SPascal van Leeuwen 	},
2101f0a8bdf0SPascal van Leeuwen };
2102f0a8bdf0SPascal van Leeuwen 
2103bb7679b8SPascal van Leeuwen static int safexcel_aead_sha1_des_cra_init(struct crypto_tfm *tfm)
2104bb7679b8SPascal van Leeuwen {
2105bb7679b8SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2106bb7679b8SPascal van Leeuwen 
2107bb7679b8SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
2108bb7679b8SPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2109098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2110098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2111bb7679b8SPascal van Leeuwen 	return 0;
2112bb7679b8SPascal van Leeuwen }
2113bb7679b8SPascal van Leeuwen 
2114bb7679b8SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des = {
2115bb7679b8SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2116bb7679b8SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1,
2117bb7679b8SPascal van Leeuwen 	.alg.aead = {
2118bb7679b8SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2119bb7679b8SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2120bb7679b8SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2121bb7679b8SPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2122bb7679b8SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
2123bb7679b8SPascal van Leeuwen 		.base = {
2124bb7679b8SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(des))",
2125bb7679b8SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des",
2126bb7679b8SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2127bb7679b8SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2128b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2129bb7679b8SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2130bb7679b8SPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2131bb7679b8SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2132bb7679b8SPascal van Leeuwen 			.cra_alignmask = 0,
2133bb7679b8SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_des_cra_init,
2134bb7679b8SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2135bb7679b8SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2136bb7679b8SPascal van Leeuwen 		},
2137bb7679b8SPascal van Leeuwen 	},
2138bb7679b8SPascal van Leeuwen };
2139bb7679b8SPascal van Leeuwen 
2140457a6fdfSPascal van Leeuwen static int safexcel_aead_sha256_des_cra_init(struct crypto_tfm *tfm)
2141457a6fdfSPascal van Leeuwen {
2142457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2143457a6fdfSPascal van Leeuwen 
2144457a6fdfSPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
2145457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2146098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2147098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2148457a6fdfSPascal van Leeuwen 	return 0;
2149457a6fdfSPascal van Leeuwen }
2150457a6fdfSPascal van Leeuwen 
2151457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des = {
2152457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2153457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2154457a6fdfSPascal van Leeuwen 	.alg.aead = {
2155457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2156457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2157457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2158457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2159457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
2160457a6fdfSPascal van Leeuwen 		.base = {
2161457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),cbc(des))",
2162457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des",
2163457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2164457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2165b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2166457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2167457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2168457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2169457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2170457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_des_cra_init,
2171457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2172457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2173457a6fdfSPascal van Leeuwen 		},
2174457a6fdfSPascal van Leeuwen 	},
2175457a6fdfSPascal van Leeuwen };
2176457a6fdfSPascal van Leeuwen 
2177457a6fdfSPascal van Leeuwen static int safexcel_aead_sha224_des_cra_init(struct crypto_tfm *tfm)
2178457a6fdfSPascal van Leeuwen {
2179457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2180457a6fdfSPascal van Leeuwen 
2181457a6fdfSPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
2182457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2183098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2184098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2185457a6fdfSPascal van Leeuwen 	return 0;
2186457a6fdfSPascal van Leeuwen }
2187457a6fdfSPascal van Leeuwen 
2188457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des = {
2189457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2190457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2191457a6fdfSPascal van Leeuwen 	.alg.aead = {
2192457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2193457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2194457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2195457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2196457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
2197457a6fdfSPascal van Leeuwen 		.base = {
2198457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),cbc(des))",
2199457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des",
2200457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2201457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2202b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2203457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2204457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2205457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2206457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2207457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_des_cra_init,
2208457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2209457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2210457a6fdfSPascal van Leeuwen 		},
2211457a6fdfSPascal van Leeuwen 	},
2212457a6fdfSPascal van Leeuwen };
2213457a6fdfSPascal van Leeuwen 
2214457a6fdfSPascal van Leeuwen static int safexcel_aead_sha512_des_cra_init(struct crypto_tfm *tfm)
2215457a6fdfSPascal van Leeuwen {
2216457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2217457a6fdfSPascal van Leeuwen 
2218457a6fdfSPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
2219457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2220098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2221098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2222457a6fdfSPascal van Leeuwen 	return 0;
2223457a6fdfSPascal van Leeuwen }
2224457a6fdfSPascal van Leeuwen 
2225457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des = {
2226457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2227457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2228457a6fdfSPascal van Leeuwen 	.alg.aead = {
2229457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2230457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2231457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2232457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2233457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
2234457a6fdfSPascal van Leeuwen 		.base = {
2235457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),cbc(des))",
2236457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des",
2237457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2238457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2239b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2240457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2241457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2242457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2243457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2244457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_des_cra_init,
2245457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2246457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2247457a6fdfSPascal van Leeuwen 		},
2248457a6fdfSPascal van Leeuwen 	},
2249457a6fdfSPascal van Leeuwen };
2250457a6fdfSPascal van Leeuwen 
2251457a6fdfSPascal van Leeuwen static int safexcel_aead_sha384_des_cra_init(struct crypto_tfm *tfm)
2252457a6fdfSPascal van Leeuwen {
2253457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2254457a6fdfSPascal van Leeuwen 
2255457a6fdfSPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
2256457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2257098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2258098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2259457a6fdfSPascal van Leeuwen 	return 0;
2260457a6fdfSPascal van Leeuwen }
2261457a6fdfSPascal van Leeuwen 
2262457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des = {
2263457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2264457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2265457a6fdfSPascal van Leeuwen 	.alg.aead = {
2266457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2267457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2268457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2269457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2270457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
2271457a6fdfSPascal van Leeuwen 		.base = {
2272457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),cbc(des))",
2273457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des",
2274457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2275457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2276b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2277457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2278457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2279457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2280457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2281457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_des_cra_init,
2282457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2283457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2284457a6fdfSPascal van Leeuwen 		},
2285457a6fdfSPascal van Leeuwen 	},
2286457a6fdfSPascal van Leeuwen };
2287457a6fdfSPascal van Leeuwen 
22880e17e362SPascal van Leeuwen static int safexcel_aead_sha1_ctr_cra_init(struct crypto_tfm *tfm)
22890e17e362SPascal van Leeuwen {
22900e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
22910e17e362SPascal van Leeuwen 
22920e17e362SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
22930e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
22940e17e362SPascal van Leeuwen 	return 0;
22950e17e362SPascal van Leeuwen }
22960e17e362SPascal van Leeuwen 
22970e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_aes = {
22980e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2299062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA1,
23000e17e362SPascal van Leeuwen 	.alg.aead = {
23010e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
230293369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
230393369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2304f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23050e17e362SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
23060e17e362SPascal van Leeuwen 		.base = {
23070e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
23080e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-aes",
2309aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23100e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2311b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
23120e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23130e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23140e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23150e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23160e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_ctr_cra_init,
23170e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23180e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23190e17e362SPascal van Leeuwen 		},
23200e17e362SPascal van Leeuwen 	},
23210e17e362SPascal van Leeuwen };
23220e17e362SPascal van Leeuwen 
23230e17e362SPascal van Leeuwen static int safexcel_aead_sha256_ctr_cra_init(struct crypto_tfm *tfm)
23240e17e362SPascal van Leeuwen {
23250e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23260e17e362SPascal van Leeuwen 
23270e17e362SPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
23280e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23290e17e362SPascal van Leeuwen 	return 0;
23300e17e362SPascal van Leeuwen }
23310e17e362SPascal van Leeuwen 
23320e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_ctr_aes = {
23330e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2334062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
23350e17e362SPascal van Leeuwen 	.alg.aead = {
23360e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
233793369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
233893369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2339f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23400e17e362SPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
23410e17e362SPascal van Leeuwen 		.base = {
23420e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
23430e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-ctr-aes",
2344aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23450e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2346b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
23470e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23480e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23490e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23500e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23510e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_ctr_cra_init,
23520e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23530e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23540e17e362SPascal van Leeuwen 		},
23550e17e362SPascal van Leeuwen 	},
23560e17e362SPascal van Leeuwen };
23570e17e362SPascal van Leeuwen 
23580e17e362SPascal van Leeuwen static int safexcel_aead_sha224_ctr_cra_init(struct crypto_tfm *tfm)
23590e17e362SPascal van Leeuwen {
23600e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23610e17e362SPascal van Leeuwen 
23620e17e362SPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
23630e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23640e17e362SPascal van Leeuwen 	return 0;
23650e17e362SPascal van Leeuwen }
23660e17e362SPascal van Leeuwen 
23670e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_ctr_aes = {
23680e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2369062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
23700e17e362SPascal van Leeuwen 	.alg.aead = {
23710e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
237293369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
237393369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2374f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23750e17e362SPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
23760e17e362SPascal van Leeuwen 		.base = {
23770e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))",
23780e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-ctr-aes",
2379aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23800e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2381b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
23820e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23830e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23840e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23850e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23860e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_ctr_cra_init,
23870e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23880e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23890e17e362SPascal van Leeuwen 		},
23900e17e362SPascal van Leeuwen 	},
23910e17e362SPascal van Leeuwen };
23920e17e362SPascal van Leeuwen 
23930e17e362SPascal van Leeuwen static int safexcel_aead_sha512_ctr_cra_init(struct crypto_tfm *tfm)
23940e17e362SPascal van Leeuwen {
23950e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23960e17e362SPascal van Leeuwen 
23970e17e362SPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
23980e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23990e17e362SPascal van Leeuwen 	return 0;
24000e17e362SPascal van Leeuwen }
24010e17e362SPascal van Leeuwen 
24020e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_ctr_aes = {
24030e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2404062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
24050e17e362SPascal van Leeuwen 	.alg.aead = {
24060e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
240793369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
240893369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2409f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
24100e17e362SPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
24110e17e362SPascal van Leeuwen 		.base = {
24120e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
24130e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-ctr-aes",
2414aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
24150e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2416b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
24170e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
24180e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
24190e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
24200e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
24210e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_ctr_cra_init,
24220e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
24230e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
24240e17e362SPascal van Leeuwen 		},
24250e17e362SPascal van Leeuwen 	},
24260e17e362SPascal van Leeuwen };
24270e17e362SPascal van Leeuwen 
24280e17e362SPascal van Leeuwen static int safexcel_aead_sha384_ctr_cra_init(struct crypto_tfm *tfm)
24290e17e362SPascal van Leeuwen {
24300e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
24310e17e362SPascal van Leeuwen 
24320e17e362SPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
24330e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
24340e17e362SPascal van Leeuwen 	return 0;
24350e17e362SPascal van Leeuwen }
24360e17e362SPascal van Leeuwen 
24370e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_ctr_aes = {
24380e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2439062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
24400e17e362SPascal van Leeuwen 	.alg.aead = {
24410e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
244293369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
244393369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2444f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
24450e17e362SPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
24460e17e362SPascal van Leeuwen 		.base = {
24470e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
24480e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-ctr-aes",
2449aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
24500e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2451b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
24520e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
24530e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
24540e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
24550e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
24560e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_ctr_cra_init,
245777cdd4efSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
245877cdd4efSPascal van Leeuwen 			.cra_module = THIS_MODULE,
245977cdd4efSPascal van Leeuwen 		},
246077cdd4efSPascal van Leeuwen 	},
246177cdd4efSPascal van Leeuwen };
2462c7da38a7SPascal van Leeuwen 
2463c7da38a7SPascal van Leeuwen static int safexcel_skcipher_aesxts_setkey(struct crypto_skcipher *ctfm,
2464c7da38a7SPascal van Leeuwen 					   const u8 *key, unsigned int len)
2465c7da38a7SPascal van Leeuwen {
2466c7da38a7SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
2467c7da38a7SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
246818e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
2469c7da38a7SPascal van Leeuwen 	struct crypto_aes_ctx aes;
2470c7da38a7SPascal van Leeuwen 	int ret, i;
2471c7da38a7SPascal van Leeuwen 	unsigned int keylen;
2472c7da38a7SPascal van Leeuwen 
2473c7da38a7SPascal van Leeuwen 	/* Check for illegal XTS keys */
2474c7da38a7SPascal van Leeuwen 	ret = xts_verify_key(ctfm, key, len);
2475c7da38a7SPascal van Leeuwen 	if (ret)
2476c7da38a7SPascal van Leeuwen 		return ret;
2477c7da38a7SPascal van Leeuwen 
2478c7da38a7SPascal van Leeuwen 	/* Only half of the key data is cipher key */
2479c7da38a7SPascal van Leeuwen 	keylen = (len >> 1);
2480c7da38a7SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, keylen);
2481674f368aSEric Biggers 	if (ret)
2482c7da38a7SPascal van Leeuwen 		return ret;
2483c7da38a7SPascal van Leeuwen 
2484c7da38a7SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
2485c7da38a7SPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
248613a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
2487c7da38a7SPascal van Leeuwen 				ctx->base.needs_inv = true;
2488c7da38a7SPascal van Leeuwen 				break;
2489c7da38a7SPascal van Leeuwen 			}
2490c7da38a7SPascal van Leeuwen 		}
2491c7da38a7SPascal van Leeuwen 	}
2492c7da38a7SPascal van Leeuwen 
2493c7da38a7SPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
2494c7da38a7SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
2495c7da38a7SPascal van Leeuwen 
2496c7da38a7SPascal van Leeuwen 	/* The other half is the tweak key */
2497c7da38a7SPascal van Leeuwen 	ret = aes_expandkey(&aes, (u8 *)(key + keylen), keylen);
2498674f368aSEric Biggers 	if (ret)
2499c7da38a7SPascal van Leeuwen 		return ret;
2500c7da38a7SPascal van Leeuwen 
2501c7da38a7SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
2502c7da38a7SPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
250313a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i + keylen / sizeof(u32)]) !=
250413a1bb93SPascal van Leeuwen 			    aes.key_enc[i]) {
2505c7da38a7SPascal van Leeuwen 				ctx->base.needs_inv = true;
2506c7da38a7SPascal van Leeuwen 				break;
2507c7da38a7SPascal van Leeuwen 			}
2508c7da38a7SPascal van Leeuwen 		}
2509c7da38a7SPascal van Leeuwen 	}
2510c7da38a7SPascal van Leeuwen 
2511c7da38a7SPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
2512c7da38a7SPascal van Leeuwen 		ctx->key[i + keylen / sizeof(u32)] =
2513c7da38a7SPascal van Leeuwen 			cpu_to_le32(aes.key_enc[i]);
2514c7da38a7SPascal van Leeuwen 
2515c7da38a7SPascal van Leeuwen 	ctx->key_len = keylen << 1;
2516c7da38a7SPascal van Leeuwen 
2517c7da38a7SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
2518c7da38a7SPascal van Leeuwen 	return 0;
2519c7da38a7SPascal van Leeuwen }
2520c7da38a7SPascal van Leeuwen 
2521c7da38a7SPascal van Leeuwen static int safexcel_skcipher_aes_xts_cra_init(struct crypto_tfm *tfm)
2522c7da38a7SPascal van Leeuwen {
2523c7da38a7SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2524c7da38a7SPascal van Leeuwen 
2525c7da38a7SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
2526c7da38a7SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
2527098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
2528c7da38a7SPascal van Leeuwen 	ctx->xts  = 1;
2529c7da38a7SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XTS;
2530c7da38a7SPascal van Leeuwen 	return 0;
2531c7da38a7SPascal van Leeuwen }
2532c7da38a7SPascal van Leeuwen 
2533c7da38a7SPascal van Leeuwen static int safexcel_encrypt_xts(struct skcipher_request *req)
2534c7da38a7SPascal van Leeuwen {
2535c7da38a7SPascal van Leeuwen 	if (req->cryptlen < XTS_BLOCK_SIZE)
2536c7da38a7SPascal van Leeuwen 		return -EINVAL;
2537c7da38a7SPascal van Leeuwen 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2538c7da38a7SPascal van Leeuwen 				  SAFEXCEL_ENCRYPT);
2539c7da38a7SPascal van Leeuwen }
2540c7da38a7SPascal van Leeuwen 
2541c7da38a7SPascal van Leeuwen static int safexcel_decrypt_xts(struct skcipher_request *req)
2542c7da38a7SPascal van Leeuwen {
2543c7da38a7SPascal van Leeuwen 	if (req->cryptlen < XTS_BLOCK_SIZE)
2544c7da38a7SPascal van Leeuwen 		return -EINVAL;
2545c7da38a7SPascal van Leeuwen 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2546c7da38a7SPascal van Leeuwen 				  SAFEXCEL_DECRYPT);
2547c7da38a7SPascal van Leeuwen }
2548c7da38a7SPascal van Leeuwen 
2549c7da38a7SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xts_aes = {
2550c7da38a7SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
2551062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XTS,
2552c7da38a7SPascal van Leeuwen 	.alg.skcipher = {
2553c7da38a7SPascal van Leeuwen 		.setkey = safexcel_skcipher_aesxts_setkey,
2554c7da38a7SPascal van Leeuwen 		.encrypt = safexcel_encrypt_xts,
2555c7da38a7SPascal van Leeuwen 		.decrypt = safexcel_decrypt_xts,
2556c7da38a7SPascal van Leeuwen 		/* XTS actually uses 2 AES keys glued together */
2557c7da38a7SPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE * 2,
2558c7da38a7SPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE * 2,
2559c7da38a7SPascal van Leeuwen 		.ivsize = XTS_BLOCK_SIZE,
2560c7da38a7SPascal van Leeuwen 		.base = {
2561c7da38a7SPascal van Leeuwen 			.cra_name = "xts(aes)",
2562c7da38a7SPascal van Leeuwen 			.cra_driver_name = "safexcel-xts-aes",
2563aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2564c7da38a7SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2565b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2566c7da38a7SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2567c7da38a7SPascal van Leeuwen 			.cra_blocksize = XTS_BLOCK_SIZE,
2568c7da38a7SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2569c7da38a7SPascal van Leeuwen 			.cra_alignmask = 0,
2570c7da38a7SPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_xts_cra_init,
2571c7da38a7SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
2572c7da38a7SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2573c7da38a7SPascal van Leeuwen 		},
2574c7da38a7SPascal van Leeuwen 	},
2575c7da38a7SPascal van Leeuwen };
25763e450886SPascal van Leeuwen 
25773e450886SPascal van Leeuwen static int safexcel_aead_gcm_setkey(struct crypto_aead *ctfm, const u8 *key,
25783e450886SPascal van Leeuwen 				    unsigned int len)
25793e450886SPascal van Leeuwen {
25803e450886SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
25813e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
258218e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
25833e450886SPascal van Leeuwen 	struct crypto_aes_ctx aes;
25843e450886SPascal van Leeuwen 	u32 hashkey[AES_BLOCK_SIZE >> 2];
25853e450886SPascal van Leeuwen 	int ret, i;
25863e450886SPascal van Leeuwen 
25873e450886SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
25883e450886SPascal van Leeuwen 	if (ret) {
25893e450886SPascal van Leeuwen 		memzero_explicit(&aes, sizeof(aes));
25903e450886SPascal van Leeuwen 		return ret;
25913e450886SPascal van Leeuwen 	}
25923e450886SPascal van Leeuwen 
25933e450886SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
25943e450886SPascal van Leeuwen 		for (i = 0; i < len / sizeof(u32); i++) {
259513a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
25963e450886SPascal van Leeuwen 				ctx->base.needs_inv = true;
25973e450886SPascal van Leeuwen 				break;
25983e450886SPascal van Leeuwen 			}
25993e450886SPascal van Leeuwen 		}
26003e450886SPascal van Leeuwen 	}
26013e450886SPascal van Leeuwen 
26023e450886SPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
26033e450886SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
26043e450886SPascal van Leeuwen 
26053e450886SPascal van Leeuwen 	ctx->key_len = len;
26063e450886SPascal van Leeuwen 
26073e450886SPascal van Leeuwen 	/* Compute hash key by encrypting zeroes with cipher key */
26083e450886SPascal van Leeuwen 	memset(hashkey, 0, AES_BLOCK_SIZE);
2609320406cbSPeter Harliman Liem 	aes_encrypt(&aes, (u8 *)hashkey, (u8 *)hashkey);
26103e450886SPascal van Leeuwen 
26113e450886SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
26123e450886SPascal van Leeuwen 		for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) {
261378cf1c8bSHerbert Xu 			if (be32_to_cpu(ctx->base.ipad.be[i]) != hashkey[i]) {
26143e450886SPascal van Leeuwen 				ctx->base.needs_inv = true;
26153e450886SPascal van Leeuwen 				break;
26163e450886SPascal van Leeuwen 			}
26173e450886SPascal van Leeuwen 		}
26183e450886SPascal van Leeuwen 	}
26193e450886SPascal van Leeuwen 
26203e450886SPascal van Leeuwen 	for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
262178cf1c8bSHerbert Xu 		ctx->base.ipad.be[i] = cpu_to_be32(hashkey[i]);
26223e450886SPascal van Leeuwen 
26233e450886SPascal van Leeuwen 	memzero_explicit(hashkey, AES_BLOCK_SIZE);
26243e450886SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
26253e450886SPascal van Leeuwen 	return 0;
26263e450886SPascal van Leeuwen }
26273e450886SPascal van Leeuwen 
26283e450886SPascal van Leeuwen static int safexcel_aead_gcm_cra_init(struct crypto_tfm *tfm)
26293e450886SPascal van Leeuwen {
26303e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
26313e450886SPascal van Leeuwen 
26323e450886SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
26333e450886SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_GHASH;
26343e450886SPascal van Leeuwen 	ctx->state_sz = GHASH_BLOCK_SIZE;
26354eb76fafSPascal van Leeuwen 	ctx->xcm = EIP197_XCM_MODE_GCM;
26363e450886SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */
26373e450886SPascal van Leeuwen 
2638320406cbSPeter Harliman Liem 	return 0;
26393e450886SPascal van Leeuwen }
26403e450886SPascal van Leeuwen 
26413e450886SPascal van Leeuwen static void safexcel_aead_gcm_cra_exit(struct crypto_tfm *tfm)
26423e450886SPascal van Leeuwen {
26433e450886SPascal van Leeuwen 	safexcel_aead_cra_exit(tfm);
26443e450886SPascal van Leeuwen }
26453e450886SPascal van Leeuwen 
26463e450886SPascal van Leeuwen static int safexcel_aead_gcm_setauthsize(struct crypto_aead *tfm,
26473e450886SPascal van Leeuwen 					 unsigned int authsize)
26483e450886SPascal van Leeuwen {
26493e450886SPascal van Leeuwen 	return crypto_gcm_check_authsize(authsize);
26503e450886SPascal van Leeuwen }
26513e450886SPascal van Leeuwen 
26523e450886SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_gcm = {
26533e450886SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
26543e450886SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
26553e450886SPascal van Leeuwen 	.alg.aead = {
26563e450886SPascal van Leeuwen 		.setkey = safexcel_aead_gcm_setkey,
26573e450886SPascal van Leeuwen 		.setauthsize = safexcel_aead_gcm_setauthsize,
26583e450886SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
26593e450886SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
26603e450886SPascal van Leeuwen 		.ivsize = GCM_AES_IV_SIZE,
26613e450886SPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
26623e450886SPascal van Leeuwen 		.base = {
26633e450886SPascal van Leeuwen 			.cra_name = "gcm(aes)",
26643e450886SPascal van Leeuwen 			.cra_driver_name = "safexcel-gcm-aes",
26653e450886SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
26663e450886SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2667b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
26683e450886SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
26693e450886SPascal van Leeuwen 			.cra_blocksize = 1,
26703e450886SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
26713e450886SPascal van Leeuwen 			.cra_alignmask = 0,
26723e450886SPascal van Leeuwen 			.cra_init = safexcel_aead_gcm_cra_init,
26733e450886SPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
26743e450886SPascal van Leeuwen 			.cra_module = THIS_MODULE,
26753e450886SPascal van Leeuwen 		},
26763e450886SPascal van Leeuwen 	},
26773e450886SPascal van Leeuwen };
26784eb76fafSPascal van Leeuwen 
26794eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_setkey(struct crypto_aead *ctfm, const u8 *key,
26804eb76fafSPascal van Leeuwen 				    unsigned int len)
26814eb76fafSPascal van Leeuwen {
26824eb76fafSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
26834eb76fafSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
268418e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
26854eb76fafSPascal van Leeuwen 	struct crypto_aes_ctx aes;
26864eb76fafSPascal van Leeuwen 	int ret, i;
26874eb76fafSPascal van Leeuwen 
26884eb76fafSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
26894eb76fafSPascal van Leeuwen 	if (ret) {
26904eb76fafSPascal van Leeuwen 		memzero_explicit(&aes, sizeof(aes));
26914eb76fafSPascal van Leeuwen 		return ret;
26924eb76fafSPascal van Leeuwen 	}
26934eb76fafSPascal van Leeuwen 
26944eb76fafSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
26954eb76fafSPascal van Leeuwen 		for (i = 0; i < len / sizeof(u32); i++) {
269613a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
26974eb76fafSPascal van Leeuwen 				ctx->base.needs_inv = true;
26984eb76fafSPascal van Leeuwen 				break;
26994eb76fafSPascal van Leeuwen 			}
27004eb76fafSPascal van Leeuwen 		}
27014eb76fafSPascal van Leeuwen 	}
27024eb76fafSPascal van Leeuwen 
27034eb76fafSPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++) {
27044eb76fafSPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
270578cf1c8bSHerbert Xu 		ctx->base.ipad.be[i + 2 * AES_BLOCK_SIZE / sizeof(u32)] =
27064eb76fafSPascal van Leeuwen 			cpu_to_be32(aes.key_enc[i]);
27074eb76fafSPascal van Leeuwen 	}
27084eb76fafSPascal van Leeuwen 
27094eb76fafSPascal van Leeuwen 	ctx->key_len = len;
27104eb76fafSPascal van Leeuwen 	ctx->state_sz = 2 * AES_BLOCK_SIZE + len;
27114eb76fafSPascal van Leeuwen 
27124eb76fafSPascal van Leeuwen 	if (len == AES_KEYSIZE_192)
27134eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
27144eb76fafSPascal van Leeuwen 	else if (len == AES_KEYSIZE_256)
27154eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
27164eb76fafSPascal van Leeuwen 	else
27174eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
27184eb76fafSPascal van Leeuwen 
27194eb76fafSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
27204eb76fafSPascal van Leeuwen 	return 0;
27214eb76fafSPascal van Leeuwen }
27224eb76fafSPascal van Leeuwen 
27234eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_cra_init(struct crypto_tfm *tfm)
27244eb76fafSPascal van Leeuwen {
27254eb76fafSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
27264eb76fafSPascal van Leeuwen 
27274eb76fafSPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
27284eb76fafSPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
27294eb76fafSPascal van Leeuwen 	ctx->state_sz = 3 * AES_BLOCK_SIZE;
27304eb76fafSPascal van Leeuwen 	ctx->xcm = EIP197_XCM_MODE_CCM;
27314eb76fafSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */
2732098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
27334eb76fafSPascal van Leeuwen 	return 0;
27344eb76fafSPascal van Leeuwen }
27354eb76fafSPascal van Leeuwen 
27364eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_setauthsize(struct crypto_aead *tfm,
27374eb76fafSPascal van Leeuwen 					 unsigned int authsize)
27384eb76fafSPascal van Leeuwen {
27394eb76fafSPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
27404eb76fafSPascal van Leeuwen 	switch (authsize) {
27414eb76fafSPascal van Leeuwen 	case 4:
27424eb76fafSPascal van Leeuwen 	case 6:
27434eb76fafSPascal van Leeuwen 	case 8:
27444eb76fafSPascal van Leeuwen 	case 10:
27454eb76fafSPascal van Leeuwen 	case 12:
27464eb76fafSPascal van Leeuwen 	case 14:
27474eb76fafSPascal van Leeuwen 	case 16:
27484eb76fafSPascal van Leeuwen 		break;
27494eb76fafSPascal van Leeuwen 	default:
27504eb76fafSPascal van Leeuwen 		return -EINVAL;
27514eb76fafSPascal van Leeuwen 	}
27524eb76fafSPascal van Leeuwen 
27534eb76fafSPascal van Leeuwen 	return 0;
27544eb76fafSPascal van Leeuwen }
27554eb76fafSPascal van Leeuwen 
27564eb76fafSPascal van Leeuwen static int safexcel_ccm_encrypt(struct aead_request *req)
27574eb76fafSPascal van Leeuwen {
27584eb76fafSPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
27594eb76fafSPascal van Leeuwen 
27604eb76fafSPascal van Leeuwen 	if (req->iv[0] < 1 || req->iv[0] > 7)
27614eb76fafSPascal van Leeuwen 		return -EINVAL;
27624eb76fafSPascal van Leeuwen 
27634eb76fafSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
27644eb76fafSPascal van Leeuwen }
27654eb76fafSPascal van Leeuwen 
27664eb76fafSPascal van Leeuwen static int safexcel_ccm_decrypt(struct aead_request *req)
27674eb76fafSPascal van Leeuwen {
27684eb76fafSPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
27694eb76fafSPascal van Leeuwen 
27704eb76fafSPascal van Leeuwen 	if (req->iv[0] < 1 || req->iv[0] > 7)
27714eb76fafSPascal van Leeuwen 		return -EINVAL;
27724eb76fafSPascal van Leeuwen 
27734eb76fafSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
27744eb76fafSPascal van Leeuwen }
27754eb76fafSPascal van Leeuwen 
27764eb76fafSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ccm = {
27774eb76fafSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
27784eb76fafSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL,
27794eb76fafSPascal van Leeuwen 	.alg.aead = {
27804eb76fafSPascal van Leeuwen 		.setkey = safexcel_aead_ccm_setkey,
27814eb76fafSPascal van Leeuwen 		.setauthsize = safexcel_aead_ccm_setauthsize,
27824eb76fafSPascal van Leeuwen 		.encrypt = safexcel_ccm_encrypt,
27834eb76fafSPascal van Leeuwen 		.decrypt = safexcel_ccm_decrypt,
27844eb76fafSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
27854eb76fafSPascal van Leeuwen 		.maxauthsize = AES_BLOCK_SIZE,
27864eb76fafSPascal van Leeuwen 		.base = {
27874eb76fafSPascal van Leeuwen 			.cra_name = "ccm(aes)",
27884eb76fafSPascal van Leeuwen 			.cra_driver_name = "safexcel-ccm-aes",
27894eb76fafSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
27904eb76fafSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2791b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
27924eb76fafSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
27934eb76fafSPascal van Leeuwen 			.cra_blocksize = 1,
27944eb76fafSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
27954eb76fafSPascal van Leeuwen 			.cra_alignmask = 0,
27964eb76fafSPascal van Leeuwen 			.cra_init = safexcel_aead_ccm_cra_init,
27974eb76fafSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
27984eb76fafSPascal van Leeuwen 			.cra_module = THIS_MODULE,
27994eb76fafSPascal van Leeuwen 		},
28004eb76fafSPascal van Leeuwen 	},
28014eb76fafSPascal van Leeuwen };
28024a593fb3SPascal van Leeuwen 
2803a6061921SPascal van Leeuwen static void safexcel_chacha20_setkey(struct safexcel_cipher_ctx *ctx,
2804a6061921SPascal van Leeuwen 				     const u8 *key)
28054a593fb3SPascal van Leeuwen {
280618e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
28074a593fb3SPascal van Leeuwen 
280813a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
280913a1bb93SPascal van Leeuwen 		if (memcmp(ctx->key, key, CHACHA_KEY_SIZE))
28104a593fb3SPascal van Leeuwen 			ctx->base.needs_inv = true;
28114a593fb3SPascal van Leeuwen 
281213a1bb93SPascal van Leeuwen 	memcpy(ctx->key, key, CHACHA_KEY_SIZE);
28134a593fb3SPascal van Leeuwen 	ctx->key_len = CHACHA_KEY_SIZE;
2814a6061921SPascal van Leeuwen }
2815a6061921SPascal van Leeuwen 
2816a6061921SPascal van Leeuwen static int safexcel_skcipher_chacha20_setkey(struct crypto_skcipher *ctfm,
2817a6061921SPascal van Leeuwen 					     const u8 *key, unsigned int len)
2818a6061921SPascal van Leeuwen {
2819a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
2820a6061921SPascal van Leeuwen 
2821674f368aSEric Biggers 	if (len != CHACHA_KEY_SIZE)
2822a6061921SPascal van Leeuwen 		return -EINVAL;
2823674f368aSEric Biggers 
2824a6061921SPascal van Leeuwen 	safexcel_chacha20_setkey(ctx, key);
28254a593fb3SPascal van Leeuwen 
28264a593fb3SPascal van Leeuwen 	return 0;
28274a593fb3SPascal van Leeuwen }
28284a593fb3SPascal van Leeuwen 
28294a593fb3SPascal van Leeuwen static int safexcel_skcipher_chacha20_cra_init(struct crypto_tfm *tfm)
28304a593fb3SPascal van Leeuwen {
28314a593fb3SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
28324a593fb3SPascal van Leeuwen 
28334a593fb3SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
28344a593fb3SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_CHACHA20;
2835098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
28364a593fb3SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32;
28374a593fb3SPascal van Leeuwen 	return 0;
28384a593fb3SPascal van Leeuwen }
28394a593fb3SPascal van Leeuwen 
28404a593fb3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chacha20 = {
28414a593fb3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
28424a593fb3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20,
28434a593fb3SPascal van Leeuwen 	.alg.skcipher = {
28444a593fb3SPascal van Leeuwen 		.setkey = safexcel_skcipher_chacha20_setkey,
28454a593fb3SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
28464a593fb3SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
28474a593fb3SPascal van Leeuwen 		.min_keysize = CHACHA_KEY_SIZE,
28484a593fb3SPascal van Leeuwen 		.max_keysize = CHACHA_KEY_SIZE,
28494a593fb3SPascal van Leeuwen 		.ivsize = CHACHA_IV_SIZE,
28504a593fb3SPascal van Leeuwen 		.base = {
28514a593fb3SPascal van Leeuwen 			.cra_name = "chacha20",
28524a593fb3SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20",
28534a593fb3SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
28544a593fb3SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2855b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
28564a593fb3SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
28574a593fb3SPascal van Leeuwen 			.cra_blocksize = 1,
28584a593fb3SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
28594a593fb3SPascal van Leeuwen 			.cra_alignmask = 0,
28604a593fb3SPascal van Leeuwen 			.cra_init = safexcel_skcipher_chacha20_cra_init,
28614a593fb3SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
28624a593fb3SPascal van Leeuwen 			.cra_module = THIS_MODULE,
28634a593fb3SPascal van Leeuwen 		},
28644a593fb3SPascal van Leeuwen 	},
28654a593fb3SPascal van Leeuwen };
2866a6061921SPascal van Leeuwen 
2867a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_setkey(struct crypto_aead *ctfm,
2868a6061921SPascal van Leeuwen 				    const u8 *key, unsigned int len)
2869a6061921SPascal van Leeuwen {
2870a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_aead_ctx(ctfm);
2871a6061921SPascal van Leeuwen 
2872a6061921SPascal van Leeuwen 	if (ctx->aead  == EIP197_AEAD_TYPE_IPSEC_ESP &&
2873a6061921SPascal van Leeuwen 	    len > EIP197_AEAD_IPSEC_NONCE_SIZE) {
2874a6061921SPascal van Leeuwen 		/* ESP variant has nonce appended to key */
2875a6061921SPascal van Leeuwen 		len -= EIP197_AEAD_IPSEC_NONCE_SIZE;
2876a6061921SPascal van Leeuwen 		ctx->nonce = *(u32 *)(key + len);
2877a6061921SPascal van Leeuwen 	}
2878674f368aSEric Biggers 	if (len != CHACHA_KEY_SIZE)
2879a6061921SPascal van Leeuwen 		return -EINVAL;
2880674f368aSEric Biggers 
2881a6061921SPascal van Leeuwen 	safexcel_chacha20_setkey(ctx, key);
2882a6061921SPascal van Leeuwen 
2883a6061921SPascal van Leeuwen 	return 0;
2884a6061921SPascal van Leeuwen }
2885a6061921SPascal van Leeuwen 
2886a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_setauthsize(struct crypto_aead *tfm,
2887a6061921SPascal van Leeuwen 					 unsigned int authsize)
2888a6061921SPascal van Leeuwen {
2889a6061921SPascal van Leeuwen 	if (authsize != POLY1305_DIGEST_SIZE)
2890a6061921SPascal van Leeuwen 		return -EINVAL;
2891a6061921SPascal van Leeuwen 	return 0;
2892a6061921SPascal van Leeuwen }
2893a6061921SPascal van Leeuwen 
2894a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_crypt(struct aead_request *req,
2895a6061921SPascal van Leeuwen 					  enum safexcel_cipher_direction dir)
2896a6061921SPascal van Leeuwen {
2897a6061921SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
2898a6061921SPascal van Leeuwen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2899a6061921SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
2900a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2901a6061921SPascal van Leeuwen 	struct aead_request *subreq = aead_request_ctx(req);
2902a6061921SPascal van Leeuwen 	u32 key[CHACHA_KEY_SIZE / sizeof(u32) + 1];
290313a1bb93SPascal van Leeuwen 	int ret = 0;
2904a6061921SPascal van Leeuwen 
2905a6061921SPascal van Leeuwen 	/*
2906a6061921SPascal van Leeuwen 	 * Instead of wasting time detecting umpteen silly corner cases,
2907a6061921SPascal van Leeuwen 	 * just dump all "small" requests to the fallback implementation.
2908a6061921SPascal van Leeuwen 	 * HW would not be faster on such small requests anyway.
2909a6061921SPascal van Leeuwen 	 */
2910a6061921SPascal van Leeuwen 	if (likely((ctx->aead != EIP197_AEAD_TYPE_IPSEC_ESP ||
2911a6061921SPascal van Leeuwen 		    req->assoclen >= EIP197_AEAD_IPSEC_IV_SIZE) &&
2912a6061921SPascal van Leeuwen 		   req->cryptlen > POLY1305_DIGEST_SIZE)) {
2913a6061921SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, dir);
2914a6061921SPascal van Leeuwen 	}
2915a6061921SPascal van Leeuwen 
2916a6061921SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
291713a1bb93SPascal van Leeuwen 	memcpy(key, ctx->key, CHACHA_KEY_SIZE);
2918a6061921SPascal van Leeuwen 	if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
2919a6061921SPascal van Leeuwen 		/* ESP variant has nonce appended to the key */
2920a6061921SPascal van Leeuwen 		key[CHACHA_KEY_SIZE / sizeof(u32)] = ctx->nonce;
2921a6061921SPascal van Leeuwen 		ret = crypto_aead_setkey(ctx->fback, (u8 *)key,
2922a6061921SPascal van Leeuwen 					 CHACHA_KEY_SIZE +
2923a6061921SPascal van Leeuwen 					 EIP197_AEAD_IPSEC_NONCE_SIZE);
2924a6061921SPascal van Leeuwen 	} else {
2925a6061921SPascal van Leeuwen 		ret = crypto_aead_setkey(ctx->fback, (u8 *)key,
2926a6061921SPascal van Leeuwen 					 CHACHA_KEY_SIZE);
2927a6061921SPascal van Leeuwen 	}
2928a6061921SPascal van Leeuwen 	if (ret) {
2929a6061921SPascal van Leeuwen 		crypto_aead_clear_flags(aead, CRYPTO_TFM_REQ_MASK);
2930a6061921SPascal van Leeuwen 		crypto_aead_set_flags(aead, crypto_aead_get_flags(ctx->fback) &
2931a6061921SPascal van Leeuwen 					    CRYPTO_TFM_REQ_MASK);
2932a6061921SPascal van Leeuwen 		return ret;
2933a6061921SPascal van Leeuwen 	}
2934a6061921SPascal van Leeuwen 
2935a6061921SPascal van Leeuwen 	aead_request_set_tfm(subreq, ctx->fback);
2936a6061921SPascal van Leeuwen 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
2937a6061921SPascal van Leeuwen 				  req->base.data);
2938a6061921SPascal van Leeuwen 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
2939a6061921SPascal van Leeuwen 			       req->iv);
2940a6061921SPascal van Leeuwen 	aead_request_set_ad(subreq, req->assoclen);
2941a6061921SPascal van Leeuwen 
2942a6061921SPascal van Leeuwen 	return (dir ==  SAFEXCEL_ENCRYPT) ?
2943a6061921SPascal van Leeuwen 		crypto_aead_encrypt(subreq) :
2944a6061921SPascal van Leeuwen 		crypto_aead_decrypt(subreq);
2945a6061921SPascal van Leeuwen }
2946a6061921SPascal van Leeuwen 
2947a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_encrypt(struct aead_request *req)
2948a6061921SPascal van Leeuwen {
2949a6061921SPascal van Leeuwen 	return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_ENCRYPT);
2950a6061921SPascal van Leeuwen }
2951a6061921SPascal van Leeuwen 
2952a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_decrypt(struct aead_request *req)
2953a6061921SPascal van Leeuwen {
2954a6061921SPascal van Leeuwen 	return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_DECRYPT);
2955a6061921SPascal van Leeuwen }
2956a6061921SPascal van Leeuwen 
29571769f704SPascal van Leeuwen static int safexcel_aead_fallback_cra_init(struct crypto_tfm *tfm)
2958a6061921SPascal van Leeuwen {
2959a6061921SPascal van Leeuwen 	struct crypto_aead *aead = __crypto_aead_cast(tfm);
2960a6061921SPascal van Leeuwen 	struct aead_alg *alg = crypto_aead_alg(aead);
2961a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2962a6061921SPascal van Leeuwen 
2963a6061921SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
2964a6061921SPascal van Leeuwen 
2965a6061921SPascal van Leeuwen 	/* Allocate fallback implementation */
2966a6061921SPascal van Leeuwen 	ctx->fback = crypto_alloc_aead(alg->base.cra_name, 0,
2967a6061921SPascal van Leeuwen 				       CRYPTO_ALG_ASYNC |
2968a6061921SPascal van Leeuwen 				       CRYPTO_ALG_NEED_FALLBACK);
2969a6061921SPascal van Leeuwen 	if (IS_ERR(ctx->fback))
2970a6061921SPascal van Leeuwen 		return PTR_ERR(ctx->fback);
2971a6061921SPascal van Leeuwen 
2972a6061921SPascal van Leeuwen 	crypto_aead_set_reqsize(aead, max(sizeof(struct safexcel_cipher_req),
2973a6061921SPascal van Leeuwen 					  sizeof(struct aead_request) +
2974a6061921SPascal van Leeuwen 					  crypto_aead_reqsize(ctx->fback)));
2975a6061921SPascal van Leeuwen 
2976a6061921SPascal van Leeuwen 	return 0;
2977a6061921SPascal van Leeuwen }
2978a6061921SPascal van Leeuwen 
29791769f704SPascal van Leeuwen static int safexcel_aead_chachapoly_cra_init(struct crypto_tfm *tfm)
29801769f704SPascal van Leeuwen {
29811769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
29821769f704SPascal van Leeuwen 
29831769f704SPascal van Leeuwen 	safexcel_aead_fallback_cra_init(tfm);
29841769f704SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_CHACHA20;
29851769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32 |
29861769f704SPascal van Leeuwen 		    CONTEXT_CONTROL_CHACHA20_MODE_CALC_OTK;
2987098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
29881769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_POLY1305;
29891769f704SPascal van Leeuwen 	ctx->state_sz = 0; /* Precomputed by HW */
29901769f704SPascal van Leeuwen 	return 0;
29911769f704SPascal van Leeuwen }
29921769f704SPascal van Leeuwen 
29931769f704SPascal van Leeuwen static void safexcel_aead_fallback_cra_exit(struct crypto_tfm *tfm)
2994a6061921SPascal van Leeuwen {
2995a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2996a6061921SPascal van Leeuwen 
2997a6061921SPascal van Leeuwen 	crypto_free_aead(ctx->fback);
2998a6061921SPascal van Leeuwen 	safexcel_aead_cra_exit(tfm);
2999a6061921SPascal van Leeuwen }
3000a6061921SPascal van Leeuwen 
3001a6061921SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chachapoly = {
3002a6061921SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3003a6061921SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305,
3004a6061921SPascal van Leeuwen 	.alg.aead = {
3005a6061921SPascal van Leeuwen 		.setkey = safexcel_aead_chachapoly_setkey,
3006a6061921SPascal van Leeuwen 		.setauthsize = safexcel_aead_chachapoly_setauthsize,
3007a6061921SPascal van Leeuwen 		.encrypt = safexcel_aead_chachapoly_encrypt,
3008a6061921SPascal van Leeuwen 		.decrypt = safexcel_aead_chachapoly_decrypt,
3009a6061921SPascal van Leeuwen 		.ivsize = CHACHAPOLY_IV_SIZE,
3010a6061921SPascal van Leeuwen 		.maxauthsize = POLY1305_DIGEST_SIZE,
3011a6061921SPascal van Leeuwen 		.base = {
3012a6061921SPascal van Leeuwen 			.cra_name = "rfc7539(chacha20,poly1305)",
3013a6061921SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20-poly1305",
3014a6061921SPascal van Leeuwen 			/* +1 to put it above HW chacha + SW poly */
3015a6061921SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY + 1,
3016a6061921SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3017b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3018a6061921SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
3019a6061921SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
3020a6061921SPascal van Leeuwen 			.cra_blocksize = 1,
3021a6061921SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3022a6061921SPascal van Leeuwen 			.cra_alignmask = 0,
3023a6061921SPascal van Leeuwen 			.cra_init = safexcel_aead_chachapoly_cra_init,
30241769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
3025a6061921SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3026a6061921SPascal van Leeuwen 		},
3027a6061921SPascal van Leeuwen 	},
3028a6061921SPascal van Leeuwen };
3029a6061921SPascal van Leeuwen 
3030a6061921SPascal van Leeuwen static int safexcel_aead_chachapolyesp_cra_init(struct crypto_tfm *tfm)
3031a6061921SPascal van Leeuwen {
3032a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3033a6061921SPascal van Leeuwen 	int ret;
3034a6061921SPascal van Leeuwen 
3035a6061921SPascal van Leeuwen 	ret = safexcel_aead_chachapoly_cra_init(tfm);
3036a6061921SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3037098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3038a6061921SPascal van Leeuwen 	return ret;
3039a6061921SPascal van Leeuwen }
3040a6061921SPascal van Leeuwen 
3041a6061921SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chachapoly_esp = {
3042a6061921SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3043a6061921SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305,
3044a6061921SPascal van Leeuwen 	.alg.aead = {
3045a6061921SPascal van Leeuwen 		.setkey = safexcel_aead_chachapoly_setkey,
3046a6061921SPascal van Leeuwen 		.setauthsize = safexcel_aead_chachapoly_setauthsize,
3047a6061921SPascal van Leeuwen 		.encrypt = safexcel_aead_chachapoly_encrypt,
3048a6061921SPascal van Leeuwen 		.decrypt = safexcel_aead_chachapoly_decrypt,
3049a6061921SPascal van Leeuwen 		.ivsize = CHACHAPOLY_IV_SIZE - EIP197_AEAD_IPSEC_NONCE_SIZE,
3050a6061921SPascal van Leeuwen 		.maxauthsize = POLY1305_DIGEST_SIZE,
3051a6061921SPascal van Leeuwen 		.base = {
3052a6061921SPascal van Leeuwen 			.cra_name = "rfc7539esp(chacha20,poly1305)",
3053a6061921SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20-poly1305-esp",
3054a6061921SPascal van Leeuwen 			/* +1 to put it above HW chacha + SW poly */
3055a6061921SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY + 1,
3056a6061921SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3057b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3058a6061921SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
3059a6061921SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
3060a6061921SPascal van Leeuwen 			.cra_blocksize = 1,
3061a6061921SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3062a6061921SPascal van Leeuwen 			.cra_alignmask = 0,
3063a6061921SPascal van Leeuwen 			.cra_init = safexcel_aead_chachapolyesp_cra_init,
30641769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
3065a6061921SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3066a6061921SPascal van Leeuwen 		},
3067a6061921SPascal van Leeuwen 	},
3068a6061921SPascal van Leeuwen };
3069fcca797dSPascal van Leeuwen 
3070fcca797dSPascal van Leeuwen static int safexcel_skcipher_sm4_setkey(struct crypto_skcipher *ctfm,
3071fcca797dSPascal van Leeuwen 					const u8 *key, unsigned int len)
3072fcca797dSPascal van Leeuwen {
3073fcca797dSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3074fcca797dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
307518e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
3076fcca797dSPascal van Leeuwen 
3077674f368aSEric Biggers 	if (len != SM4_KEY_SIZE)
3078fcca797dSPascal van Leeuwen 		return -EINVAL;
3079fcca797dSPascal van Leeuwen 
308013a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
308113a1bb93SPascal van Leeuwen 		if (memcmp(ctx->key, key, SM4_KEY_SIZE))
3082fcca797dSPascal van Leeuwen 			ctx->base.needs_inv = true;
3083fcca797dSPascal van Leeuwen 
308413a1bb93SPascal van Leeuwen 	memcpy(ctx->key, key, SM4_KEY_SIZE);
3085fcca797dSPascal van Leeuwen 	ctx->key_len = SM4_KEY_SIZE;
3086fcca797dSPascal van Leeuwen 
3087fcca797dSPascal van Leeuwen 	return 0;
3088fcca797dSPascal van Leeuwen }
3089fcca797dSPascal van Leeuwen 
3090fcca797dSPascal van Leeuwen static int safexcel_sm4_blk_encrypt(struct skcipher_request *req)
3091fcca797dSPascal van Leeuwen {
3092fcca797dSPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
3093fcca797dSPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
3094fcca797dSPascal van Leeuwen 		return -EINVAL;
3095fcca797dSPascal van Leeuwen 	else
3096fcca797dSPascal van Leeuwen 		return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
3097fcca797dSPascal van Leeuwen 					  SAFEXCEL_ENCRYPT);
3098fcca797dSPascal van Leeuwen }
3099fcca797dSPascal van Leeuwen 
3100fcca797dSPascal van Leeuwen static int safexcel_sm4_blk_decrypt(struct skcipher_request *req)
3101fcca797dSPascal van Leeuwen {
3102fcca797dSPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
3103fcca797dSPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
3104fcca797dSPascal van Leeuwen 		return -EINVAL;
3105fcca797dSPascal van Leeuwen 	else
3106fcca797dSPascal van Leeuwen 		return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
3107fcca797dSPascal van Leeuwen 					  SAFEXCEL_DECRYPT);
3108fcca797dSPascal van Leeuwen }
3109fcca797dSPascal van Leeuwen 
3110fcca797dSPascal van Leeuwen static int safexcel_skcipher_sm4_ecb_cra_init(struct crypto_tfm *tfm)
3111fcca797dSPascal van Leeuwen {
3112fcca797dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3113fcca797dSPascal van Leeuwen 
3114fcca797dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
3115fcca797dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3116fcca797dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
3117098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
3118098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
3119fcca797dSPascal van Leeuwen 	return 0;
3120fcca797dSPascal van Leeuwen }
3121fcca797dSPascal van Leeuwen 
3122fcca797dSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ecb_sm4 = {
3123fcca797dSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
3124fcca797dSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
3125fcca797dSPascal van Leeuwen 	.alg.skcipher = {
3126fcca797dSPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
3127fcca797dSPascal van Leeuwen 		.encrypt = safexcel_sm4_blk_encrypt,
3128fcca797dSPascal van Leeuwen 		.decrypt = safexcel_sm4_blk_decrypt,
3129fcca797dSPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
3130fcca797dSPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
3131fcca797dSPascal van Leeuwen 		.base = {
3132fcca797dSPascal van Leeuwen 			.cra_name = "ecb(sm4)",
3133fcca797dSPascal van Leeuwen 			.cra_driver_name = "safexcel-ecb-sm4",
3134fcca797dSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3135fcca797dSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3136b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3137fcca797dSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3138fcca797dSPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
3139fcca797dSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3140fcca797dSPascal van Leeuwen 			.cra_alignmask = 0,
3141fcca797dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ecb_cra_init,
3142fcca797dSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
3143fcca797dSPascal van Leeuwen 			.cra_module = THIS_MODULE,
3144fcca797dSPascal van Leeuwen 		},
3145fcca797dSPascal van Leeuwen 	},
3146fcca797dSPascal van Leeuwen };
31476f2d1428SPascal van Leeuwen 
31486f2d1428SPascal van Leeuwen static int safexcel_skcipher_sm4_cbc_cra_init(struct crypto_tfm *tfm)
31496f2d1428SPascal van Leeuwen {
31506f2d1428SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
31516f2d1428SPascal van Leeuwen 
31526f2d1428SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
31536f2d1428SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3154098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
31556f2d1428SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
31566f2d1428SPascal van Leeuwen 	return 0;
31576f2d1428SPascal van Leeuwen }
31586f2d1428SPascal van Leeuwen 
31596f2d1428SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbc_sm4 = {
31606f2d1428SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
31616f2d1428SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
31626f2d1428SPascal van Leeuwen 	.alg.skcipher = {
31636f2d1428SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
31646f2d1428SPascal van Leeuwen 		.encrypt = safexcel_sm4_blk_encrypt,
31656f2d1428SPascal van Leeuwen 		.decrypt = safexcel_sm4_blk_decrypt,
31666f2d1428SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
31676f2d1428SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
31686f2d1428SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
31696f2d1428SPascal van Leeuwen 		.base = {
31706f2d1428SPascal van Leeuwen 			.cra_name = "cbc(sm4)",
31716f2d1428SPascal van Leeuwen 			.cra_driver_name = "safexcel-cbc-sm4",
31726f2d1428SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
31736f2d1428SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3174b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
31756f2d1428SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
31766f2d1428SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
31776f2d1428SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
31786f2d1428SPascal van Leeuwen 			.cra_alignmask = 0,
31796f2d1428SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_cbc_cra_init,
31806f2d1428SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
31816f2d1428SPascal van Leeuwen 			.cra_module = THIS_MODULE,
31826f2d1428SPascal van Leeuwen 		},
31836f2d1428SPascal van Leeuwen 	},
31846f2d1428SPascal van Leeuwen };
318503a6cfb9SPascal van Leeuwen 
318603a6cfb9SPascal van Leeuwen static int safexcel_skcipher_sm4_ofb_cra_init(struct crypto_tfm *tfm)
318703a6cfb9SPascal van Leeuwen {
318803a6cfb9SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
318903a6cfb9SPascal van Leeuwen 
319003a6cfb9SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
319103a6cfb9SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3192098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
319303a6cfb9SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB;
319403a6cfb9SPascal van Leeuwen 	return 0;
319503a6cfb9SPascal van Leeuwen }
319603a6cfb9SPascal van Leeuwen 
319703a6cfb9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ofb_sm4 = {
319803a6cfb9SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
319903a6cfb9SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB,
320003a6cfb9SPascal van Leeuwen 	.alg.skcipher = {
320103a6cfb9SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
320203a6cfb9SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
320303a6cfb9SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
320403a6cfb9SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
320503a6cfb9SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
320603a6cfb9SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
320703a6cfb9SPascal van Leeuwen 		.base = {
320803a6cfb9SPascal van Leeuwen 			.cra_name = "ofb(sm4)",
320903a6cfb9SPascal van Leeuwen 			.cra_driver_name = "safexcel-ofb-sm4",
321003a6cfb9SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
321103a6cfb9SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3212b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
321303a6cfb9SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
321403a6cfb9SPascal van Leeuwen 			.cra_blocksize = 1,
321503a6cfb9SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
321603a6cfb9SPascal van Leeuwen 			.cra_alignmask = 0,
321703a6cfb9SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ofb_cra_init,
321803a6cfb9SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
321903a6cfb9SPascal van Leeuwen 			.cra_module = THIS_MODULE,
322003a6cfb9SPascal van Leeuwen 		},
322103a6cfb9SPascal van Leeuwen 	},
322203a6cfb9SPascal van Leeuwen };
32237468ab22SPascal van Leeuwen 
32247468ab22SPascal van Leeuwen static int safexcel_skcipher_sm4_cfb_cra_init(struct crypto_tfm *tfm)
32257468ab22SPascal van Leeuwen {
32267468ab22SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
32277468ab22SPascal van Leeuwen 
32287468ab22SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
32297468ab22SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3230098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
32317468ab22SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB;
32327468ab22SPascal van Leeuwen 	return 0;
32337468ab22SPascal van Leeuwen }
32347468ab22SPascal van Leeuwen 
32357468ab22SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cfb_sm4 = {
32367468ab22SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
32377468ab22SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB,
32387468ab22SPascal van Leeuwen 	.alg.skcipher = {
32397468ab22SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
32407468ab22SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
32417468ab22SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
32427468ab22SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
32437468ab22SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
32447468ab22SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
32457468ab22SPascal van Leeuwen 		.base = {
32467468ab22SPascal van Leeuwen 			.cra_name = "cfb(sm4)",
32477468ab22SPascal van Leeuwen 			.cra_driver_name = "safexcel-cfb-sm4",
32487468ab22SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
32497468ab22SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3250b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
32517468ab22SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
32527468ab22SPascal van Leeuwen 			.cra_blocksize = 1,
32537468ab22SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
32547468ab22SPascal van Leeuwen 			.cra_alignmask = 0,
32557468ab22SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_cfb_cra_init,
32567468ab22SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
32577468ab22SPascal van Leeuwen 			.cra_module = THIS_MODULE,
32587468ab22SPascal van Leeuwen 		},
32597468ab22SPascal van Leeuwen 	},
32607468ab22SPascal van Leeuwen };
3261f77e5dc0SPascal van Leeuwen 
3262f77e5dc0SPascal van Leeuwen static int safexcel_skcipher_sm4ctr_setkey(struct crypto_skcipher *ctfm,
3263f77e5dc0SPascal van Leeuwen 					   const u8 *key, unsigned int len)
3264f77e5dc0SPascal van Leeuwen {
3265f77e5dc0SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3266f77e5dc0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3267f77e5dc0SPascal van Leeuwen 
3268f77e5dc0SPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
3269f77e5dc0SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
3270f77e5dc0SPascal van Leeuwen 	/* exclude the nonce here */
3271f77e5dc0SPascal van Leeuwen 	len -= CTR_RFC3686_NONCE_SIZE;
3272f77e5dc0SPascal van Leeuwen 
3273f77e5dc0SPascal van Leeuwen 	return safexcel_skcipher_sm4_setkey(ctfm, key, len);
3274f77e5dc0SPascal van Leeuwen }
3275f77e5dc0SPascal van Leeuwen 
3276f77e5dc0SPascal van Leeuwen static int safexcel_skcipher_sm4_ctr_cra_init(struct crypto_tfm *tfm)
3277f77e5dc0SPascal van Leeuwen {
3278f77e5dc0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3279f77e5dc0SPascal van Leeuwen 
3280f77e5dc0SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
3281f77e5dc0SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3282098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
3283f77e5dc0SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
3284f77e5dc0SPascal van Leeuwen 	return 0;
3285f77e5dc0SPascal van Leeuwen }
3286f77e5dc0SPascal van Leeuwen 
3287f77e5dc0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ctr_sm4 = {
3288f77e5dc0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
3289f77e5dc0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
3290f77e5dc0SPascal van Leeuwen 	.alg.skcipher = {
3291f77e5dc0SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4ctr_setkey,
3292f77e5dc0SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
3293f77e5dc0SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
3294f77e5dc0SPascal van Leeuwen 		/* Add nonce size */
3295f77e5dc0SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
3296f77e5dc0SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
3297f77e5dc0SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
3298f77e5dc0SPascal van Leeuwen 		.base = {
3299f77e5dc0SPascal van Leeuwen 			.cra_name = "rfc3686(ctr(sm4))",
3300f77e5dc0SPascal van Leeuwen 			.cra_driver_name = "safexcel-ctr-sm4",
3301f77e5dc0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3302f77e5dc0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3303b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3304f77e5dc0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3305f77e5dc0SPascal van Leeuwen 			.cra_blocksize = 1,
3306f77e5dc0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3307f77e5dc0SPascal van Leeuwen 			.cra_alignmask = 0,
3308f77e5dc0SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ctr_cra_init,
3309f77e5dc0SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
3310f77e5dc0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3311f77e5dc0SPascal van Leeuwen 		},
3312f77e5dc0SPascal van Leeuwen 	},
3313f77e5dc0SPascal van Leeuwen };
33141769f704SPascal van Leeuwen 
33151769f704SPascal van Leeuwen static int safexcel_aead_sm4_blk_encrypt(struct aead_request *req)
33161769f704SPascal van Leeuwen {
33171769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
33181769f704SPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
33191769f704SPascal van Leeuwen 		return -EINVAL;
33201769f704SPascal van Leeuwen 
33211769f704SPascal van Leeuwen 	return safexcel_queue_req(&req->base, aead_request_ctx(req),
33221769f704SPascal van Leeuwen 				  SAFEXCEL_ENCRYPT);
33231769f704SPascal van Leeuwen }
33241769f704SPascal van Leeuwen 
33251769f704SPascal van Leeuwen static int safexcel_aead_sm4_blk_decrypt(struct aead_request *req)
33261769f704SPascal van Leeuwen {
33271769f704SPascal van Leeuwen 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
33281769f704SPascal van Leeuwen 
33291769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
33301769f704SPascal van Leeuwen 	if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1))
33311769f704SPascal van Leeuwen 		return -EINVAL;
33321769f704SPascal van Leeuwen 
33331769f704SPascal van Leeuwen 	return safexcel_queue_req(&req->base, aead_request_ctx(req),
33341769f704SPascal van Leeuwen 				  SAFEXCEL_DECRYPT);
33351769f704SPascal van Leeuwen }
33361769f704SPascal van Leeuwen 
33371769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sha1_cra_init(struct crypto_tfm *tfm)
33381769f704SPascal van Leeuwen {
33391769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33401769f704SPascal van Leeuwen 
33411769f704SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
33421769f704SPascal van Leeuwen 	ctx->alg = SAFEXCEL_SM4;
3343098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
33441769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
33451769f704SPascal van Leeuwen 	ctx->state_sz = SHA1_DIGEST_SIZE;
33461769f704SPascal van Leeuwen 	return 0;
33471769f704SPascal van Leeuwen }
33481769f704SPascal van Leeuwen 
33491769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_sm4 = {
33501769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
33511769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1,
33521769f704SPascal van Leeuwen 	.alg.aead = {
33531769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
33541769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_sm4_blk_encrypt,
33551769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_sm4_blk_decrypt,
33561769f704SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
33571769f704SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
33581769f704SPascal van Leeuwen 		.base = {
33591769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(sm4))",
33601769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-sm4",
33611769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
33621769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3363b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
33641769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
33651769f704SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
33661769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
33671769f704SPascal van Leeuwen 			.cra_alignmask = 0,
33681769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4cbc_sha1_cra_init,
33691769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
33701769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
33711769f704SPascal van Leeuwen 		},
33721769f704SPascal van Leeuwen 	},
33731769f704SPascal van Leeuwen };
33741769f704SPascal van Leeuwen 
33751769f704SPascal van Leeuwen static int safexcel_aead_fallback_setkey(struct crypto_aead *ctfm,
33761769f704SPascal van Leeuwen 					 const u8 *key, unsigned int len)
33771769f704SPascal van Leeuwen {
33781769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
33791769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33801769f704SPascal van Leeuwen 
33811769f704SPascal van Leeuwen 	/* Keep fallback cipher synchronized */
33821769f704SPascal van Leeuwen 	return crypto_aead_setkey(ctx->fback, (u8 *)key, len) ?:
33831769f704SPascal van Leeuwen 	       safexcel_aead_setkey(ctfm, key, len);
33841769f704SPascal van Leeuwen }
33851769f704SPascal van Leeuwen 
33861769f704SPascal van Leeuwen static int safexcel_aead_fallback_setauthsize(struct crypto_aead *ctfm,
33871769f704SPascal van Leeuwen 					      unsigned int authsize)
33881769f704SPascal van Leeuwen {
33891769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
33901769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33911769f704SPascal van Leeuwen 
33921769f704SPascal van Leeuwen 	/* Keep fallback cipher synchronized */
33931769f704SPascal van Leeuwen 	return crypto_aead_setauthsize(ctx->fback, authsize);
33941769f704SPascal van Leeuwen }
33951769f704SPascal van Leeuwen 
33961769f704SPascal van Leeuwen static int safexcel_aead_fallback_crypt(struct aead_request *req,
33971769f704SPascal van Leeuwen 					enum safexcel_cipher_direction dir)
33981769f704SPascal van Leeuwen {
33991769f704SPascal van Leeuwen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
34001769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
34011769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34021769f704SPascal van Leeuwen 	struct aead_request *subreq = aead_request_ctx(req);
34031769f704SPascal van Leeuwen 
34041769f704SPascal van Leeuwen 	aead_request_set_tfm(subreq, ctx->fback);
34051769f704SPascal van Leeuwen 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
34061769f704SPascal van Leeuwen 				  req->base.data);
34071769f704SPascal van Leeuwen 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
34081769f704SPascal van Leeuwen 			       req->iv);
34091769f704SPascal van Leeuwen 	aead_request_set_ad(subreq, req->assoclen);
34101769f704SPascal van Leeuwen 
34111769f704SPascal van Leeuwen 	return (dir ==  SAFEXCEL_ENCRYPT) ?
34121769f704SPascal van Leeuwen 		crypto_aead_encrypt(subreq) :
34131769f704SPascal van Leeuwen 		crypto_aead_decrypt(subreq);
34141769f704SPascal van Leeuwen }
34151769f704SPascal van Leeuwen 
34161769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_encrypt(struct aead_request *req)
34171769f704SPascal van Leeuwen {
34181769f704SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
34191769f704SPascal van Leeuwen 
34201769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
34211769f704SPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
34221769f704SPascal van Leeuwen 		return -EINVAL;
34231769f704SPascal van Leeuwen 	else if (req->cryptlen || req->assoclen) /* If input length > 0 only */
34241769f704SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
34251769f704SPascal van Leeuwen 
34261769f704SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
34271769f704SPascal van Leeuwen 	return safexcel_aead_fallback_crypt(req, SAFEXCEL_ENCRYPT);
34281769f704SPascal van Leeuwen }
34291769f704SPascal van Leeuwen 
34301769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_decrypt(struct aead_request *req)
34311769f704SPascal van Leeuwen {
34321769f704SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
34331769f704SPascal van Leeuwen 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
34341769f704SPascal van Leeuwen 
34351769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
34361769f704SPascal van Leeuwen 	if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1))
34371769f704SPascal van Leeuwen 		return -EINVAL;
34381769f704SPascal van Leeuwen 	else if (req->cryptlen > crypto_aead_authsize(tfm) || req->assoclen)
34391769f704SPascal van Leeuwen 		/* If input length > 0 only */
34401769f704SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
34411769f704SPascal van Leeuwen 
34421769f704SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
34431769f704SPascal van Leeuwen 	return safexcel_aead_fallback_crypt(req, SAFEXCEL_DECRYPT);
34441769f704SPascal van Leeuwen }
34451769f704SPascal van Leeuwen 
34461769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_cra_init(struct crypto_tfm *tfm)
34471769f704SPascal van Leeuwen {
34481769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34491769f704SPascal van Leeuwen 
34501769f704SPascal van Leeuwen 	safexcel_aead_fallback_cra_init(tfm);
34511769f704SPascal van Leeuwen 	ctx->alg = SAFEXCEL_SM4;
3452098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
34531769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
34541769f704SPascal van Leeuwen 	ctx->state_sz = SM3_DIGEST_SIZE;
34551769f704SPascal van Leeuwen 	return 0;
34561769f704SPascal van Leeuwen }
34571769f704SPascal van Leeuwen 
34581769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_cbc_sm4 = {
34591769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
34601769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3,
34611769f704SPascal van Leeuwen 	.alg.aead = {
34621769f704SPascal van Leeuwen 		.setkey = safexcel_aead_fallback_setkey,
34631769f704SPascal van Leeuwen 		.setauthsize = safexcel_aead_fallback_setauthsize,
34641769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_sm4cbc_sm3_encrypt,
34651769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_sm4cbc_sm3_decrypt,
34661769f704SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
34671769f704SPascal van Leeuwen 		.maxauthsize = SM3_DIGEST_SIZE,
34681769f704SPascal van Leeuwen 		.base = {
34691769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sm3),cbc(sm4))",
34701769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sm3-cbc-sm4",
34711769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
34721769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3473b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
34741769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
34751769f704SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
34761769f704SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
34771769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
34781769f704SPascal van Leeuwen 			.cra_alignmask = 0,
34791769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4cbc_sm3_cra_init,
34801769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
34811769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
34821769f704SPascal van Leeuwen 		},
34831769f704SPascal van Leeuwen 	},
34841769f704SPascal van Leeuwen };
34851769f704SPascal van Leeuwen 
34861769f704SPascal van Leeuwen static int safexcel_aead_sm4ctr_sha1_cra_init(struct crypto_tfm *tfm)
34871769f704SPascal van Leeuwen {
34881769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34891769f704SPascal van Leeuwen 
34901769f704SPascal van Leeuwen 	safexcel_aead_sm4cbc_sha1_cra_init(tfm);
34911769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
34921769f704SPascal van Leeuwen 	return 0;
34931769f704SPascal van Leeuwen }
34941769f704SPascal van Leeuwen 
34951769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_sm4 = {
34961769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
34971769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1,
34981769f704SPascal van Leeuwen 	.alg.aead = {
34991769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
35001769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
35011769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
35021769f704SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
35031769f704SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
35041769f704SPascal van Leeuwen 		.base = {
35051769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),rfc3686(ctr(sm4)))",
35061769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-sm4",
35071769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
35081769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3509b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
35101769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
35111769f704SPascal van Leeuwen 			.cra_blocksize = 1,
35121769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
35131769f704SPascal van Leeuwen 			.cra_alignmask = 0,
35141769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4ctr_sha1_cra_init,
35151769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
35161769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
35171769f704SPascal van Leeuwen 		},
35181769f704SPascal van Leeuwen 	},
35191769f704SPascal van Leeuwen };
35201769f704SPascal van Leeuwen 
35211769f704SPascal van Leeuwen static int safexcel_aead_sm4ctr_sm3_cra_init(struct crypto_tfm *tfm)
35221769f704SPascal van Leeuwen {
35231769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
35241769f704SPascal van Leeuwen 
35251769f704SPascal van Leeuwen 	safexcel_aead_sm4cbc_sm3_cra_init(tfm);
35261769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
35271769f704SPascal van Leeuwen 	return 0;
35281769f704SPascal van Leeuwen }
35291769f704SPascal van Leeuwen 
35301769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_ctr_sm4 = {
35311769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
35321769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3,
35331769f704SPascal van Leeuwen 	.alg.aead = {
35341769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
35351769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
35361769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
35371769f704SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
35381769f704SPascal van Leeuwen 		.maxauthsize = SM3_DIGEST_SIZE,
35391769f704SPascal van Leeuwen 		.base = {
35401769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sm3),rfc3686(ctr(sm4)))",
35411769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sm3-ctr-sm4",
35421769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
35431769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3544b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
35451769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
35461769f704SPascal van Leeuwen 			.cra_blocksize = 1,
35471769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
35481769f704SPascal van Leeuwen 			.cra_alignmask = 0,
35491769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4ctr_sm3_cra_init,
35501769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
35511769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
35521769f704SPascal van Leeuwen 		},
35531769f704SPascal van Leeuwen 	},
35541769f704SPascal van Leeuwen };
3555a19052d4SPascal van Leeuwen 
3556a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_setkey(struct crypto_aead *ctfm, const u8 *key,
3557a19052d4SPascal van Leeuwen 				       unsigned int len)
3558a19052d4SPascal van Leeuwen {
3559a19052d4SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
3560a19052d4SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3561a19052d4SPascal van Leeuwen 
3562a19052d4SPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
3563a19052d4SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
3564a19052d4SPascal van Leeuwen 
3565a19052d4SPascal van Leeuwen 	len -= CTR_RFC3686_NONCE_SIZE;
3566a19052d4SPascal van Leeuwen 	return safexcel_aead_gcm_setkey(ctfm, key, len);
3567a19052d4SPascal van Leeuwen }
3568a19052d4SPascal van Leeuwen 
3569a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_setauthsize(struct crypto_aead *tfm,
3570a19052d4SPascal van Leeuwen 					    unsigned int authsize)
3571a19052d4SPascal van Leeuwen {
3572a19052d4SPascal van Leeuwen 	return crypto_rfc4106_check_authsize(authsize);
3573a19052d4SPascal van Leeuwen }
3574a19052d4SPascal van Leeuwen 
3575a19052d4SPascal van Leeuwen static int safexcel_rfc4106_encrypt(struct aead_request *req)
3576a19052d4SPascal van Leeuwen {
3577a19052d4SPascal van Leeuwen 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
3578a19052d4SPascal van Leeuwen 	       safexcel_aead_encrypt(req);
3579a19052d4SPascal van Leeuwen }
3580a19052d4SPascal van Leeuwen 
3581a19052d4SPascal van Leeuwen static int safexcel_rfc4106_decrypt(struct aead_request *req)
3582a19052d4SPascal van Leeuwen {
3583a19052d4SPascal van Leeuwen 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
3584a19052d4SPascal van Leeuwen 	       safexcel_aead_decrypt(req);
3585a19052d4SPascal van Leeuwen }
3586a19052d4SPascal van Leeuwen 
3587a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_cra_init(struct crypto_tfm *tfm)
3588a19052d4SPascal van Leeuwen {
3589a19052d4SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3590a19052d4SPascal van Leeuwen 	int ret;
3591a19052d4SPascal van Leeuwen 
3592a19052d4SPascal van Leeuwen 	ret = safexcel_aead_gcm_cra_init(tfm);
3593a19052d4SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3594098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3595a19052d4SPascal van Leeuwen 	return ret;
3596a19052d4SPascal van Leeuwen }
3597a19052d4SPascal van Leeuwen 
3598a19052d4SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4106_gcm = {
3599a19052d4SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3600a19052d4SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
3601a19052d4SPascal van Leeuwen 	.alg.aead = {
3602a19052d4SPascal van Leeuwen 		.setkey = safexcel_rfc4106_gcm_setkey,
3603a19052d4SPascal van Leeuwen 		.setauthsize = safexcel_rfc4106_gcm_setauthsize,
3604a19052d4SPascal van Leeuwen 		.encrypt = safexcel_rfc4106_encrypt,
3605a19052d4SPascal van Leeuwen 		.decrypt = safexcel_rfc4106_decrypt,
3606a19052d4SPascal van Leeuwen 		.ivsize = GCM_RFC4106_IV_SIZE,
3607a19052d4SPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
3608a19052d4SPascal van Leeuwen 		.base = {
3609a19052d4SPascal van Leeuwen 			.cra_name = "rfc4106(gcm(aes))",
3610a19052d4SPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4106-gcm-aes",
3611a19052d4SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3612a19052d4SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3613b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3614a19052d4SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3615a19052d4SPascal van Leeuwen 			.cra_blocksize = 1,
3616a19052d4SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3617a19052d4SPascal van Leeuwen 			.cra_alignmask = 0,
3618a19052d4SPascal van Leeuwen 			.cra_init = safexcel_rfc4106_gcm_cra_init,
3619a19052d4SPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
3620a19052d4SPascal van Leeuwen 		},
3621a19052d4SPascal van Leeuwen 	},
3622a19052d4SPascal van Leeuwen };
362392c60cefSPascal van Leeuwen 
362492c60cefSPascal van Leeuwen static int safexcel_rfc4543_gcm_setauthsize(struct crypto_aead *tfm,
362592c60cefSPascal van Leeuwen 					    unsigned int authsize)
362692c60cefSPascal van Leeuwen {
362792c60cefSPascal van Leeuwen 	if (authsize != GHASH_DIGEST_SIZE)
362892c60cefSPascal van Leeuwen 		return -EINVAL;
362992c60cefSPascal van Leeuwen 
363092c60cefSPascal van Leeuwen 	return 0;
363192c60cefSPascal van Leeuwen }
363292c60cefSPascal van Leeuwen 
363392c60cefSPascal van Leeuwen static int safexcel_rfc4543_gcm_cra_init(struct crypto_tfm *tfm)
363492c60cefSPascal van Leeuwen {
363592c60cefSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
363692c60cefSPascal van Leeuwen 	int ret;
363792c60cefSPascal van Leeuwen 
363892c60cefSPascal van Leeuwen 	ret = safexcel_aead_gcm_cra_init(tfm);
363992c60cefSPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP_GMAC;
364092c60cefSPascal van Leeuwen 	return ret;
364192c60cefSPascal van Leeuwen }
364292c60cefSPascal van Leeuwen 
364392c60cefSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4543_gcm = {
364492c60cefSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
364592c60cefSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
364692c60cefSPascal van Leeuwen 	.alg.aead = {
364792c60cefSPascal van Leeuwen 		.setkey = safexcel_rfc4106_gcm_setkey,
364892c60cefSPascal van Leeuwen 		.setauthsize = safexcel_rfc4543_gcm_setauthsize,
364992c60cefSPascal van Leeuwen 		.encrypt = safexcel_rfc4106_encrypt,
365092c60cefSPascal van Leeuwen 		.decrypt = safexcel_rfc4106_decrypt,
365192c60cefSPascal van Leeuwen 		.ivsize = GCM_RFC4543_IV_SIZE,
365292c60cefSPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
365392c60cefSPascal van Leeuwen 		.base = {
365492c60cefSPascal van Leeuwen 			.cra_name = "rfc4543(gcm(aes))",
365592c60cefSPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4543-gcm-aes",
365692c60cefSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
365792c60cefSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3658b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
365992c60cefSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
366092c60cefSPascal van Leeuwen 			.cra_blocksize = 1,
366192c60cefSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
366292c60cefSPascal van Leeuwen 			.cra_alignmask = 0,
366392c60cefSPascal van Leeuwen 			.cra_init = safexcel_rfc4543_gcm_cra_init,
366492c60cefSPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
366592c60cefSPascal van Leeuwen 		},
366692c60cefSPascal van Leeuwen 	},
366792c60cefSPascal van Leeuwen };
3668a9a89624SPascal van Leeuwen 
3669a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_setkey(struct crypto_aead *ctfm, const u8 *key,
3670a9a89624SPascal van Leeuwen 				       unsigned int len)
3671a9a89624SPascal van Leeuwen {
3672a9a89624SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
3673a9a89624SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3674a9a89624SPascal van Leeuwen 
3675a9a89624SPascal van Leeuwen 	/* First byte of the nonce = L = always 3 for RFC4309 (4 byte ctr) */
3676a9a89624SPascal van Leeuwen 	*(u8 *)&ctx->nonce = EIP197_AEAD_IPSEC_COUNTER_SIZE - 1;
3677a9a89624SPascal van Leeuwen 	/* last 3 bytes of key are the nonce! */
3678a9a89624SPascal van Leeuwen 	memcpy((u8 *)&ctx->nonce + 1, key + len -
3679a9a89624SPascal van Leeuwen 	       EIP197_AEAD_IPSEC_CCM_NONCE_SIZE,
3680a9a89624SPascal van Leeuwen 	       EIP197_AEAD_IPSEC_CCM_NONCE_SIZE);
3681a9a89624SPascal van Leeuwen 
3682a9a89624SPascal van Leeuwen 	len -= EIP197_AEAD_IPSEC_CCM_NONCE_SIZE;
3683a9a89624SPascal van Leeuwen 	return safexcel_aead_ccm_setkey(ctfm, key, len);
3684a9a89624SPascal van Leeuwen }
3685a9a89624SPascal van Leeuwen 
3686a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_setauthsize(struct crypto_aead *tfm,
3687a9a89624SPascal van Leeuwen 					    unsigned int authsize)
3688a9a89624SPascal van Leeuwen {
3689a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3690a9a89624SPascal van Leeuwen 	switch (authsize) {
3691a9a89624SPascal van Leeuwen 	case 8:
3692a9a89624SPascal van Leeuwen 	case 12:
3693a9a89624SPascal van Leeuwen 	case 16:
3694a9a89624SPascal van Leeuwen 		break;
3695a9a89624SPascal van Leeuwen 	default:
3696a9a89624SPascal van Leeuwen 		return -EINVAL;
3697a9a89624SPascal van Leeuwen 	}
3698a9a89624SPascal van Leeuwen 
3699a9a89624SPascal van Leeuwen 	return 0;
3700a9a89624SPascal van Leeuwen }
3701a9a89624SPascal van Leeuwen 
3702a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_encrypt(struct aead_request *req)
3703a9a89624SPascal van Leeuwen {
3704a9a89624SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
3705a9a89624SPascal van Leeuwen 
3706a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3707a9a89624SPascal van Leeuwen 	if (req->assoclen != 16 && req->assoclen != 20)
3708a9a89624SPascal van Leeuwen 		return -EINVAL;
3709a9a89624SPascal van Leeuwen 
3710a9a89624SPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
3711a9a89624SPascal van Leeuwen }
3712a9a89624SPascal van Leeuwen 
3713a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_decrypt(struct aead_request *req)
3714a9a89624SPascal van Leeuwen {
3715a9a89624SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
3716a9a89624SPascal van Leeuwen 
3717a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3718a9a89624SPascal van Leeuwen 	if (req->assoclen != 16 && req->assoclen != 20)
3719a9a89624SPascal van Leeuwen 		return -EINVAL;
3720a9a89624SPascal van Leeuwen 
3721a9a89624SPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
3722a9a89624SPascal van Leeuwen }
3723a9a89624SPascal van Leeuwen 
3724a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_cra_init(struct crypto_tfm *tfm)
3725a9a89624SPascal van Leeuwen {
3726a9a89624SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3727a9a89624SPascal van Leeuwen 	int ret;
3728a9a89624SPascal van Leeuwen 
3729a9a89624SPascal van Leeuwen 	ret = safexcel_aead_ccm_cra_init(tfm);
3730a9a89624SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3731098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3732a9a89624SPascal van Leeuwen 	return ret;
3733a9a89624SPascal van Leeuwen }
3734a9a89624SPascal van Leeuwen 
3735a9a89624SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4309_ccm = {
3736a9a89624SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3737a9a89624SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL,
3738a9a89624SPascal van Leeuwen 	.alg.aead = {
3739a9a89624SPascal van Leeuwen 		.setkey = safexcel_rfc4309_ccm_setkey,
3740a9a89624SPascal van Leeuwen 		.setauthsize = safexcel_rfc4309_ccm_setauthsize,
3741a9a89624SPascal van Leeuwen 		.encrypt = safexcel_rfc4309_ccm_encrypt,
3742a9a89624SPascal van Leeuwen 		.decrypt = safexcel_rfc4309_ccm_decrypt,
3743a9a89624SPascal van Leeuwen 		.ivsize = EIP197_AEAD_IPSEC_IV_SIZE,
3744a9a89624SPascal van Leeuwen 		.maxauthsize = AES_BLOCK_SIZE,
3745a9a89624SPascal van Leeuwen 		.base = {
3746a9a89624SPascal van Leeuwen 			.cra_name = "rfc4309(ccm(aes))",
3747a9a89624SPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4309-ccm-aes",
3748a9a89624SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3749a9a89624SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3750b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3751a9a89624SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3752a9a89624SPascal van Leeuwen 			.cra_blocksize = 1,
3753a9a89624SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3754a9a89624SPascal van Leeuwen 			.cra_alignmask = 0,
3755a9a89624SPascal van Leeuwen 			.cra_init = safexcel_rfc4309_ccm_cra_init,
3756a9a89624SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
3757a9a89624SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3758a9a89624SPascal van Leeuwen 		},
3759a9a89624SPascal van Leeuwen 	},
3760a9a89624SPascal van Leeuwen };
3761