1301422e3SAntoine Tenart // SPDX-License-Identifier: GPL-2.0
21b44c5a6SAntoine Ténart /*
31b44c5a6SAntoine Ténart  * Copyright (C) 2017 Marvell
41b44c5a6SAntoine Ténart  *
51b44c5a6SAntoine Ténart  * Antoine Tenart <antoine.tenart@free-electrons.com>
61b44c5a6SAntoine Ténart  */
71b44c5a6SAntoine Ténart 
84a593fb3SPascal van Leeuwen #include <asm/unaligned.h>
91b44c5a6SAntoine Ténart #include <linux/device.h>
101b44c5a6SAntoine Ténart #include <linux/dma-mapping.h>
111b44c5a6SAntoine Ténart #include <linux/dmapool.h>
12f6beaea3SAntoine Tenart #include <crypto/aead.h>
131b44c5a6SAntoine Ténart #include <crypto/aes.h>
14f6beaea3SAntoine Tenart #include <crypto/authenc.h>
154a593fb3SPascal van Leeuwen #include <crypto/chacha.h>
16f26882a3SPascal van Leeuwen #include <crypto/ctr.h>
1704007b0eSArd Biesheuvel #include <crypto/internal/des.h>
183e450886SPascal van Leeuwen #include <crypto/gcm.h>
193e450886SPascal van Leeuwen #include <crypto/ghash.h>
20a6061921SPascal van Leeuwen #include <crypto/poly1305.h>
21f6beaea3SAntoine Tenart #include <crypto/sha.h>
221769f704SPascal van Leeuwen #include <crypto/sm3.h>
23fcca797dSPascal van Leeuwen #include <crypto/sm4.h>
24c7da38a7SPascal van Leeuwen #include <crypto/xts.h>
251b44c5a6SAntoine Ténart #include <crypto/skcipher.h>
26f6beaea3SAntoine Tenart #include <crypto/internal/aead.h>
271eb7b403SOfer Heifetz #include <crypto/internal/skcipher.h>
281b44c5a6SAntoine Ténart 
291b44c5a6SAntoine Ténart #include "safexcel.h"
301b44c5a6SAntoine Ténart 
311b44c5a6SAntoine Ténart enum safexcel_cipher_direction {
321b44c5a6SAntoine Ténart 	SAFEXCEL_ENCRYPT,
331b44c5a6SAntoine Ténart 	SAFEXCEL_DECRYPT,
341b44c5a6SAntoine Ténart };
351b44c5a6SAntoine Ténart 
36a7dea8c0SOfer Heifetz enum safexcel_cipher_alg {
37a7dea8c0SOfer Heifetz 	SAFEXCEL_DES,
3862469879SOfer Heifetz 	SAFEXCEL_3DES,
39a7dea8c0SOfer Heifetz 	SAFEXCEL_AES,
404a593fb3SPascal van Leeuwen 	SAFEXCEL_CHACHA20,
41fcca797dSPascal van Leeuwen 	SAFEXCEL_SM4,
42a7dea8c0SOfer Heifetz };
43a7dea8c0SOfer Heifetz 
441b44c5a6SAntoine Ténart struct safexcel_cipher_ctx {
451b44c5a6SAntoine Ténart 	struct safexcel_context base;
461b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv;
471b44c5a6SAntoine Ténart 
481b44c5a6SAntoine Ténart 	u32 mode;
49a7dea8c0SOfer Heifetz 	enum safexcel_cipher_alg alg;
50098e51e5SPascal van Leeuwen 	u8 aead; /* !=0=AEAD, 2=IPSec ESP AEAD, 3=IPsec ESP GMAC */
51098e51e5SPascal van Leeuwen 	u8 xcm;  /* 0=authenc, 1=GCM, 2 reserved for CCM */
52098e51e5SPascal van Leeuwen 	u8 aadskip;
53098e51e5SPascal van Leeuwen 	u8 blocksz;
54098e51e5SPascal van Leeuwen 	u32 ivmask;
55098e51e5SPascal van Leeuwen 	u32 ctrinit;
561b44c5a6SAntoine Ténart 
57c7da38a7SPascal van Leeuwen 	__le32 key[16];
5854f9e8faSPascal van Leeuwen 	u32 nonce;
59c7da38a7SPascal van Leeuwen 	unsigned int key_len, xts;
60f6beaea3SAntoine Tenart 
61f6beaea3SAntoine Tenart 	/* All the below is AEAD specific */
62a7dea8c0SOfer Heifetz 	u32 hash_alg;
63f6beaea3SAntoine Tenart 	u32 state_sz;
643e450886SPascal van Leeuwen 
653e450886SPascal van Leeuwen 	struct crypto_cipher *hkaes;
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) {
64419b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL);
6451b44c5a6SAntoine Ténart 	} else {
64619b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE);
64719b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE);
6481b44c5a6SAntoine Ténart 	}
6491b44c5a6SAntoine Ténart 
6505bdb6e6aSPascal van Leeuwen 	/*
6515bdb6e6aSPascal van Leeuwen 	 * Update IV in req from last crypto output word for CBC modes
6525bdb6e6aSPascal van Leeuwen 	 */
6535bdb6e6aSPascal van Leeuwen 	if ((!ctx->aead) && (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) &&
6545bdb6e6aSPascal van Leeuwen 	    (sreq->direction == SAFEXCEL_ENCRYPT)) {
6555bdb6e6aSPascal van Leeuwen 		/* For encrypt take the last output word */
65619b347b3SPascal van Leeuwen 		sg_pcopy_to_buffer(dst, sreq->nr_dst, areq->iv,
6575bdb6e6aSPascal van Leeuwen 				   crypto_skcipher_ivsize(skcipher),
6585bdb6e6aSPascal van Leeuwen 				   (cryptlen -
6595bdb6e6aSPascal van Leeuwen 				    crypto_skcipher_ivsize(skcipher)));
6605bdb6e6aSPascal van Leeuwen 	}
6615bdb6e6aSPascal van Leeuwen 
6621b44c5a6SAntoine Ténart 	*should_complete = true;
6631b44c5a6SAntoine Ténart 
6641b44c5a6SAntoine Ténart 	return ndesc;
6651b44c5a6SAntoine Ténart }
6661b44c5a6SAntoine Ténart 
667a7dea8c0SOfer Heifetz static int safexcel_send_req(struct crypto_async_request *base, int ring,
6688ac1283eSAntoine Tenart 			     struct safexcel_cipher_req *sreq,
6698ac1283eSAntoine Tenart 			     struct scatterlist *src, struct scatterlist *dst,
670f6beaea3SAntoine Tenart 			     unsigned int cryptlen, unsigned int assoclen,
671f6beaea3SAntoine Tenart 			     unsigned int digestsize, u8 *iv, int *commands,
6728ac1283eSAntoine Tenart 			     int *results)
6731b44c5a6SAntoine Ténart {
6745bdb6e6aSPascal van Leeuwen 	struct skcipher_request *areq = skcipher_request_cast(base);
6755bdb6e6aSPascal van Leeuwen 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq);
6768ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
67718e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
6781b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc;
67919b347b3SPascal van Leeuwen 	struct safexcel_command_desc *first_cdesc = NULL;
680e5c8ee1fSAntoine Tenart 	struct safexcel_result_desc *rdesc, *first_rdesc = NULL;
6811b44c5a6SAntoine Ténart 	struct scatterlist *sg;
68219b347b3SPascal van Leeuwen 	unsigned int totlen;
68319b347b3SPascal van Leeuwen 	unsigned int totlen_src = cryptlen + assoclen;
68419b347b3SPascal van Leeuwen 	unsigned int totlen_dst = totlen_src;
685098e51e5SPascal van Leeuwen 	struct safexcel_token *atoken;
68619b347b3SPascal van Leeuwen 	int n_cdesc = 0, n_rdesc = 0;
68719b347b3SPascal van Leeuwen 	int queued, i, ret = 0;
68819b347b3SPascal van Leeuwen 	bool first = true;
6891b44c5a6SAntoine Ténart 
69019b347b3SPascal van Leeuwen 	sreq->nr_src = sg_nents_for_len(src, totlen_src);
69119b347b3SPascal van Leeuwen 
69219b347b3SPascal van Leeuwen 	if (ctx->aead) {
69319b347b3SPascal van Leeuwen 		/*
69419b347b3SPascal van Leeuwen 		 * AEAD has auth tag appended to output for encrypt and
69519b347b3SPascal van Leeuwen 		 * removed from the output for decrypt!
69619b347b3SPascal van Leeuwen 		 */
69719b347b3SPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_DECRYPT)
69819b347b3SPascal van Leeuwen 			totlen_dst -= digestsize;
69919b347b3SPascal van Leeuwen 		else
70019b347b3SPascal van Leeuwen 			totlen_dst += digestsize;
70119b347b3SPascal van Leeuwen 
70219b347b3SPascal van Leeuwen 		memcpy(ctx->base.ctxr->data + ctx->key_len / sizeof(u32),
70378cf1c8bSHerbert Xu 		       &ctx->base.ipad, ctx->state_sz);
7043e450886SPascal van Leeuwen 		if (!ctx->xcm)
7053e450886SPascal van Leeuwen 			memcpy(ctx->base.ctxr->data + (ctx->key_len +
70678cf1c8bSHerbert Xu 			       ctx->state_sz) / sizeof(u32), &ctx->base.opad,
7073e450886SPascal van Leeuwen 			       ctx->state_sz);
70819b347b3SPascal van Leeuwen 	} else if ((ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) &&
7095bdb6e6aSPascal van Leeuwen 		   (sreq->direction == SAFEXCEL_DECRYPT)) {
7105bdb6e6aSPascal van Leeuwen 		/*
7115bdb6e6aSPascal van Leeuwen 		 * Save IV from last crypto input word for CBC modes in decrypt
7125bdb6e6aSPascal van Leeuwen 		 * direction. Need to do this first in case of inplace operation
7135bdb6e6aSPascal van Leeuwen 		 * as it will be overwritten.
7145bdb6e6aSPascal van Leeuwen 		 */
71519b347b3SPascal van Leeuwen 		sg_pcopy_to_buffer(src, sreq->nr_src, areq->iv,
7165bdb6e6aSPascal van Leeuwen 				   crypto_skcipher_ivsize(skcipher),
71719b347b3SPascal van Leeuwen 				   (totlen_src -
7185bdb6e6aSPascal van Leeuwen 				    crypto_skcipher_ivsize(skcipher)));
7195bdb6e6aSPascal van Leeuwen 	}
7205bdb6e6aSPascal van Leeuwen 
72119b347b3SPascal van Leeuwen 	sreq->nr_dst = sg_nents_for_len(dst, totlen_dst);
7221b44c5a6SAntoine Ténart 
72319b347b3SPascal van Leeuwen 	/*
72419b347b3SPascal van Leeuwen 	 * Remember actual input length, source buffer length may be
72519b347b3SPascal van Leeuwen 	 * updated in case of inline operation below.
72619b347b3SPascal van Leeuwen 	 */
72719b347b3SPascal van Leeuwen 	totlen = totlen_src;
72819b347b3SPascal van Leeuwen 	queued = totlen_src;
72919b347b3SPascal van Leeuwen 
73019b347b3SPascal van Leeuwen 	if (src == dst) {
73119b347b3SPascal van Leeuwen 		sreq->nr_src = max(sreq->nr_src, sreq->nr_dst);
73219b347b3SPascal van Leeuwen 		sreq->nr_dst = sreq->nr_src;
73319b347b3SPascal van Leeuwen 		if (unlikely((totlen_src || totlen_dst) &&
73419b347b3SPascal van Leeuwen 		    (sreq->nr_src <= 0))) {
73519b347b3SPascal van Leeuwen 			dev_err(priv->dev, "In-place buffer not large enough (need %d bytes)!",
73619b347b3SPascal van Leeuwen 				max(totlen_src, totlen_dst));
7371b44c5a6SAntoine Ténart 			return -EINVAL;
7381b44c5a6SAntoine Ténart 		}
73919b347b3SPascal van Leeuwen 		dma_map_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL);
74019b347b3SPascal van Leeuwen 	} else {
74119b347b3SPascal van Leeuwen 		if (unlikely(totlen_src && (sreq->nr_src <= 0))) {
74219b347b3SPascal van Leeuwen 			dev_err(priv->dev, "Source buffer not large enough (need %d bytes)!",
74319b347b3SPascal van Leeuwen 				totlen_src);
74419b347b3SPascal van Leeuwen 			return -EINVAL;
74519b347b3SPascal van Leeuwen 		}
74619b347b3SPascal van Leeuwen 		dma_map_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE);
74719b347b3SPascal van Leeuwen 
74819b347b3SPascal van Leeuwen 		if (unlikely(totlen_dst && (sreq->nr_dst <= 0))) {
74919b347b3SPascal van Leeuwen 			dev_err(priv->dev, "Dest buffer not large enough (need %d bytes)!",
75019b347b3SPascal van Leeuwen 				totlen_dst);
75119b347b3SPascal van Leeuwen 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
75219b347b3SPascal van Leeuwen 				     DMA_TO_DEVICE);
75319b347b3SPascal van Leeuwen 			return -EINVAL;
75419b347b3SPascal van Leeuwen 		}
75519b347b3SPascal van Leeuwen 		dma_map_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE);
7561b44c5a6SAntoine Ténart 	}
7571b44c5a6SAntoine Ténart 
7581b44c5a6SAntoine Ténart 	memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len);
7591b44c5a6SAntoine Ténart 
760cb97aa94SPascal van Leeuwen 	if (!totlen) {
761cb97aa94SPascal van Leeuwen 		/*
762cb97aa94SPascal van Leeuwen 		 * The EIP97 cannot deal with zero length input packets!
763cb97aa94SPascal van Leeuwen 		 * So stuff a dummy command descriptor indicating a 1 byte
764cb97aa94SPascal van Leeuwen 		 * (dummy) input packet, using the context record as source.
765cb97aa94SPascal van Leeuwen 		 */
766cb97aa94SPascal van Leeuwen 		first_cdesc = safexcel_add_cdesc(priv, ring,
767cb97aa94SPascal van Leeuwen 						 1, 1, ctx->base.ctxr_dma,
768cb97aa94SPascal van Leeuwen 						 1, 1, ctx->base.ctxr_dma,
769cb97aa94SPascal van Leeuwen 						 &atoken);
770cb97aa94SPascal van Leeuwen 		if (IS_ERR(first_cdesc)) {
771cb97aa94SPascal van Leeuwen 			/* No space left in the command descriptor ring */
772cb97aa94SPascal van Leeuwen 			ret = PTR_ERR(first_cdesc);
773cb97aa94SPascal van Leeuwen 			goto cdesc_rollback;
774cb97aa94SPascal van Leeuwen 		}
775cb97aa94SPascal van Leeuwen 		n_cdesc = 1;
776cb97aa94SPascal van Leeuwen 		goto skip_cdesc;
777cb97aa94SPascal van Leeuwen 	}
778f6beaea3SAntoine Tenart 
7791b44c5a6SAntoine Ténart 	/* command descriptors */
78019b347b3SPascal van Leeuwen 	for_each_sg(src, sg, sreq->nr_src, i) {
7811b44c5a6SAntoine Ténart 		int len = sg_dma_len(sg);
7821b44c5a6SAntoine Ténart 
7831b44c5a6SAntoine Ténart 		/* Do not overflow the request */
784cb97aa94SPascal van Leeuwen 		if (queued < len)
7851b44c5a6SAntoine Ténart 			len = queued;
7861b44c5a6SAntoine Ténart 
78719b347b3SPascal van Leeuwen 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
78819b347b3SPascal van Leeuwen 					   !(queued - len),
789f6beaea3SAntoine Tenart 					   sg_dma_address(sg), len, totlen,
790098e51e5SPascal van Leeuwen 					   ctx->base.ctxr_dma, &atoken);
7911b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
7921b44c5a6SAntoine Ténart 			/* No space left in the command descriptor ring */
7931b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
7941b44c5a6SAntoine Ténart 			goto cdesc_rollback;
7951b44c5a6SAntoine Ténart 		}
7961b44c5a6SAntoine Ténart 
797cb97aa94SPascal van Leeuwen 		if (!n_cdesc)
79819b347b3SPascal van Leeuwen 			first_cdesc = cdesc;
7991b44c5a6SAntoine Ténart 
800cb97aa94SPascal van Leeuwen 		n_cdesc++;
8011b44c5a6SAntoine Ténart 		queued -= len;
8021b44c5a6SAntoine Ténart 		if (!queued)
8031b44c5a6SAntoine Ténart 			break;
8041b44c5a6SAntoine Ténart 	}
805cb97aa94SPascal van Leeuwen skip_cdesc:
80619b347b3SPascal van Leeuwen 	/* Add context control words and token to first command descriptor */
80719b347b3SPascal van Leeuwen 	safexcel_context_control(ctx, base, sreq, first_cdesc);
80819b347b3SPascal van Leeuwen 	if (ctx->aead)
809098e51e5SPascal van Leeuwen 		safexcel_aead_token(ctx, iv, first_cdesc, atoken,
81019b347b3SPascal van Leeuwen 				    sreq->direction, cryptlen,
81119b347b3SPascal van Leeuwen 				    assoclen, digestsize);
81219b347b3SPascal van Leeuwen 	else
813098e51e5SPascal van Leeuwen 		safexcel_skcipher_token(ctx, iv, first_cdesc, atoken,
81419b347b3SPascal van Leeuwen 					cryptlen);
81519b347b3SPascal van Leeuwen 
8161b44c5a6SAntoine Ténart 	/* result descriptors */
81719b347b3SPascal van Leeuwen 	for_each_sg(dst, sg, sreq->nr_dst, i) {
81819b347b3SPascal van Leeuwen 		bool last = (i == sreq->nr_dst - 1);
8191b44c5a6SAntoine Ténart 		u32 len = sg_dma_len(sg);
8201b44c5a6SAntoine Ténart 
82119b347b3SPascal van Leeuwen 		/* only allow the part of the buffer we know we need */
82219b347b3SPascal van Leeuwen 		if (len > totlen_dst)
82319b347b3SPascal van Leeuwen 			len = totlen_dst;
82419b347b3SPascal van Leeuwen 		if (unlikely(!len))
82519b347b3SPascal van Leeuwen 			break;
82619b347b3SPascal van Leeuwen 		totlen_dst -= len;
82719b347b3SPascal van Leeuwen 
82819b347b3SPascal van Leeuwen 		/* skip over AAD space in buffer - not written */
82919b347b3SPascal van Leeuwen 		if (assoclen) {
83019b347b3SPascal van Leeuwen 			if (assoclen >= len) {
83119b347b3SPascal van Leeuwen 				assoclen -= len;
83219b347b3SPascal van Leeuwen 				continue;
83319b347b3SPascal van Leeuwen 			}
8341b44c5a6SAntoine Ténart 			rdesc = safexcel_add_rdesc(priv, ring, first, last,
83519b347b3SPascal van Leeuwen 						   sg_dma_address(sg) +
83619b347b3SPascal van Leeuwen 						   assoclen,
83719b347b3SPascal van Leeuwen 						   len - assoclen);
83819b347b3SPascal van Leeuwen 			assoclen = 0;
83919b347b3SPascal van Leeuwen 		} else {
84019b347b3SPascal van Leeuwen 			rdesc = safexcel_add_rdesc(priv, ring, first, last,
84119b347b3SPascal van Leeuwen 						   sg_dma_address(sg),
84219b347b3SPascal van Leeuwen 						   len);
84319b347b3SPascal van Leeuwen 		}
8441b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
8451b44c5a6SAntoine Ténart 			/* No space left in the result descriptor ring */
8461b44c5a6SAntoine Ténart 			ret = PTR_ERR(rdesc);
8471b44c5a6SAntoine Ténart 			goto rdesc_rollback;
8481b44c5a6SAntoine Ténart 		}
84919b347b3SPascal van Leeuwen 		if (first) {
8509744fec9SOfer Heifetz 			first_rdesc = rdesc;
85119b347b3SPascal van Leeuwen 			first = false;
85219b347b3SPascal van Leeuwen 		}
8531b44c5a6SAntoine Ténart 		n_rdesc++;
8541b44c5a6SAntoine Ténart 	}
8551b44c5a6SAntoine Ténart 
85619b347b3SPascal van Leeuwen 	if (unlikely(first)) {
85719b347b3SPascal van Leeuwen 		/*
85819b347b3SPascal van Leeuwen 		 * Special case: AEAD decrypt with only AAD data.
85919b347b3SPascal van Leeuwen 		 * In this case there is NO output data from the engine,
86019b347b3SPascal van Leeuwen 		 * but the engine still needs a result descriptor!
86119b347b3SPascal van Leeuwen 		 * Create a dummy one just for catching the result token.
86219b347b3SPascal van Leeuwen 		 */
86319b347b3SPascal van Leeuwen 		rdesc = safexcel_add_rdesc(priv, ring, true, true, 0, 0);
86419b347b3SPascal van Leeuwen 		if (IS_ERR(rdesc)) {
86519b347b3SPascal van Leeuwen 			/* No space left in the result descriptor ring */
86619b347b3SPascal van Leeuwen 			ret = PTR_ERR(rdesc);
86719b347b3SPascal van Leeuwen 			goto rdesc_rollback;
86819b347b3SPascal van Leeuwen 		}
86919b347b3SPascal van Leeuwen 		first_rdesc = rdesc;
87019b347b3SPascal van Leeuwen 		n_rdesc = 1;
87119b347b3SPascal van Leeuwen 	}
87219b347b3SPascal van Leeuwen 
8739744fec9SOfer Heifetz 	safexcel_rdr_req_set(priv, ring, first_rdesc, base);
87497858434SAntoine Ténart 
8751b44c5a6SAntoine Ténart 	*commands = n_cdesc;
876152bdf4cSOfer Heifetz 	*results = n_rdesc;
8771b44c5a6SAntoine Ténart 	return 0;
8781b44c5a6SAntoine Ténart 
8791b44c5a6SAntoine Ténart rdesc_rollback:
8801b44c5a6SAntoine Ténart 	for (i = 0; i < n_rdesc; i++)
8811b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].rdr);
8821b44c5a6SAntoine Ténart cdesc_rollback:
8831b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
8841b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
8851b44c5a6SAntoine Ténart 
8868ac1283eSAntoine Tenart 	if (src == dst) {
88719b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL);
8881b44c5a6SAntoine Ténart 	} else {
88919b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE);
89019b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE);
8911b44c5a6SAntoine Ténart 	}
8921b44c5a6SAntoine Ténart 
8931b44c5a6SAntoine Ténart 	return ret;
8941b44c5a6SAntoine Ténart }
8951b44c5a6SAntoine Ténart 
8961b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
8971b44c5a6SAntoine Ténart 				      int ring,
8988ac1283eSAntoine Tenart 				      struct crypto_async_request *base,
89989332590SAntoine Tenart 				      struct safexcel_cipher_req *sreq,
9001b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
9011b44c5a6SAntoine Ténart {
9028ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
9031b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
9041b44c5a6SAntoine Ténart 	int ndesc = 0, enq_ret;
9051b44c5a6SAntoine Ténart 
9061b44c5a6SAntoine Ténart 	*ret = 0;
9071b44c5a6SAntoine Ténart 
90889332590SAntoine Tenart 	if (unlikely(!sreq->rdescs))
90989332590SAntoine Tenart 		return 0;
91089332590SAntoine Tenart 
91189332590SAntoine Tenart 	while (sreq->rdescs--) {
9121b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
9131b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
9141b44c5a6SAntoine Ténart 			dev_err(priv->dev,
9151b44c5a6SAntoine Ténart 				"cipher: invalidate: could not retrieve the result descriptor\n");
9161b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
9171b44c5a6SAntoine Ténart 			break;
9181b44c5a6SAntoine Ténart 		}
9191b44c5a6SAntoine Ténart 
920cda3e73aSAntoine Tenart 		if (likely(!*ret))
921cda3e73aSAntoine Tenart 			*ret = safexcel_rdesc_check_errors(priv, rdesc);
9221b44c5a6SAntoine Ténart 
9231b44c5a6SAntoine Ténart 		ndesc++;
92489332590SAntoine Tenart 	}
9251b44c5a6SAntoine Ténart 
9261b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
9271b44c5a6SAntoine Ténart 
9281b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
9291b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
9301b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
9311b44c5a6SAntoine Ténart 
9321b44c5a6SAntoine Ténart 		*should_complete = true;
9331b44c5a6SAntoine Ténart 
9341b44c5a6SAntoine Ténart 		return ndesc;
9351b44c5a6SAntoine Ténart 	}
9361b44c5a6SAntoine Ténart 
93786671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
93886671abbSAntoine Ténart 	ctx->base.ring = ring;
9391b44c5a6SAntoine Ténart 
94086671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
9418ac1283eSAntoine Tenart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
94286671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
9431b44c5a6SAntoine Ténart 
9441b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
9451b44c5a6SAntoine Ténart 		*ret = enq_ret;
9461b44c5a6SAntoine Ténart 
9478472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
9488472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
94986671abbSAntoine Ténart 
9501b44c5a6SAntoine Ténart 	*should_complete = false;
9511b44c5a6SAntoine Ténart 
9521b44c5a6SAntoine Ténart 	return ndesc;
9531b44c5a6SAntoine Ténart }
9541b44c5a6SAntoine Ténart 
9558ac1283eSAntoine Tenart static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv,
9568ac1283eSAntoine Tenart 					   int ring,
9571eb7b403SOfer Heifetz 					   struct crypto_async_request *async,
9581eb7b403SOfer Heifetz 					   bool *should_complete, int *ret)
9591eb7b403SOfer Heifetz {
9601eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
9611eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
9621eb7b403SOfer Heifetz 	int err;
9631eb7b403SOfer Heifetz 
9641eb7b403SOfer Heifetz 	if (sreq->needs_inv) {
9651eb7b403SOfer Heifetz 		sreq->needs_inv = false;
96689332590SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async, sreq,
9671eb7b403SOfer Heifetz 						 should_complete, ret);
9681eb7b403SOfer Heifetz 	} else {
9698ac1283eSAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
9708ac1283eSAntoine Tenart 						 req->dst, req->cryptlen, sreq,
9711eb7b403SOfer Heifetz 						 should_complete, ret);
9721eb7b403SOfer Heifetz 	}
9731eb7b403SOfer Heifetz 
9741eb7b403SOfer Heifetz 	return err;
9751eb7b403SOfer Heifetz }
9761eb7b403SOfer Heifetz 
977f6beaea3SAntoine Tenart static int safexcel_aead_handle_result(struct safexcel_crypto_priv *priv,
978f6beaea3SAntoine Tenart 				       int ring,
979f6beaea3SAntoine Tenart 				       struct crypto_async_request *async,
980f6beaea3SAntoine Tenart 				       bool *should_complete, int *ret)
981f6beaea3SAntoine Tenart {
982f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
983f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
984f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
985f6beaea3SAntoine Tenart 	int err;
986f6beaea3SAntoine Tenart 
987f6beaea3SAntoine Tenart 	if (sreq->needs_inv) {
988f6beaea3SAntoine Tenart 		sreq->needs_inv = false;
98989332590SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async, sreq,
990f6beaea3SAntoine Tenart 						 should_complete, ret);
991f6beaea3SAntoine Tenart 	} else {
992f6beaea3SAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
993f6beaea3SAntoine Tenart 						 req->dst,
994f6beaea3SAntoine Tenart 						 req->cryptlen + crypto_aead_authsize(tfm),
995f6beaea3SAntoine Tenart 						 sreq, should_complete, ret);
996f6beaea3SAntoine Tenart 	}
997f6beaea3SAntoine Tenart 
998f6beaea3SAntoine Tenart 	return err;
999f6beaea3SAntoine Tenart }
1000f6beaea3SAntoine Tenart 
10018ac1283eSAntoine Tenart static int safexcel_cipher_send_inv(struct crypto_async_request *base,
10029744fec9SOfer Heifetz 				    int ring, int *commands, int *results)
10031b44c5a6SAntoine Ténart {
10048ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
100518e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
10061b44c5a6SAntoine Ténart 	int ret;
10071b44c5a6SAntoine Ténart 
10089744fec9SOfer Heifetz 	ret = safexcel_invalidate_cache(base, priv, ctx->base.ctxr_dma, ring);
10091b44c5a6SAntoine Ténart 	if (unlikely(ret))
10101b44c5a6SAntoine Ténart 		return ret;
10111b44c5a6SAntoine Ténart 
10121b44c5a6SAntoine Ténart 	*commands = 1;
10131b44c5a6SAntoine Ténart 	*results = 1;
10141b44c5a6SAntoine Ténart 
10151b44c5a6SAntoine Ténart 	return 0;
10161b44c5a6SAntoine Ténart }
10171b44c5a6SAntoine Ténart 
10188ac1283eSAntoine Tenart static int safexcel_skcipher_send(struct crypto_async_request *async, int ring,
10191eb7b403SOfer Heifetz 				  int *commands, int *results)
10201eb7b403SOfer Heifetz {
10211eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
1022871df319SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
10231eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
102418e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
10251eb7b403SOfer Heifetz 	int ret;
10261eb7b403SOfer Heifetz 
102753c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv);
1028871df319SAntoine Ténart 
10295bdb6e6aSPascal van Leeuwen 	if (sreq->needs_inv) {
10309744fec9SOfer Heifetz 		ret = safexcel_cipher_send_inv(async, ring, commands, results);
10315bdb6e6aSPascal van Leeuwen 	} else {
10325bdb6e6aSPascal van Leeuwen 		struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
10335bdb6e6aSPascal van Leeuwen 		u8 input_iv[AES_BLOCK_SIZE];
10345bdb6e6aSPascal van Leeuwen 
10355bdb6e6aSPascal van Leeuwen 		/*
10365bdb6e6aSPascal van Leeuwen 		 * Save input IV in case of CBC decrypt mode
10375bdb6e6aSPascal van Leeuwen 		 * Will be overwritten with output IV prior to use!
10385bdb6e6aSPascal van Leeuwen 		 */
10395bdb6e6aSPascal van Leeuwen 		memcpy(input_iv, req->iv, crypto_skcipher_ivsize(skcipher));
10405bdb6e6aSPascal van Leeuwen 
10419744fec9SOfer Heifetz 		ret = safexcel_send_req(async, ring, sreq, req->src,
10425bdb6e6aSPascal van Leeuwen 					req->dst, req->cryptlen, 0, 0, input_iv,
1043f6beaea3SAntoine Tenart 					commands, results);
10445bdb6e6aSPascal van Leeuwen 	}
104589332590SAntoine Tenart 
104689332590SAntoine Tenart 	sreq->rdescs = *results;
1047f6beaea3SAntoine Tenart 	return ret;
1048f6beaea3SAntoine Tenart }
1049f6beaea3SAntoine Tenart 
1050f6beaea3SAntoine Tenart static int safexcel_aead_send(struct crypto_async_request *async, int ring,
10519744fec9SOfer Heifetz 			      int *commands, int *results)
1052f6beaea3SAntoine Tenart {
1053f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
1054f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1055f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
1056f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
105718e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
1058f6beaea3SAntoine Tenart 	int ret;
1059f6beaea3SAntoine Tenart 
106053c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv);
1061f6beaea3SAntoine Tenart 
1062f6beaea3SAntoine Tenart 	if (sreq->needs_inv)
10639744fec9SOfer Heifetz 		ret = safexcel_cipher_send_inv(async, ring, commands, results);
1064f6beaea3SAntoine Tenart 	else
10659744fec9SOfer Heifetz 		ret = safexcel_send_req(async, ring, sreq, req->src, req->dst,
10669744fec9SOfer Heifetz 					req->cryptlen, req->assoclen,
1067f6beaea3SAntoine Tenart 					crypto_aead_authsize(tfm), req->iv,
10681eb7b403SOfer Heifetz 					commands, results);
106989332590SAntoine Tenart 	sreq->rdescs = *results;
10701eb7b403SOfer Heifetz 	return ret;
10711eb7b403SOfer Heifetz }
10721eb7b403SOfer Heifetz 
10738ac1283eSAntoine Tenart static int safexcel_cipher_exit_inv(struct crypto_tfm *tfm,
10748ac1283eSAntoine Tenart 				    struct crypto_async_request *base,
10758ac1283eSAntoine Tenart 				    struct safexcel_cipher_req *sreq,
10768ac1283eSAntoine Tenart 				    struct safexcel_inv_result *result)
10771b44c5a6SAntoine Ténart {
10781b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
107918e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
108086671abbSAntoine Ténart 	int ring = ctx->base.ring;
10811b44c5a6SAntoine Ténart 
10828ac1283eSAntoine Tenart 	init_completion(&result->completion);
10831b44c5a6SAntoine Ténart 
10848ac1283eSAntoine Tenart 	ctx = crypto_tfm_ctx(base->tfm);
10851b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
10861eb7b403SOfer Heifetz 	sreq->needs_inv = true;
10871b44c5a6SAntoine Ténart 
108886671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
10898ac1283eSAntoine Tenart 	crypto_enqueue_request(&priv->ring[ring].queue, base);
109086671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
10911b44c5a6SAntoine Ténart 
10928472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
10938472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
10941b44c5a6SAntoine Ténart 
10958ac1283eSAntoine Tenart 	wait_for_completion(&result->completion);
10961b44c5a6SAntoine Ténart 
10978ac1283eSAntoine Tenart 	if (result->error) {
10981b44c5a6SAntoine Ténart 		dev_warn(priv->dev,
10991b44c5a6SAntoine Ténart 			"cipher: sync: invalidate: completion error %d\n",
11008ac1283eSAntoine Tenart 			 result->error);
11018ac1283eSAntoine Tenart 		return result->error;
11021b44c5a6SAntoine Ténart 	}
11031b44c5a6SAntoine Ténart 
11041b44c5a6SAntoine Ténart 	return 0;
11051b44c5a6SAntoine Ténart }
11061b44c5a6SAntoine Ténart 
11078ac1283eSAntoine Tenart static int safexcel_skcipher_exit_inv(struct crypto_tfm *tfm)
11088ac1283eSAntoine Tenart {
11098ac1283eSAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, skcipher, EIP197_SKCIPHER_REQ_SIZE);
11108ac1283eSAntoine Tenart 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
11118ac1283eSAntoine Tenart 	struct safexcel_inv_result result = {};
11128ac1283eSAntoine Tenart 
11138ac1283eSAntoine Tenart 	memset(req, 0, sizeof(struct skcipher_request));
11148ac1283eSAntoine Tenart 
11158ac1283eSAntoine Tenart 	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
11168ac1283eSAntoine Tenart 				      safexcel_inv_complete, &result);
11178ac1283eSAntoine Tenart 	skcipher_request_set_tfm(req, __crypto_skcipher_cast(tfm));
11188ac1283eSAntoine Tenart 
11198ac1283eSAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
11208ac1283eSAntoine Tenart }
11218ac1283eSAntoine Tenart 
1122f6beaea3SAntoine Tenart static int safexcel_aead_exit_inv(struct crypto_tfm *tfm)
1123f6beaea3SAntoine Tenart {
1124f6beaea3SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, aead, EIP197_AEAD_REQ_SIZE);
1125f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
1126f6beaea3SAntoine Tenart 	struct safexcel_inv_result result = {};
1127f6beaea3SAntoine Tenart 
1128f6beaea3SAntoine Tenart 	memset(req, 0, sizeof(struct aead_request));
1129f6beaea3SAntoine Tenart 
1130f6beaea3SAntoine Tenart 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1131f6beaea3SAntoine Tenart 				  safexcel_inv_complete, &result);
1132f6beaea3SAntoine Tenart 	aead_request_set_tfm(req, __crypto_aead_cast(tfm));
1133f6beaea3SAntoine Tenart 
1134f6beaea3SAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
1135f6beaea3SAntoine Tenart }
1136f6beaea3SAntoine Tenart 
1137a7dea8c0SOfer Heifetz static int safexcel_queue_req(struct crypto_async_request *base,
11388ac1283eSAntoine Tenart 			struct safexcel_cipher_req *sreq,
113993369b5dSPascal van Leeuwen 			enum safexcel_cipher_direction dir)
11401b44c5a6SAntoine Ténart {
11418ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
114218e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
114386671abbSAntoine Ténart 	int ret, ring;
11441b44c5a6SAntoine Ténart 
11451eb7b403SOfer Heifetz 	sreq->needs_inv = false;
1146847ccfc5SOfer Heifetz 	sreq->direction = dir;
11471b44c5a6SAntoine Ténart 
11481b44c5a6SAntoine Ténart 	if (ctx->base.ctxr) {
114953c83e91SAntoine Tenart 		if (priv->flags & EIP197_TRC_CACHE && ctx->base.needs_inv) {
11501eb7b403SOfer Heifetz 			sreq->needs_inv = true;
11511eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
11521eb7b403SOfer Heifetz 		}
11531b44c5a6SAntoine Ténart 	} else {
11541b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
11551b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
11568ac1283eSAntoine Tenart 						 EIP197_GFP_FLAGS(*base),
11571b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
11581b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
11591b44c5a6SAntoine Ténart 			return -ENOMEM;
11601b44c5a6SAntoine Ténart 	}
11611b44c5a6SAntoine Ténart 
116286671abbSAntoine Ténart 	ring = ctx->base.ring;
11631b44c5a6SAntoine Ténart 
116486671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
11658ac1283eSAntoine Tenart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
116686671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
116786671abbSAntoine Ténart 
11688472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
11698472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
11701b44c5a6SAntoine Ténart 
11711b44c5a6SAntoine Ténart 	return ret;
11721b44c5a6SAntoine Ténart }
11731b44c5a6SAntoine Ténart 
117493369b5dSPascal van Leeuwen static int safexcel_encrypt(struct skcipher_request *req)
11751b44c5a6SAntoine Ténart {
1176a7dea8c0SOfer Heifetz 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
117793369b5dSPascal van Leeuwen 			SAFEXCEL_ENCRYPT);
11781b44c5a6SAntoine Ténart }
11791b44c5a6SAntoine Ténart 
118093369b5dSPascal van Leeuwen static int safexcel_decrypt(struct skcipher_request *req)
11811b44c5a6SAntoine Ténart {
1182a7dea8c0SOfer Heifetz 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
118393369b5dSPascal van Leeuwen 			SAFEXCEL_DECRYPT);
11841b44c5a6SAntoine Ténart }
11851b44c5a6SAntoine Ténart 
11861b44c5a6SAntoine Ténart static int safexcel_skcipher_cra_init(struct crypto_tfm *tfm)
11871b44c5a6SAntoine Ténart {
11881b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
11891b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
11901b44c5a6SAntoine Ténart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
11911b44c5a6SAntoine Ténart 			     alg.skcipher.base);
11921b44c5a6SAntoine Ténart 
11931eb7b403SOfer Heifetz 	crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm),
11941eb7b403SOfer Heifetz 				    sizeof(struct safexcel_cipher_req));
11951b44c5a6SAntoine Ténart 
119618e51895SHerbert Xu 	ctx->base.priv = tmpl->priv;
11978ac1283eSAntoine Tenart 
11988ac1283eSAntoine Tenart 	ctx->base.send = safexcel_skcipher_send;
11998ac1283eSAntoine Tenart 	ctx->base.handle_result = safexcel_skcipher_handle_result;
1200098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD;
1201098e51e5SPascal van Leeuwen 	ctx->ctrinit = 1;
12028ac1283eSAntoine Tenart 	return 0;
12038ac1283eSAntoine Tenart }
12048ac1283eSAntoine Tenart 
12058ac1283eSAntoine Tenart static int safexcel_cipher_cra_exit(struct crypto_tfm *tfm)
12068ac1283eSAntoine Tenart {
12078ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
12088ac1283eSAntoine Tenart 
1209ce679559SAntoine Tenart 	memzero_explicit(ctx->key, sizeof(ctx->key));
12108ac1283eSAntoine Tenart 
12118ac1283eSAntoine Tenart 	/* context not allocated, skip invalidation */
12128ac1283eSAntoine Tenart 	if (!ctx->base.ctxr)
12138ac1283eSAntoine Tenart 		return -ENOMEM;
12148ac1283eSAntoine Tenart 
1215ce679559SAntoine Tenart 	memzero_explicit(ctx->base.ctxr->data, sizeof(ctx->base.ctxr->data));
12161b44c5a6SAntoine Ténart 	return 0;
12171b44c5a6SAntoine Ténart }
12181b44c5a6SAntoine Ténart 
12191b44c5a6SAntoine Ténart static void safexcel_skcipher_cra_exit(struct crypto_tfm *tfm)
12201b44c5a6SAntoine Ténart {
12211b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
122218e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
12231b44c5a6SAntoine Ténart 	int ret;
12241b44c5a6SAntoine Ténart 
12258ac1283eSAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
12261b44c5a6SAntoine Ténart 		return;
12271b44c5a6SAntoine Ténart 
122853c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
12298ac1283eSAntoine Tenart 		ret = safexcel_skcipher_exit_inv(tfm);
12301b44c5a6SAntoine Ténart 		if (ret)
12318ac1283eSAntoine Tenart 			dev_warn(priv->dev, "skcipher: invalidation error %d\n",
12328ac1283eSAntoine Tenart 				 ret);
1233871df319SAntoine Ténart 	} else {
1234871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
1235871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
1236871df319SAntoine Ténart 	}
12371b44c5a6SAntoine Ténart }
12381b44c5a6SAntoine Ténart 
1239f6beaea3SAntoine Tenart static void safexcel_aead_cra_exit(struct crypto_tfm *tfm)
1240f6beaea3SAntoine Tenart {
1241f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
124218e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
1243f6beaea3SAntoine Tenart 	int ret;
1244f6beaea3SAntoine Tenart 
1245f6beaea3SAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
1246f6beaea3SAntoine Tenart 		return;
1247f6beaea3SAntoine Tenart 
124853c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
1249f6beaea3SAntoine Tenart 		ret = safexcel_aead_exit_inv(tfm);
1250f6beaea3SAntoine Tenart 		if (ret)
1251f6beaea3SAntoine Tenart 			dev_warn(priv->dev, "aead: invalidation error %d\n",
1252f6beaea3SAntoine Tenart 				 ret);
1253f6beaea3SAntoine Tenart 	} else {
1254f6beaea3SAntoine Tenart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
1255f6beaea3SAntoine Tenart 			      ctx->base.ctxr_dma);
1256f6beaea3SAntoine Tenart 	}
1257f6beaea3SAntoine Tenart }
1258f6beaea3SAntoine Tenart 
125993369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_ecb_cra_init(struct crypto_tfm *tfm)
126093369b5dSPascal van Leeuwen {
126193369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
126293369b5dSPascal van Leeuwen 
126393369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
126493369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
126593369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1266098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1267098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
126893369b5dSPascal van Leeuwen 	return 0;
126993369b5dSPascal van Leeuwen }
127093369b5dSPascal van Leeuwen 
12711b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_ecb_aes = {
12721b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1273062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
12741b44c5a6SAntoine Ténart 	.alg.skcipher = {
12758ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
127693369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
127793369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
12781b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
12791b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
12801b44c5a6SAntoine Ténart 		.base = {
12811b44c5a6SAntoine Ténart 			.cra_name = "ecb(aes)",
12821b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-ecb-aes",
1283aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
12842c95e6d9SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1285b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
12861b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
12871b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
12881b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
12891b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
129093369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ecb_cra_init,
12911b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
12921b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
12931b44c5a6SAntoine Ténart 		},
12941b44c5a6SAntoine Ténart 	},
12951b44c5a6SAntoine Ténart };
12961b44c5a6SAntoine Ténart 
129793369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_cbc_cra_init(struct crypto_tfm *tfm)
12981b44c5a6SAntoine Ténart {
129993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
13001b44c5a6SAntoine Ténart 
130193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
130293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1303098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
130493369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
130593369b5dSPascal van Leeuwen 	return 0;
13061b44c5a6SAntoine Ténart }
13071b44c5a6SAntoine Ténart 
13081b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_cbc_aes = {
13091b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1310062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
13111b44c5a6SAntoine Ténart 	.alg.skcipher = {
13128ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
131393369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
131493369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
13151b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
13161b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
13171b44c5a6SAntoine Ténart 		.ivsize = AES_BLOCK_SIZE,
13181b44c5a6SAntoine Ténart 		.base = {
13191b44c5a6SAntoine Ténart 			.cra_name = "cbc(aes)",
13201b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-cbc-aes",
1321aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
13222c95e6d9SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1323b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
13241b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
13251b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
13261b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
13271b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
132893369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_cbc_cra_init,
13291b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
13301b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
13311b44c5a6SAntoine Ténart 		},
13321b44c5a6SAntoine Ténart 	},
13331b44c5a6SAntoine Ténart };
1334f6beaea3SAntoine Tenart 
133548e97afaSPascal van Leeuwen static int safexcel_skcipher_aes_cfb_cra_init(struct crypto_tfm *tfm)
133648e97afaSPascal van Leeuwen {
133748e97afaSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
133848e97afaSPascal van Leeuwen 
133948e97afaSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
134048e97afaSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1341098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
134248e97afaSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB;
134348e97afaSPascal van Leeuwen 	return 0;
134448e97afaSPascal van Leeuwen }
134548e97afaSPascal van Leeuwen 
134648e97afaSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cfb_aes = {
134748e97afaSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
134848e97afaSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XFB,
134948e97afaSPascal van Leeuwen 	.alg.skcipher = {
135048e97afaSPascal van Leeuwen 		.setkey = safexcel_skcipher_aes_setkey,
135148e97afaSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
135248e97afaSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
135348e97afaSPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE,
135448e97afaSPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE,
135548e97afaSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
135648e97afaSPascal van Leeuwen 		.base = {
135748e97afaSPascal van Leeuwen 			.cra_name = "cfb(aes)",
135848e97afaSPascal van Leeuwen 			.cra_driver_name = "safexcel-cfb-aes",
135948e97afaSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
136048e97afaSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1361b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
136248e97afaSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
136348e97afaSPascal van Leeuwen 			.cra_blocksize = 1,
136448e97afaSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
136548e97afaSPascal van Leeuwen 			.cra_alignmask = 0,
136648e97afaSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_cfb_cra_init,
136748e97afaSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
136848e97afaSPascal van Leeuwen 			.cra_module = THIS_MODULE,
136948e97afaSPascal van Leeuwen 		},
137048e97afaSPascal van Leeuwen 	},
137148e97afaSPascal van Leeuwen };
137248e97afaSPascal van Leeuwen 
137350485dfbSPascal van Leeuwen static int safexcel_skcipher_aes_ofb_cra_init(struct crypto_tfm *tfm)
137450485dfbSPascal van Leeuwen {
137550485dfbSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
137650485dfbSPascal van Leeuwen 
137750485dfbSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
137850485dfbSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1379098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
138050485dfbSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB;
138150485dfbSPascal van Leeuwen 	return 0;
138250485dfbSPascal van Leeuwen }
138350485dfbSPascal van Leeuwen 
138450485dfbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ofb_aes = {
138550485dfbSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
138650485dfbSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XFB,
138750485dfbSPascal van Leeuwen 	.alg.skcipher = {
138850485dfbSPascal van Leeuwen 		.setkey = safexcel_skcipher_aes_setkey,
138950485dfbSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
139050485dfbSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
139150485dfbSPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE,
139250485dfbSPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE,
139350485dfbSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
139450485dfbSPascal van Leeuwen 		.base = {
139550485dfbSPascal van Leeuwen 			.cra_name = "ofb(aes)",
139650485dfbSPascal van Leeuwen 			.cra_driver_name = "safexcel-ofb-aes",
139750485dfbSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
139850485dfbSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1399b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
140050485dfbSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
140150485dfbSPascal van Leeuwen 			.cra_blocksize = 1,
140250485dfbSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
140350485dfbSPascal van Leeuwen 			.cra_alignmask = 0,
140450485dfbSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ofb_cra_init,
140550485dfbSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
140650485dfbSPascal van Leeuwen 			.cra_module = THIS_MODULE,
140750485dfbSPascal van Leeuwen 		},
140850485dfbSPascal van Leeuwen 	},
140950485dfbSPascal van Leeuwen };
141050485dfbSPascal van Leeuwen 
141154f9e8faSPascal van Leeuwen static int safexcel_skcipher_aesctr_setkey(struct crypto_skcipher *ctfm,
141254f9e8faSPascal van Leeuwen 					   const u8 *key, unsigned int len)
141354f9e8faSPascal van Leeuwen {
141454f9e8faSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
141554f9e8faSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
141618e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
141754f9e8faSPascal van Leeuwen 	struct crypto_aes_ctx aes;
141854f9e8faSPascal van Leeuwen 	int ret, i;
141954f9e8faSPascal van Leeuwen 	unsigned int keylen;
142054f9e8faSPascal van Leeuwen 
142154f9e8faSPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
1422f26882a3SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
142354f9e8faSPascal van Leeuwen 	/* exclude the nonce here */
1424f26882a3SPascal van Leeuwen 	keylen = len - CTR_RFC3686_NONCE_SIZE;
142554f9e8faSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, keylen);
1426674f368aSEric Biggers 	if (ret)
142754f9e8faSPascal van Leeuwen 		return ret;
142854f9e8faSPascal van Leeuwen 
142954f9e8faSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
143054f9e8faSPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
143113a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
143254f9e8faSPascal van Leeuwen 				ctx->base.needs_inv = true;
143354f9e8faSPascal van Leeuwen 				break;
143454f9e8faSPascal van Leeuwen 			}
143554f9e8faSPascal van Leeuwen 		}
143654f9e8faSPascal van Leeuwen 	}
143754f9e8faSPascal van Leeuwen 
143854f9e8faSPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
143954f9e8faSPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
144054f9e8faSPascal van Leeuwen 
144154f9e8faSPascal van Leeuwen 	ctx->key_len = keylen;
144254f9e8faSPascal van Leeuwen 
144354f9e8faSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
144454f9e8faSPascal van Leeuwen 	return 0;
144554f9e8faSPascal van Leeuwen }
144654f9e8faSPascal van Leeuwen 
144793369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_ctr_cra_init(struct crypto_tfm *tfm)
144893369b5dSPascal van Leeuwen {
144993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
145093369b5dSPascal van Leeuwen 
145193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
145293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1453098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
145493369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
145593369b5dSPascal van Leeuwen 	return 0;
145693369b5dSPascal van Leeuwen }
145793369b5dSPascal van Leeuwen 
145854f9e8faSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ctr_aes = {
145954f9e8faSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1460062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
146154f9e8faSPascal van Leeuwen 	.alg.skcipher = {
146254f9e8faSPascal van Leeuwen 		.setkey = safexcel_skcipher_aesctr_setkey,
146393369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
146493369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1465f26882a3SPascal van Leeuwen 		/* Add nonce size */
1466f26882a3SPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
1467f26882a3SPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
1468f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
146954f9e8faSPascal van Leeuwen 		.base = {
147054f9e8faSPascal van Leeuwen 			.cra_name = "rfc3686(ctr(aes))",
147154f9e8faSPascal van Leeuwen 			.cra_driver_name = "safexcel-ctr-aes",
1472aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
147354f9e8faSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1474b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
147554f9e8faSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
147654f9e8faSPascal van Leeuwen 			.cra_blocksize = 1,
147754f9e8faSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
147854f9e8faSPascal van Leeuwen 			.cra_alignmask = 0,
147993369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ctr_cra_init,
148054f9e8faSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
148154f9e8faSPascal van Leeuwen 			.cra_module = THIS_MODULE,
148254f9e8faSPascal van Leeuwen 		},
148354f9e8faSPascal van Leeuwen 	},
148454f9e8faSPascal van Leeuwen };
148554f9e8faSPascal van Leeuwen 
1486a7dea8c0SOfer Heifetz static int safexcel_des_setkey(struct crypto_skcipher *ctfm, const u8 *key,
1487a7dea8c0SOfer Heifetz 			       unsigned int len)
1488a7dea8c0SOfer Heifetz {
148921f5a15eSArd Biesheuvel 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
149018e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
1491a7dea8c0SOfer Heifetz 	int ret;
1492a7dea8c0SOfer Heifetz 
149321f5a15eSArd Biesheuvel 	ret = verify_skcipher_des_key(ctfm, key);
149421f5a15eSArd Biesheuvel 	if (ret)
149521f5a15eSArd Biesheuvel 		return ret;
1496a7dea8c0SOfer Heifetz 
1497a7dea8c0SOfer Heifetz 	/* if context exits and key changed, need to invalidate it */
1498177e358cSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
1499a7dea8c0SOfer Heifetz 		if (memcmp(ctx->key, key, len))
1500a7dea8c0SOfer Heifetz 			ctx->base.needs_inv = true;
1501a7dea8c0SOfer Heifetz 
1502a7dea8c0SOfer Heifetz 	memcpy(ctx->key, key, len);
1503a7dea8c0SOfer Heifetz 	ctx->key_len = len;
1504a7dea8c0SOfer Heifetz 
1505a7dea8c0SOfer Heifetz 	return 0;
1506a7dea8c0SOfer Heifetz }
1507a7dea8c0SOfer Heifetz 
150893369b5dSPascal van Leeuwen static int safexcel_skcipher_des_cbc_cra_init(struct crypto_tfm *tfm)
150993369b5dSPascal van Leeuwen {
151093369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
151193369b5dSPascal van Leeuwen 
151293369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
151393369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_DES;
1514098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
1515098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
151693369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
151793369b5dSPascal van Leeuwen 	return 0;
151893369b5dSPascal van Leeuwen }
151993369b5dSPascal van Leeuwen 
1520a7dea8c0SOfer Heifetz struct safexcel_alg_template safexcel_alg_cbc_des = {
1521a7dea8c0SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1522062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
1523a7dea8c0SOfer Heifetz 	.alg.skcipher = {
1524a7dea8c0SOfer Heifetz 		.setkey = safexcel_des_setkey,
152593369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
152693369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1527a7dea8c0SOfer Heifetz 		.min_keysize = DES_KEY_SIZE,
1528a7dea8c0SOfer Heifetz 		.max_keysize = DES_KEY_SIZE,
1529a7dea8c0SOfer Heifetz 		.ivsize = DES_BLOCK_SIZE,
1530a7dea8c0SOfer Heifetz 		.base = {
1531a7dea8c0SOfer Heifetz 			.cra_name = "cbc(des)",
1532a7dea8c0SOfer Heifetz 			.cra_driver_name = "safexcel-cbc-des",
1533aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
15342b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1535b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1536a7dea8c0SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1537a7dea8c0SOfer Heifetz 			.cra_blocksize = DES_BLOCK_SIZE,
1538a7dea8c0SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1539a7dea8c0SOfer Heifetz 			.cra_alignmask = 0,
154093369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des_cbc_cra_init,
1541a7dea8c0SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
1542a7dea8c0SOfer Heifetz 			.cra_module = THIS_MODULE,
1543a7dea8c0SOfer Heifetz 		},
1544a7dea8c0SOfer Heifetz 	},
1545a7dea8c0SOfer Heifetz };
1546a7dea8c0SOfer Heifetz 
154793369b5dSPascal van Leeuwen static int safexcel_skcipher_des_ecb_cra_init(struct crypto_tfm *tfm)
1548a7dea8c0SOfer Heifetz {
154993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1550a7dea8c0SOfer Heifetz 
155193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
155293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_DES;
155393369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1554098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1555098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
155693369b5dSPascal van Leeuwen 	return 0;
1557a7dea8c0SOfer Heifetz }
1558a7dea8c0SOfer Heifetz 
1559a7dea8c0SOfer Heifetz struct safexcel_alg_template safexcel_alg_ecb_des = {
1560a7dea8c0SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1561062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
1562a7dea8c0SOfer Heifetz 	.alg.skcipher = {
1563a7dea8c0SOfer Heifetz 		.setkey = safexcel_des_setkey,
156493369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
156593369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1566a7dea8c0SOfer Heifetz 		.min_keysize = DES_KEY_SIZE,
1567a7dea8c0SOfer Heifetz 		.max_keysize = DES_KEY_SIZE,
1568a7dea8c0SOfer Heifetz 		.base = {
1569a7dea8c0SOfer Heifetz 			.cra_name = "ecb(des)",
1570a7dea8c0SOfer Heifetz 			.cra_driver_name = "safexcel-ecb-des",
1571aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
15722b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1573b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1574a7dea8c0SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1575a7dea8c0SOfer Heifetz 			.cra_blocksize = DES_BLOCK_SIZE,
1576a7dea8c0SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1577a7dea8c0SOfer Heifetz 			.cra_alignmask = 0,
157893369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des_ecb_cra_init,
1579a7dea8c0SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
1580a7dea8c0SOfer Heifetz 			.cra_module = THIS_MODULE,
1581a7dea8c0SOfer Heifetz 		},
1582a7dea8c0SOfer Heifetz 	},
1583a7dea8c0SOfer Heifetz };
158462469879SOfer Heifetz 
158562469879SOfer Heifetz static int safexcel_des3_ede_setkey(struct crypto_skcipher *ctfm,
158662469879SOfer Heifetz 				   const u8 *key, unsigned int len)
158762469879SOfer Heifetz {
158867ac62bfSHerbert Xu 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
158918e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
159067ac62bfSHerbert Xu 	int err;
159162469879SOfer Heifetz 
159221f5a15eSArd Biesheuvel 	err = verify_skcipher_des3_key(ctfm, key);
159321f5a15eSArd Biesheuvel 	if (err)
159467ac62bfSHerbert Xu 		return err;
159562469879SOfer Heifetz 
159662469879SOfer Heifetz 	/* if context exits and key changed, need to invalidate it */
1597177e358cSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
159862469879SOfer Heifetz 		if (memcmp(ctx->key, key, len))
159962469879SOfer Heifetz 			ctx->base.needs_inv = true;
160062469879SOfer Heifetz 
160162469879SOfer Heifetz 	memcpy(ctx->key, key, len);
160262469879SOfer Heifetz 	ctx->key_len = len;
160362469879SOfer Heifetz 
160462469879SOfer Heifetz 	return 0;
160562469879SOfer Heifetz }
160662469879SOfer Heifetz 
160793369b5dSPascal van Leeuwen static int safexcel_skcipher_des3_cbc_cra_init(struct crypto_tfm *tfm)
160893369b5dSPascal van Leeuwen {
160993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
161093369b5dSPascal van Leeuwen 
161193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
161293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_3DES;
1613098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1614098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
161593369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
161693369b5dSPascal van Leeuwen 	return 0;
161793369b5dSPascal van Leeuwen }
161893369b5dSPascal van Leeuwen 
161962469879SOfer Heifetz struct safexcel_alg_template safexcel_alg_cbc_des3_ede = {
162062469879SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1621062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
162262469879SOfer Heifetz 	.alg.skcipher = {
162362469879SOfer Heifetz 		.setkey = safexcel_des3_ede_setkey,
162493369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
162593369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
162662469879SOfer Heifetz 		.min_keysize = DES3_EDE_KEY_SIZE,
162762469879SOfer Heifetz 		.max_keysize = DES3_EDE_KEY_SIZE,
162862469879SOfer Heifetz 		.ivsize = DES3_EDE_BLOCK_SIZE,
162962469879SOfer Heifetz 		.base = {
163062469879SOfer Heifetz 			.cra_name = "cbc(des3_ede)",
163162469879SOfer Heifetz 			.cra_driver_name = "safexcel-cbc-des3_ede",
1632aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
16332b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1634b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
163562469879SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
163662469879SOfer Heifetz 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
163762469879SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
163862469879SOfer Heifetz 			.cra_alignmask = 0,
163993369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des3_cbc_cra_init,
164062469879SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
164162469879SOfer Heifetz 			.cra_module = THIS_MODULE,
164262469879SOfer Heifetz 		},
164362469879SOfer Heifetz 	},
164462469879SOfer Heifetz };
164562469879SOfer Heifetz 
164693369b5dSPascal van Leeuwen static int safexcel_skcipher_des3_ecb_cra_init(struct crypto_tfm *tfm)
164762469879SOfer Heifetz {
164893369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
164962469879SOfer Heifetz 
165093369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
165193369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_3DES;
165293369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1653098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1654098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
165593369b5dSPascal van Leeuwen 	return 0;
165662469879SOfer Heifetz }
165762469879SOfer Heifetz 
165862469879SOfer Heifetz struct safexcel_alg_template safexcel_alg_ecb_des3_ede = {
165962469879SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1660062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
166162469879SOfer Heifetz 	.alg.skcipher = {
166262469879SOfer Heifetz 		.setkey = safexcel_des3_ede_setkey,
166393369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
166493369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
166562469879SOfer Heifetz 		.min_keysize = DES3_EDE_KEY_SIZE,
166662469879SOfer Heifetz 		.max_keysize = DES3_EDE_KEY_SIZE,
166762469879SOfer Heifetz 		.base = {
166862469879SOfer Heifetz 			.cra_name = "ecb(des3_ede)",
166962469879SOfer Heifetz 			.cra_driver_name = "safexcel-ecb-des3_ede",
1670aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
16712b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1672b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
167362469879SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
167462469879SOfer Heifetz 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
167562469879SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
167662469879SOfer Heifetz 			.cra_alignmask = 0,
167793369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des3_ecb_cra_init,
167862469879SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
167962469879SOfer Heifetz 			.cra_module = THIS_MODULE,
168062469879SOfer Heifetz 		},
168162469879SOfer Heifetz 	},
168262469879SOfer Heifetz };
168362469879SOfer Heifetz 
168493369b5dSPascal van Leeuwen static int safexcel_aead_encrypt(struct aead_request *req)
1685f6beaea3SAntoine Tenart {
1686f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
1687f6beaea3SAntoine Tenart 
168893369b5dSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
1689f6beaea3SAntoine Tenart }
1690f6beaea3SAntoine Tenart 
169193369b5dSPascal van Leeuwen static int safexcel_aead_decrypt(struct aead_request *req)
1692f6beaea3SAntoine Tenart {
1693f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
1694f6beaea3SAntoine Tenart 
169593369b5dSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
1696f6beaea3SAntoine Tenart }
1697f6beaea3SAntoine Tenart 
1698f6beaea3SAntoine Tenart static int safexcel_aead_cra_init(struct crypto_tfm *tfm)
1699f6beaea3SAntoine Tenart {
1700f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1701f6beaea3SAntoine Tenart 	struct safexcel_alg_template *tmpl =
1702f6beaea3SAntoine Tenart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
1703f6beaea3SAntoine Tenart 			     alg.aead.base);
1704f6beaea3SAntoine Tenart 
1705f6beaea3SAntoine Tenart 	crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
1706f6beaea3SAntoine Tenart 				sizeof(struct safexcel_cipher_req));
1707f6beaea3SAntoine Tenart 
170818e51895SHerbert Xu 	ctx->base.priv = tmpl->priv;
1709f6beaea3SAntoine Tenart 
17100e17e362SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES; /* default */
1711098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
1712098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD;
1713098e51e5SPascal van Leeuwen 	ctx->ctrinit = 1;
171493369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; /* default */
1715f6beaea3SAntoine Tenart 	ctx->aead = true;
1716f6beaea3SAntoine Tenart 	ctx->base.send = safexcel_aead_send;
1717f6beaea3SAntoine Tenart 	ctx->base.handle_result = safexcel_aead_handle_result;
1718f6beaea3SAntoine Tenart 	return 0;
1719f6beaea3SAntoine Tenart }
1720f6beaea3SAntoine Tenart 
172101ba061dSAntoine Tenart static int safexcel_aead_sha1_cra_init(struct crypto_tfm *tfm)
172201ba061dSAntoine Tenart {
172301ba061dSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
172401ba061dSAntoine Tenart 
172501ba061dSAntoine Tenart 	safexcel_aead_cra_init(tfm);
1726a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
172701ba061dSAntoine Tenart 	ctx->state_sz = SHA1_DIGEST_SIZE;
172801ba061dSAntoine Tenart 	return 0;
172901ba061dSAntoine Tenart }
173001ba061dSAntoine Tenart 
173101ba061dSAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_aes = {
173201ba061dSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1733062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA1,
173401ba061dSAntoine Tenart 	.alg.aead = {
173577cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
173693369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
173793369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
173801ba061dSAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
173901ba061dSAntoine Tenart 		.maxauthsize = SHA1_DIGEST_SIZE,
174001ba061dSAntoine Tenart 		.base = {
174101ba061dSAntoine Tenart 			.cra_name = "authenc(hmac(sha1),cbc(aes))",
174201ba061dSAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-aes",
1743aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
17443f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1745b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
174601ba061dSAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
174701ba061dSAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
174801ba061dSAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
174901ba061dSAntoine Tenart 			.cra_alignmask = 0,
175001ba061dSAntoine Tenart 			.cra_init = safexcel_aead_sha1_cra_init,
175101ba061dSAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
175201ba061dSAntoine Tenart 			.cra_module = THIS_MODULE,
175301ba061dSAntoine Tenart 		},
175401ba061dSAntoine Tenart 	},
175501ba061dSAntoine Tenart };
175601ba061dSAntoine Tenart 
1757f6beaea3SAntoine Tenart static int safexcel_aead_sha256_cra_init(struct crypto_tfm *tfm)
1758f6beaea3SAntoine Tenart {
1759f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1760f6beaea3SAntoine Tenart 
1761f6beaea3SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1762a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1763f6beaea3SAntoine Tenart 	ctx->state_sz = SHA256_DIGEST_SIZE;
1764f6beaea3SAntoine Tenart 	return 0;
1765f6beaea3SAntoine Tenart }
1766f6beaea3SAntoine Tenart 
1767f6beaea3SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_aes = {
1768f6beaea3SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1769062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
1770f6beaea3SAntoine Tenart 	.alg.aead = {
177177cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
177293369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
177393369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1774f6beaea3SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1775f6beaea3SAntoine Tenart 		.maxauthsize = SHA256_DIGEST_SIZE,
1776f6beaea3SAntoine Tenart 		.base = {
1777f6beaea3SAntoine Tenart 			.cra_name = "authenc(hmac(sha256),cbc(aes))",
1778f6beaea3SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-aes",
1779aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
17803f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1781b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1782f6beaea3SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1783f6beaea3SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1784f6beaea3SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1785f6beaea3SAntoine Tenart 			.cra_alignmask = 0,
1786f6beaea3SAntoine Tenart 			.cra_init = safexcel_aead_sha256_cra_init,
1787f6beaea3SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1788f6beaea3SAntoine Tenart 			.cra_module = THIS_MODULE,
1789f6beaea3SAntoine Tenart 		},
1790f6beaea3SAntoine Tenart 	},
1791f6beaea3SAntoine Tenart };
1792678b2878SAntoine Tenart 
1793678b2878SAntoine Tenart static int safexcel_aead_sha224_cra_init(struct crypto_tfm *tfm)
1794678b2878SAntoine Tenart {
1795678b2878SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1796678b2878SAntoine Tenart 
1797678b2878SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1798a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1799678b2878SAntoine Tenart 	ctx->state_sz = SHA256_DIGEST_SIZE;
1800678b2878SAntoine Tenart 	return 0;
1801678b2878SAntoine Tenart }
1802678b2878SAntoine Tenart 
1803678b2878SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_aes = {
1804678b2878SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1805062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
1806678b2878SAntoine Tenart 	.alg.aead = {
180777cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
180893369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
180993369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1810678b2878SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1811678b2878SAntoine Tenart 		.maxauthsize = SHA224_DIGEST_SIZE,
1812678b2878SAntoine Tenart 		.base = {
1813678b2878SAntoine Tenart 			.cra_name = "authenc(hmac(sha224),cbc(aes))",
1814678b2878SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-aes",
1815aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18163f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1817b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1818678b2878SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1819678b2878SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1820678b2878SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1821678b2878SAntoine Tenart 			.cra_alignmask = 0,
1822678b2878SAntoine Tenart 			.cra_init = safexcel_aead_sha224_cra_init,
1823678b2878SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1824678b2878SAntoine Tenart 			.cra_module = THIS_MODULE,
1825678b2878SAntoine Tenart 		},
1826678b2878SAntoine Tenart 	},
1827678b2878SAntoine Tenart };
182887eee125SAntoine Tenart 
182987eee125SAntoine Tenart static int safexcel_aead_sha512_cra_init(struct crypto_tfm *tfm)
183087eee125SAntoine Tenart {
183187eee125SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
183287eee125SAntoine Tenart 
183387eee125SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1834a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
183587eee125SAntoine Tenart 	ctx->state_sz = SHA512_DIGEST_SIZE;
183687eee125SAntoine Tenart 	return 0;
183787eee125SAntoine Tenart }
183887eee125SAntoine Tenart 
183987eee125SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_aes = {
184087eee125SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1841062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
184287eee125SAntoine Tenart 	.alg.aead = {
184377cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
184493369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
184593369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
184687eee125SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
184787eee125SAntoine Tenart 		.maxauthsize = SHA512_DIGEST_SIZE,
184887eee125SAntoine Tenart 		.base = {
184987eee125SAntoine Tenart 			.cra_name = "authenc(hmac(sha512),cbc(aes))",
185087eee125SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-aes",
1851aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18523f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1853b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
185487eee125SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
185587eee125SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
185687eee125SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
185787eee125SAntoine Tenart 			.cra_alignmask = 0,
185887eee125SAntoine Tenart 			.cra_init = safexcel_aead_sha512_cra_init,
185987eee125SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
186087eee125SAntoine Tenart 			.cra_module = THIS_MODULE,
186187eee125SAntoine Tenart 		},
186287eee125SAntoine Tenart 	},
186387eee125SAntoine Tenart };
1864ea23cb53SAntoine Tenart 
1865ea23cb53SAntoine Tenart static int safexcel_aead_sha384_cra_init(struct crypto_tfm *tfm)
1866ea23cb53SAntoine Tenart {
1867ea23cb53SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1868ea23cb53SAntoine Tenart 
1869ea23cb53SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1870a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
1871ea23cb53SAntoine Tenart 	ctx->state_sz = SHA512_DIGEST_SIZE;
1872ea23cb53SAntoine Tenart 	return 0;
1873ea23cb53SAntoine Tenart }
1874ea23cb53SAntoine Tenart 
1875ea23cb53SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_aes = {
1876ea23cb53SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1877062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
1878ea23cb53SAntoine Tenart 	.alg.aead = {
187977cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
188093369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
188193369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1882ea23cb53SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1883ea23cb53SAntoine Tenart 		.maxauthsize = SHA384_DIGEST_SIZE,
1884ea23cb53SAntoine Tenart 		.base = {
1885ea23cb53SAntoine Tenart 			.cra_name = "authenc(hmac(sha384),cbc(aes))",
1886ea23cb53SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-aes",
1887aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18883f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1889b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1890ea23cb53SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1891ea23cb53SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1892ea23cb53SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1893ea23cb53SAntoine Tenart 			.cra_alignmask = 0,
1894ea23cb53SAntoine Tenart 			.cra_init = safexcel_aead_sha384_cra_init,
1895ea23cb53SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1896ea23cb53SAntoine Tenart 			.cra_module = THIS_MODULE,
1897ea23cb53SAntoine Tenart 		},
1898ea23cb53SAntoine Tenart 	},
1899ea23cb53SAntoine Tenart };
190077cdd4efSPascal van Leeuwen 
19010e17e362SPascal van Leeuwen static int safexcel_aead_sha1_des3_cra_init(struct crypto_tfm *tfm)
19020e17e362SPascal van Leeuwen {
19030e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
19040e17e362SPascal van Leeuwen 
19050e17e362SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
19060e17e362SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1907098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1908098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
19090e17e362SPascal van Leeuwen 	return 0;
19100e17e362SPascal van Leeuwen }
19110e17e362SPascal van Leeuwen 
191277cdd4efSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des3_ede = {
191377cdd4efSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1914062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1,
191577cdd4efSPascal van Leeuwen 	.alg.aead = {
191677cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
191793369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
191893369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
191977cdd4efSPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
192077cdd4efSPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
192177cdd4efSPascal van Leeuwen 		.base = {
192277cdd4efSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
192377cdd4efSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des3_ede",
1924aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
192577cdd4efSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1926b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
192777cdd4efSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
192877cdd4efSPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
192977cdd4efSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
193077cdd4efSPascal van Leeuwen 			.cra_alignmask = 0,
19310e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_des3_cra_init,
19320e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
19330e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
19340e17e362SPascal van Leeuwen 		},
19350e17e362SPascal van Leeuwen 	},
19360e17e362SPascal van Leeuwen };
19370e17e362SPascal van Leeuwen 
1938f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha256_des3_cra_init(struct crypto_tfm *tfm)
1939f0a8bdf0SPascal van Leeuwen {
1940f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1941f0a8bdf0SPascal van Leeuwen 
1942f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
1943f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1944098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1945098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
1946f0a8bdf0SPascal van Leeuwen 	return 0;
1947f0a8bdf0SPascal van Leeuwen }
1948f0a8bdf0SPascal van Leeuwen 
1949f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des3_ede = {
1950f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1951f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
1952f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
1953f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
1954f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
1955f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1956f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
1957f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
1958f0a8bdf0SPascal van Leeuwen 		.base = {
1959f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
1960f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des3_ede",
1961f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
1962f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1963b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1964f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1965f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1966f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1967f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
1968f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_des3_cra_init,
1969f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
1970f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
1971f0a8bdf0SPascal van Leeuwen 		},
1972f0a8bdf0SPascal van Leeuwen 	},
1973f0a8bdf0SPascal van Leeuwen };
1974f0a8bdf0SPascal van Leeuwen 
1975f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha224_des3_cra_init(struct crypto_tfm *tfm)
1976f0a8bdf0SPascal van Leeuwen {
1977f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1978f0a8bdf0SPascal van Leeuwen 
1979f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
1980f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1981098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1982098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
1983f0a8bdf0SPascal van Leeuwen 	return 0;
1984f0a8bdf0SPascal van Leeuwen }
1985f0a8bdf0SPascal van Leeuwen 
1986f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des3_ede = {
1987f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1988f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
1989f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
1990f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
1991f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
1992f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1993f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
1994f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
1995f0a8bdf0SPascal van Leeuwen 		.base = {
1996f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),cbc(des3_ede))",
1997f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des3_ede",
1998f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
1999f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2000b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2001f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2002f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2003f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2004f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2005f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_des3_cra_init,
2006f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2007f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2008f0a8bdf0SPascal van Leeuwen 		},
2009f0a8bdf0SPascal van Leeuwen 	},
2010f0a8bdf0SPascal van Leeuwen };
2011f0a8bdf0SPascal van Leeuwen 
2012f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha512_des3_cra_init(struct crypto_tfm *tfm)
2013f0a8bdf0SPascal van Leeuwen {
2014f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2015f0a8bdf0SPascal van Leeuwen 
2016f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
2017f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
2018098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
2019098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2020f0a8bdf0SPascal van Leeuwen 	return 0;
2021f0a8bdf0SPascal van Leeuwen }
2022f0a8bdf0SPascal van Leeuwen 
2023f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des3_ede = {
2024f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2025f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2026f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2027f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2028f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2029f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2030f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2031f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
2032f0a8bdf0SPascal van Leeuwen 		.base = {
2033f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),cbc(des3_ede))",
2034f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des3_ede",
2035f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2036f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2037b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2038f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2039f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2040f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2041f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2042f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_des3_cra_init,
2043f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2044f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2045f0a8bdf0SPascal van Leeuwen 		},
2046f0a8bdf0SPascal van Leeuwen 	},
2047f0a8bdf0SPascal van Leeuwen };
2048f0a8bdf0SPascal van Leeuwen 
2049f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha384_des3_cra_init(struct crypto_tfm *tfm)
2050f0a8bdf0SPascal van Leeuwen {
2051f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2052f0a8bdf0SPascal van Leeuwen 
2053f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
2054f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
2055098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
2056098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2057f0a8bdf0SPascal van Leeuwen 	return 0;
2058f0a8bdf0SPascal van Leeuwen }
2059f0a8bdf0SPascal van Leeuwen 
2060f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des3_ede = {
2061f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2062f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2063f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2064f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2065f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2066f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2067f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2068f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
2069f0a8bdf0SPascal van Leeuwen 		.base = {
2070f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),cbc(des3_ede))",
2071f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des3_ede",
2072f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2073f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2074b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2075f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2076f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2077f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2078f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2079f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_des3_cra_init,
2080f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2081f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2082f0a8bdf0SPascal van Leeuwen 		},
2083f0a8bdf0SPascal van Leeuwen 	},
2084f0a8bdf0SPascal van Leeuwen };
2085f0a8bdf0SPascal van Leeuwen 
2086bb7679b8SPascal van Leeuwen static int safexcel_aead_sha1_des_cra_init(struct crypto_tfm *tfm)
2087bb7679b8SPascal van Leeuwen {
2088bb7679b8SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2089bb7679b8SPascal van Leeuwen 
2090bb7679b8SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
2091bb7679b8SPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2092098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2093098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2094bb7679b8SPascal van Leeuwen 	return 0;
2095bb7679b8SPascal van Leeuwen }
2096bb7679b8SPascal van Leeuwen 
2097bb7679b8SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des = {
2098bb7679b8SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2099bb7679b8SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1,
2100bb7679b8SPascal van Leeuwen 	.alg.aead = {
2101bb7679b8SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2102bb7679b8SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2103bb7679b8SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2104bb7679b8SPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2105bb7679b8SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
2106bb7679b8SPascal van Leeuwen 		.base = {
2107bb7679b8SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(des))",
2108bb7679b8SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des",
2109bb7679b8SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2110bb7679b8SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2111b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2112bb7679b8SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2113bb7679b8SPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2114bb7679b8SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2115bb7679b8SPascal van Leeuwen 			.cra_alignmask = 0,
2116bb7679b8SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_des_cra_init,
2117bb7679b8SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2118bb7679b8SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2119bb7679b8SPascal van Leeuwen 		},
2120bb7679b8SPascal van Leeuwen 	},
2121bb7679b8SPascal van Leeuwen };
2122bb7679b8SPascal van Leeuwen 
2123457a6fdfSPascal van Leeuwen static int safexcel_aead_sha256_des_cra_init(struct crypto_tfm *tfm)
2124457a6fdfSPascal van Leeuwen {
2125457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2126457a6fdfSPascal van Leeuwen 
2127457a6fdfSPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
2128457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2129098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2130098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2131457a6fdfSPascal van Leeuwen 	return 0;
2132457a6fdfSPascal van Leeuwen }
2133457a6fdfSPascal van Leeuwen 
2134457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des = {
2135457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2136457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2137457a6fdfSPascal van Leeuwen 	.alg.aead = {
2138457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2139457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2140457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2141457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2142457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
2143457a6fdfSPascal van Leeuwen 		.base = {
2144457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),cbc(des))",
2145457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des",
2146457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2147457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2148b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2149457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2150457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2151457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2152457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2153457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_des_cra_init,
2154457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2155457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2156457a6fdfSPascal van Leeuwen 		},
2157457a6fdfSPascal van Leeuwen 	},
2158457a6fdfSPascal van Leeuwen };
2159457a6fdfSPascal van Leeuwen 
2160457a6fdfSPascal van Leeuwen static int safexcel_aead_sha224_des_cra_init(struct crypto_tfm *tfm)
2161457a6fdfSPascal van Leeuwen {
2162457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2163457a6fdfSPascal van Leeuwen 
2164457a6fdfSPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
2165457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2166098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2167098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2168457a6fdfSPascal van Leeuwen 	return 0;
2169457a6fdfSPascal van Leeuwen }
2170457a6fdfSPascal van Leeuwen 
2171457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des = {
2172457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2173457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2174457a6fdfSPascal van Leeuwen 	.alg.aead = {
2175457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2176457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2177457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2178457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2179457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
2180457a6fdfSPascal van Leeuwen 		.base = {
2181457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),cbc(des))",
2182457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des",
2183457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2184457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2185b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2186457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2187457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2188457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2189457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2190457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_des_cra_init,
2191457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2192457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2193457a6fdfSPascal van Leeuwen 		},
2194457a6fdfSPascal van Leeuwen 	},
2195457a6fdfSPascal van Leeuwen };
2196457a6fdfSPascal van Leeuwen 
2197457a6fdfSPascal van Leeuwen static int safexcel_aead_sha512_des_cra_init(struct crypto_tfm *tfm)
2198457a6fdfSPascal van Leeuwen {
2199457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2200457a6fdfSPascal van Leeuwen 
2201457a6fdfSPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
2202457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2203098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2204098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2205457a6fdfSPascal van Leeuwen 	return 0;
2206457a6fdfSPascal van Leeuwen }
2207457a6fdfSPascal van Leeuwen 
2208457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des = {
2209457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2210457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2211457a6fdfSPascal van Leeuwen 	.alg.aead = {
2212457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2213457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2214457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2215457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2216457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
2217457a6fdfSPascal van Leeuwen 		.base = {
2218457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),cbc(des))",
2219457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des",
2220457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2221457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2222b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2223457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2224457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2225457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2226457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2227457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_des_cra_init,
2228457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2229457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2230457a6fdfSPascal van Leeuwen 		},
2231457a6fdfSPascal van Leeuwen 	},
2232457a6fdfSPascal van Leeuwen };
2233457a6fdfSPascal van Leeuwen 
2234457a6fdfSPascal van Leeuwen static int safexcel_aead_sha384_des_cra_init(struct crypto_tfm *tfm)
2235457a6fdfSPascal van Leeuwen {
2236457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2237457a6fdfSPascal van Leeuwen 
2238457a6fdfSPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
2239457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2240098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2241098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2242457a6fdfSPascal van Leeuwen 	return 0;
2243457a6fdfSPascal van Leeuwen }
2244457a6fdfSPascal van Leeuwen 
2245457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des = {
2246457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2247457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2248457a6fdfSPascal van Leeuwen 	.alg.aead = {
2249457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2250457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2251457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2252457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2253457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
2254457a6fdfSPascal van Leeuwen 		.base = {
2255457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),cbc(des))",
2256457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des",
2257457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2258457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2259b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2260457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2261457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2262457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2263457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2264457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_des_cra_init,
2265457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2266457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2267457a6fdfSPascal van Leeuwen 		},
2268457a6fdfSPascal van Leeuwen 	},
2269457a6fdfSPascal van Leeuwen };
2270457a6fdfSPascal van Leeuwen 
22710e17e362SPascal van Leeuwen static int safexcel_aead_sha1_ctr_cra_init(struct crypto_tfm *tfm)
22720e17e362SPascal van Leeuwen {
22730e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
22740e17e362SPascal van Leeuwen 
22750e17e362SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
22760e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
22770e17e362SPascal van Leeuwen 	return 0;
22780e17e362SPascal van Leeuwen }
22790e17e362SPascal van Leeuwen 
22800e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_aes = {
22810e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2282062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA1,
22830e17e362SPascal van Leeuwen 	.alg.aead = {
22840e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
228593369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
228693369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2287f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
22880e17e362SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
22890e17e362SPascal van Leeuwen 		.base = {
22900e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
22910e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-aes",
2292aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
22930e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2294b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
22950e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
22960e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
22970e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
22980e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
22990e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_ctr_cra_init,
23000e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23010e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23020e17e362SPascal van Leeuwen 		},
23030e17e362SPascal van Leeuwen 	},
23040e17e362SPascal van Leeuwen };
23050e17e362SPascal van Leeuwen 
23060e17e362SPascal van Leeuwen static int safexcel_aead_sha256_ctr_cra_init(struct crypto_tfm *tfm)
23070e17e362SPascal van Leeuwen {
23080e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23090e17e362SPascal van Leeuwen 
23100e17e362SPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
23110e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23120e17e362SPascal van Leeuwen 	return 0;
23130e17e362SPascal van Leeuwen }
23140e17e362SPascal van Leeuwen 
23150e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_ctr_aes = {
23160e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2317062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
23180e17e362SPascal van Leeuwen 	.alg.aead = {
23190e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
232093369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
232193369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2322f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23230e17e362SPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
23240e17e362SPascal van Leeuwen 		.base = {
23250e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
23260e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-ctr-aes",
2327aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23280e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2329b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
23300e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23310e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23320e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23330e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23340e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_ctr_cra_init,
23350e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23360e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23370e17e362SPascal van Leeuwen 		},
23380e17e362SPascal van Leeuwen 	},
23390e17e362SPascal van Leeuwen };
23400e17e362SPascal van Leeuwen 
23410e17e362SPascal van Leeuwen static int safexcel_aead_sha224_ctr_cra_init(struct crypto_tfm *tfm)
23420e17e362SPascal van Leeuwen {
23430e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23440e17e362SPascal van Leeuwen 
23450e17e362SPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
23460e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23470e17e362SPascal van Leeuwen 	return 0;
23480e17e362SPascal van Leeuwen }
23490e17e362SPascal van Leeuwen 
23500e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_ctr_aes = {
23510e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2352062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
23530e17e362SPascal van Leeuwen 	.alg.aead = {
23540e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
235593369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
235693369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2357f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23580e17e362SPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
23590e17e362SPascal van Leeuwen 		.base = {
23600e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))",
23610e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-ctr-aes",
2362aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23630e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2364b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
23650e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23660e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23670e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23680e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23690e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_ctr_cra_init,
23700e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23710e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23720e17e362SPascal van Leeuwen 		},
23730e17e362SPascal van Leeuwen 	},
23740e17e362SPascal van Leeuwen };
23750e17e362SPascal van Leeuwen 
23760e17e362SPascal van Leeuwen static int safexcel_aead_sha512_ctr_cra_init(struct crypto_tfm *tfm)
23770e17e362SPascal van Leeuwen {
23780e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23790e17e362SPascal van Leeuwen 
23800e17e362SPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
23810e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23820e17e362SPascal van Leeuwen 	return 0;
23830e17e362SPascal van Leeuwen }
23840e17e362SPascal van Leeuwen 
23850e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_ctr_aes = {
23860e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2387062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
23880e17e362SPascal van Leeuwen 	.alg.aead = {
23890e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
239093369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
239193369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2392f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23930e17e362SPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
23940e17e362SPascal van Leeuwen 		.base = {
23950e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
23960e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-ctr-aes",
2397aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23980e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2399b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
24000e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
24010e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
24020e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
24030e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
24040e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_ctr_cra_init,
24050e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
24060e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
24070e17e362SPascal van Leeuwen 		},
24080e17e362SPascal van Leeuwen 	},
24090e17e362SPascal van Leeuwen };
24100e17e362SPascal van Leeuwen 
24110e17e362SPascal van Leeuwen static int safexcel_aead_sha384_ctr_cra_init(struct crypto_tfm *tfm)
24120e17e362SPascal van Leeuwen {
24130e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
24140e17e362SPascal van Leeuwen 
24150e17e362SPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
24160e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
24170e17e362SPascal van Leeuwen 	return 0;
24180e17e362SPascal van Leeuwen }
24190e17e362SPascal van Leeuwen 
24200e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_ctr_aes = {
24210e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2422062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
24230e17e362SPascal van Leeuwen 	.alg.aead = {
24240e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
242593369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
242693369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2427f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
24280e17e362SPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
24290e17e362SPascal van Leeuwen 		.base = {
24300e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
24310e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-ctr-aes",
2432aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
24330e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2434b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
24350e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
24360e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
24370e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
24380e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
24390e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_ctr_cra_init,
244077cdd4efSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
244177cdd4efSPascal van Leeuwen 			.cra_module = THIS_MODULE,
244277cdd4efSPascal van Leeuwen 		},
244377cdd4efSPascal van Leeuwen 	},
244477cdd4efSPascal van Leeuwen };
2445c7da38a7SPascal van Leeuwen 
2446c7da38a7SPascal van Leeuwen static int safexcel_skcipher_aesxts_setkey(struct crypto_skcipher *ctfm,
2447c7da38a7SPascal van Leeuwen 					   const u8 *key, unsigned int len)
2448c7da38a7SPascal van Leeuwen {
2449c7da38a7SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
2450c7da38a7SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
245118e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
2452c7da38a7SPascal van Leeuwen 	struct crypto_aes_ctx aes;
2453c7da38a7SPascal van Leeuwen 	int ret, i;
2454c7da38a7SPascal van Leeuwen 	unsigned int keylen;
2455c7da38a7SPascal van Leeuwen 
2456c7da38a7SPascal van Leeuwen 	/* Check for illegal XTS keys */
2457c7da38a7SPascal van Leeuwen 	ret = xts_verify_key(ctfm, key, len);
2458c7da38a7SPascal van Leeuwen 	if (ret)
2459c7da38a7SPascal van Leeuwen 		return ret;
2460c7da38a7SPascal van Leeuwen 
2461c7da38a7SPascal van Leeuwen 	/* Only half of the key data is cipher key */
2462c7da38a7SPascal van Leeuwen 	keylen = (len >> 1);
2463c7da38a7SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, keylen);
2464674f368aSEric Biggers 	if (ret)
2465c7da38a7SPascal van Leeuwen 		return ret;
2466c7da38a7SPascal van Leeuwen 
2467c7da38a7SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
2468c7da38a7SPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
246913a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
2470c7da38a7SPascal van Leeuwen 				ctx->base.needs_inv = true;
2471c7da38a7SPascal van Leeuwen 				break;
2472c7da38a7SPascal van Leeuwen 			}
2473c7da38a7SPascal van Leeuwen 		}
2474c7da38a7SPascal van Leeuwen 	}
2475c7da38a7SPascal van Leeuwen 
2476c7da38a7SPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
2477c7da38a7SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
2478c7da38a7SPascal van Leeuwen 
2479c7da38a7SPascal van Leeuwen 	/* The other half is the tweak key */
2480c7da38a7SPascal van Leeuwen 	ret = aes_expandkey(&aes, (u8 *)(key + keylen), keylen);
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 + keylen / sizeof(u32)]) !=
248713a1bb93SPascal van Leeuwen 			    aes.key_enc[i]) {
2488c7da38a7SPascal van Leeuwen 				ctx->base.needs_inv = true;
2489c7da38a7SPascal van Leeuwen 				break;
2490c7da38a7SPascal van Leeuwen 			}
2491c7da38a7SPascal van Leeuwen 		}
2492c7da38a7SPascal van Leeuwen 	}
2493c7da38a7SPascal van Leeuwen 
2494c7da38a7SPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
2495c7da38a7SPascal van Leeuwen 		ctx->key[i + keylen / sizeof(u32)] =
2496c7da38a7SPascal van Leeuwen 			cpu_to_le32(aes.key_enc[i]);
2497c7da38a7SPascal van Leeuwen 
2498c7da38a7SPascal van Leeuwen 	ctx->key_len = keylen << 1;
2499c7da38a7SPascal van Leeuwen 
2500c7da38a7SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
2501c7da38a7SPascal van Leeuwen 	return 0;
2502c7da38a7SPascal van Leeuwen }
2503c7da38a7SPascal van Leeuwen 
2504c7da38a7SPascal van Leeuwen static int safexcel_skcipher_aes_xts_cra_init(struct crypto_tfm *tfm)
2505c7da38a7SPascal van Leeuwen {
2506c7da38a7SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2507c7da38a7SPascal van Leeuwen 
2508c7da38a7SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
2509c7da38a7SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
2510098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
2511c7da38a7SPascal van Leeuwen 	ctx->xts  = 1;
2512c7da38a7SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XTS;
2513c7da38a7SPascal van Leeuwen 	return 0;
2514c7da38a7SPascal van Leeuwen }
2515c7da38a7SPascal van Leeuwen 
2516c7da38a7SPascal van Leeuwen static int safexcel_encrypt_xts(struct skcipher_request *req)
2517c7da38a7SPascal van Leeuwen {
2518c7da38a7SPascal van Leeuwen 	if (req->cryptlen < XTS_BLOCK_SIZE)
2519c7da38a7SPascal van Leeuwen 		return -EINVAL;
2520c7da38a7SPascal van Leeuwen 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2521c7da38a7SPascal van Leeuwen 				  SAFEXCEL_ENCRYPT);
2522c7da38a7SPascal van Leeuwen }
2523c7da38a7SPascal van Leeuwen 
2524c7da38a7SPascal van Leeuwen static int safexcel_decrypt_xts(struct skcipher_request *req)
2525c7da38a7SPascal van Leeuwen {
2526c7da38a7SPascal van Leeuwen 	if (req->cryptlen < XTS_BLOCK_SIZE)
2527c7da38a7SPascal van Leeuwen 		return -EINVAL;
2528c7da38a7SPascal van Leeuwen 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2529c7da38a7SPascal van Leeuwen 				  SAFEXCEL_DECRYPT);
2530c7da38a7SPascal van Leeuwen }
2531c7da38a7SPascal van Leeuwen 
2532c7da38a7SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xts_aes = {
2533c7da38a7SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
2534062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XTS,
2535c7da38a7SPascal van Leeuwen 	.alg.skcipher = {
2536c7da38a7SPascal van Leeuwen 		.setkey = safexcel_skcipher_aesxts_setkey,
2537c7da38a7SPascal van Leeuwen 		.encrypt = safexcel_encrypt_xts,
2538c7da38a7SPascal van Leeuwen 		.decrypt = safexcel_decrypt_xts,
2539c7da38a7SPascal van Leeuwen 		/* XTS actually uses 2 AES keys glued together */
2540c7da38a7SPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE * 2,
2541c7da38a7SPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE * 2,
2542c7da38a7SPascal van Leeuwen 		.ivsize = XTS_BLOCK_SIZE,
2543c7da38a7SPascal van Leeuwen 		.base = {
2544c7da38a7SPascal van Leeuwen 			.cra_name = "xts(aes)",
2545c7da38a7SPascal van Leeuwen 			.cra_driver_name = "safexcel-xts-aes",
2546aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2547c7da38a7SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2548b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2549c7da38a7SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2550c7da38a7SPascal van Leeuwen 			.cra_blocksize = XTS_BLOCK_SIZE,
2551c7da38a7SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2552c7da38a7SPascal van Leeuwen 			.cra_alignmask = 0,
2553c7da38a7SPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_xts_cra_init,
2554c7da38a7SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
2555c7da38a7SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2556c7da38a7SPascal van Leeuwen 		},
2557c7da38a7SPascal van Leeuwen 	},
2558c7da38a7SPascal van Leeuwen };
25593e450886SPascal van Leeuwen 
25603e450886SPascal van Leeuwen static int safexcel_aead_gcm_setkey(struct crypto_aead *ctfm, const u8 *key,
25613e450886SPascal van Leeuwen 				    unsigned int len)
25623e450886SPascal van Leeuwen {
25633e450886SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
25643e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
256518e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
25663e450886SPascal van Leeuwen 	struct crypto_aes_ctx aes;
25673e450886SPascal van Leeuwen 	u32 hashkey[AES_BLOCK_SIZE >> 2];
25683e450886SPascal van Leeuwen 	int ret, i;
25693e450886SPascal van Leeuwen 
25703e450886SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
25713e450886SPascal van Leeuwen 	if (ret) {
25723e450886SPascal van Leeuwen 		memzero_explicit(&aes, sizeof(aes));
25733e450886SPascal van Leeuwen 		return ret;
25743e450886SPascal van Leeuwen 	}
25753e450886SPascal van Leeuwen 
25763e450886SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
25773e450886SPascal van Leeuwen 		for (i = 0; i < len / sizeof(u32); i++) {
257813a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
25793e450886SPascal van Leeuwen 				ctx->base.needs_inv = true;
25803e450886SPascal van Leeuwen 				break;
25813e450886SPascal van Leeuwen 			}
25823e450886SPascal van Leeuwen 		}
25833e450886SPascal van Leeuwen 	}
25843e450886SPascal van Leeuwen 
25853e450886SPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
25863e450886SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
25873e450886SPascal van Leeuwen 
25883e450886SPascal van Leeuwen 	ctx->key_len = len;
25893e450886SPascal van Leeuwen 
25903e450886SPascal van Leeuwen 	/* Compute hash key by encrypting zeroes with cipher key */
25913e450886SPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->hkaes, CRYPTO_TFM_REQ_MASK);
25923e450886SPascal van Leeuwen 	crypto_cipher_set_flags(ctx->hkaes, crypto_aead_get_flags(ctfm) &
25933e450886SPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
25943e450886SPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->hkaes, key, len);
25953e450886SPascal van Leeuwen 	if (ret)
25963e450886SPascal van Leeuwen 		return ret;
25973e450886SPascal van Leeuwen 
25983e450886SPascal van Leeuwen 	memset(hashkey, 0, AES_BLOCK_SIZE);
25993e450886SPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->hkaes, (u8 *)hashkey, (u8 *)hashkey);
26003e450886SPascal van Leeuwen 
26013e450886SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
26023e450886SPascal van Leeuwen 		for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) {
260378cf1c8bSHerbert Xu 			if (be32_to_cpu(ctx->base.ipad.be[i]) != hashkey[i]) {
26043e450886SPascal van Leeuwen 				ctx->base.needs_inv = true;
26053e450886SPascal van Leeuwen 				break;
26063e450886SPascal van Leeuwen 			}
26073e450886SPascal van Leeuwen 		}
26083e450886SPascal van Leeuwen 	}
26093e450886SPascal van Leeuwen 
26103e450886SPascal van Leeuwen 	for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
261178cf1c8bSHerbert Xu 		ctx->base.ipad.be[i] = cpu_to_be32(hashkey[i]);
26123e450886SPascal van Leeuwen 
26133e450886SPascal van Leeuwen 	memzero_explicit(hashkey, AES_BLOCK_SIZE);
26143e450886SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
26153e450886SPascal van Leeuwen 	return 0;
26163e450886SPascal van Leeuwen }
26173e450886SPascal van Leeuwen 
26183e450886SPascal van Leeuwen static int safexcel_aead_gcm_cra_init(struct crypto_tfm *tfm)
26193e450886SPascal van Leeuwen {
26203e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
26213e450886SPascal van Leeuwen 
26223e450886SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
26233e450886SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_GHASH;
26243e450886SPascal van Leeuwen 	ctx->state_sz = GHASH_BLOCK_SIZE;
26254eb76fafSPascal van Leeuwen 	ctx->xcm = EIP197_XCM_MODE_GCM;
26263e450886SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */
26273e450886SPascal van Leeuwen 
26283e450886SPascal van Leeuwen 	ctx->hkaes = crypto_alloc_cipher("aes", 0, 0);
26293f61b052Szhengbin 	return PTR_ERR_OR_ZERO(ctx->hkaes);
26303e450886SPascal van Leeuwen }
26313e450886SPascal van Leeuwen 
26323e450886SPascal van Leeuwen static void safexcel_aead_gcm_cra_exit(struct crypto_tfm *tfm)
26333e450886SPascal van Leeuwen {
26343e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
26353e450886SPascal van Leeuwen 
26363e450886SPascal van Leeuwen 	crypto_free_cipher(ctx->hkaes);
26373e450886SPascal van Leeuwen 	safexcel_aead_cra_exit(tfm);
26383e450886SPascal van Leeuwen }
26393e450886SPascal van Leeuwen 
26403e450886SPascal van Leeuwen static int safexcel_aead_gcm_setauthsize(struct crypto_aead *tfm,
26413e450886SPascal van Leeuwen 					 unsigned int authsize)
26423e450886SPascal van Leeuwen {
26433e450886SPascal van Leeuwen 	return crypto_gcm_check_authsize(authsize);
26443e450886SPascal van Leeuwen }
26453e450886SPascal van Leeuwen 
26463e450886SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_gcm = {
26473e450886SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
26483e450886SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
26493e450886SPascal van Leeuwen 	.alg.aead = {
26503e450886SPascal van Leeuwen 		.setkey = safexcel_aead_gcm_setkey,
26513e450886SPascal van Leeuwen 		.setauthsize = safexcel_aead_gcm_setauthsize,
26523e450886SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
26533e450886SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
26543e450886SPascal van Leeuwen 		.ivsize = GCM_AES_IV_SIZE,
26553e450886SPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
26563e450886SPascal van Leeuwen 		.base = {
26573e450886SPascal van Leeuwen 			.cra_name = "gcm(aes)",
26583e450886SPascal van Leeuwen 			.cra_driver_name = "safexcel-gcm-aes",
26593e450886SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
26603e450886SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2661b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
26623e450886SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
26633e450886SPascal van Leeuwen 			.cra_blocksize = 1,
26643e450886SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
26653e450886SPascal van Leeuwen 			.cra_alignmask = 0,
26663e450886SPascal van Leeuwen 			.cra_init = safexcel_aead_gcm_cra_init,
26673e450886SPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
26683e450886SPascal van Leeuwen 			.cra_module = THIS_MODULE,
26693e450886SPascal van Leeuwen 		},
26703e450886SPascal van Leeuwen 	},
26713e450886SPascal van Leeuwen };
26724eb76fafSPascal van Leeuwen 
26734eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_setkey(struct crypto_aead *ctfm, const u8 *key,
26744eb76fafSPascal van Leeuwen 				    unsigned int len)
26754eb76fafSPascal van Leeuwen {
26764eb76fafSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
26774eb76fafSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
267818e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
26794eb76fafSPascal van Leeuwen 	struct crypto_aes_ctx aes;
26804eb76fafSPascal van Leeuwen 	int ret, i;
26814eb76fafSPascal van Leeuwen 
26824eb76fafSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
26834eb76fafSPascal van Leeuwen 	if (ret) {
26844eb76fafSPascal van Leeuwen 		memzero_explicit(&aes, sizeof(aes));
26854eb76fafSPascal van Leeuwen 		return ret;
26864eb76fafSPascal van Leeuwen 	}
26874eb76fafSPascal van Leeuwen 
26884eb76fafSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
26894eb76fafSPascal van Leeuwen 		for (i = 0; i < len / sizeof(u32); i++) {
269013a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
26914eb76fafSPascal van Leeuwen 				ctx->base.needs_inv = true;
26924eb76fafSPascal van Leeuwen 				break;
26934eb76fafSPascal van Leeuwen 			}
26944eb76fafSPascal van Leeuwen 		}
26954eb76fafSPascal van Leeuwen 	}
26964eb76fafSPascal van Leeuwen 
26974eb76fafSPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++) {
26984eb76fafSPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
269978cf1c8bSHerbert Xu 		ctx->base.ipad.be[i + 2 * AES_BLOCK_SIZE / sizeof(u32)] =
27004eb76fafSPascal van Leeuwen 			cpu_to_be32(aes.key_enc[i]);
27014eb76fafSPascal van Leeuwen 	}
27024eb76fafSPascal van Leeuwen 
27034eb76fafSPascal van Leeuwen 	ctx->key_len = len;
27044eb76fafSPascal van Leeuwen 	ctx->state_sz = 2 * AES_BLOCK_SIZE + len;
27054eb76fafSPascal van Leeuwen 
27064eb76fafSPascal van Leeuwen 	if (len == AES_KEYSIZE_192)
27074eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
27084eb76fafSPascal van Leeuwen 	else if (len == AES_KEYSIZE_256)
27094eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
27104eb76fafSPascal van Leeuwen 	else
27114eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
27124eb76fafSPascal van Leeuwen 
27134eb76fafSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
27144eb76fafSPascal van Leeuwen 	return 0;
27154eb76fafSPascal van Leeuwen }
27164eb76fafSPascal van Leeuwen 
27174eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_cra_init(struct crypto_tfm *tfm)
27184eb76fafSPascal van Leeuwen {
27194eb76fafSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
27204eb76fafSPascal van Leeuwen 
27214eb76fafSPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
27224eb76fafSPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
27234eb76fafSPascal van Leeuwen 	ctx->state_sz = 3 * AES_BLOCK_SIZE;
27244eb76fafSPascal van Leeuwen 	ctx->xcm = EIP197_XCM_MODE_CCM;
27254eb76fafSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */
2726098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
27274eb76fafSPascal van Leeuwen 	return 0;
27284eb76fafSPascal van Leeuwen }
27294eb76fafSPascal van Leeuwen 
27304eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_setauthsize(struct crypto_aead *tfm,
27314eb76fafSPascal van Leeuwen 					 unsigned int authsize)
27324eb76fafSPascal van Leeuwen {
27334eb76fafSPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
27344eb76fafSPascal van Leeuwen 	switch (authsize) {
27354eb76fafSPascal van Leeuwen 	case 4:
27364eb76fafSPascal van Leeuwen 	case 6:
27374eb76fafSPascal van Leeuwen 	case 8:
27384eb76fafSPascal van Leeuwen 	case 10:
27394eb76fafSPascal van Leeuwen 	case 12:
27404eb76fafSPascal van Leeuwen 	case 14:
27414eb76fafSPascal van Leeuwen 	case 16:
27424eb76fafSPascal van Leeuwen 		break;
27434eb76fafSPascal van Leeuwen 	default:
27444eb76fafSPascal van Leeuwen 		return -EINVAL;
27454eb76fafSPascal van Leeuwen 	}
27464eb76fafSPascal van Leeuwen 
27474eb76fafSPascal van Leeuwen 	return 0;
27484eb76fafSPascal van Leeuwen }
27494eb76fafSPascal van Leeuwen 
27504eb76fafSPascal van Leeuwen static int safexcel_ccm_encrypt(struct aead_request *req)
27514eb76fafSPascal van Leeuwen {
27524eb76fafSPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
27534eb76fafSPascal van Leeuwen 
27544eb76fafSPascal van Leeuwen 	if (req->iv[0] < 1 || req->iv[0] > 7)
27554eb76fafSPascal van Leeuwen 		return -EINVAL;
27564eb76fafSPascal van Leeuwen 
27574eb76fafSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
27584eb76fafSPascal van Leeuwen }
27594eb76fafSPascal van Leeuwen 
27604eb76fafSPascal van Leeuwen static int safexcel_ccm_decrypt(struct aead_request *req)
27614eb76fafSPascal van Leeuwen {
27624eb76fafSPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
27634eb76fafSPascal van Leeuwen 
27644eb76fafSPascal van Leeuwen 	if (req->iv[0] < 1 || req->iv[0] > 7)
27654eb76fafSPascal van Leeuwen 		return -EINVAL;
27664eb76fafSPascal van Leeuwen 
27674eb76fafSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
27684eb76fafSPascal van Leeuwen }
27694eb76fafSPascal van Leeuwen 
27704eb76fafSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ccm = {
27714eb76fafSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
27724eb76fafSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL,
27734eb76fafSPascal van Leeuwen 	.alg.aead = {
27744eb76fafSPascal van Leeuwen 		.setkey = safexcel_aead_ccm_setkey,
27754eb76fafSPascal van Leeuwen 		.setauthsize = safexcel_aead_ccm_setauthsize,
27764eb76fafSPascal van Leeuwen 		.encrypt = safexcel_ccm_encrypt,
27774eb76fafSPascal van Leeuwen 		.decrypt = safexcel_ccm_decrypt,
27784eb76fafSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
27794eb76fafSPascal van Leeuwen 		.maxauthsize = AES_BLOCK_SIZE,
27804eb76fafSPascal van Leeuwen 		.base = {
27814eb76fafSPascal van Leeuwen 			.cra_name = "ccm(aes)",
27824eb76fafSPascal van Leeuwen 			.cra_driver_name = "safexcel-ccm-aes",
27834eb76fafSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
27844eb76fafSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2785b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
27864eb76fafSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
27874eb76fafSPascal van Leeuwen 			.cra_blocksize = 1,
27884eb76fafSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
27894eb76fafSPascal van Leeuwen 			.cra_alignmask = 0,
27904eb76fafSPascal van Leeuwen 			.cra_init = safexcel_aead_ccm_cra_init,
27914eb76fafSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
27924eb76fafSPascal van Leeuwen 			.cra_module = THIS_MODULE,
27934eb76fafSPascal van Leeuwen 		},
27944eb76fafSPascal van Leeuwen 	},
27954eb76fafSPascal van Leeuwen };
27964a593fb3SPascal van Leeuwen 
2797a6061921SPascal van Leeuwen static void safexcel_chacha20_setkey(struct safexcel_cipher_ctx *ctx,
2798a6061921SPascal van Leeuwen 				     const u8 *key)
27994a593fb3SPascal van Leeuwen {
280018e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
28014a593fb3SPascal van Leeuwen 
280213a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
280313a1bb93SPascal van Leeuwen 		if (memcmp(ctx->key, key, CHACHA_KEY_SIZE))
28044a593fb3SPascal van Leeuwen 			ctx->base.needs_inv = true;
28054a593fb3SPascal van Leeuwen 
280613a1bb93SPascal van Leeuwen 	memcpy(ctx->key, key, CHACHA_KEY_SIZE);
28074a593fb3SPascal van Leeuwen 	ctx->key_len = CHACHA_KEY_SIZE;
2808a6061921SPascal van Leeuwen }
2809a6061921SPascal van Leeuwen 
2810a6061921SPascal van Leeuwen static int safexcel_skcipher_chacha20_setkey(struct crypto_skcipher *ctfm,
2811a6061921SPascal van Leeuwen 					     const u8 *key, unsigned int len)
2812a6061921SPascal van Leeuwen {
2813a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
2814a6061921SPascal van Leeuwen 
2815674f368aSEric Biggers 	if (len != CHACHA_KEY_SIZE)
2816a6061921SPascal van Leeuwen 		return -EINVAL;
2817674f368aSEric Biggers 
2818a6061921SPascal van Leeuwen 	safexcel_chacha20_setkey(ctx, key);
28194a593fb3SPascal van Leeuwen 
28204a593fb3SPascal van Leeuwen 	return 0;
28214a593fb3SPascal van Leeuwen }
28224a593fb3SPascal van Leeuwen 
28234a593fb3SPascal van Leeuwen static int safexcel_skcipher_chacha20_cra_init(struct crypto_tfm *tfm)
28244a593fb3SPascal van Leeuwen {
28254a593fb3SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
28264a593fb3SPascal van Leeuwen 
28274a593fb3SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
28284a593fb3SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_CHACHA20;
2829098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
28304a593fb3SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32;
28314a593fb3SPascal van Leeuwen 	return 0;
28324a593fb3SPascal van Leeuwen }
28334a593fb3SPascal van Leeuwen 
28344a593fb3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chacha20 = {
28354a593fb3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
28364a593fb3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20,
28374a593fb3SPascal van Leeuwen 	.alg.skcipher = {
28384a593fb3SPascal van Leeuwen 		.setkey = safexcel_skcipher_chacha20_setkey,
28394a593fb3SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
28404a593fb3SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
28414a593fb3SPascal van Leeuwen 		.min_keysize = CHACHA_KEY_SIZE,
28424a593fb3SPascal van Leeuwen 		.max_keysize = CHACHA_KEY_SIZE,
28434a593fb3SPascal van Leeuwen 		.ivsize = CHACHA_IV_SIZE,
28444a593fb3SPascal van Leeuwen 		.base = {
28454a593fb3SPascal van Leeuwen 			.cra_name = "chacha20",
28464a593fb3SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20",
28474a593fb3SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
28484a593fb3SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2849b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
28504a593fb3SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
28514a593fb3SPascal van Leeuwen 			.cra_blocksize = 1,
28524a593fb3SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
28534a593fb3SPascal van Leeuwen 			.cra_alignmask = 0,
28544a593fb3SPascal van Leeuwen 			.cra_init = safexcel_skcipher_chacha20_cra_init,
28554a593fb3SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
28564a593fb3SPascal van Leeuwen 			.cra_module = THIS_MODULE,
28574a593fb3SPascal van Leeuwen 		},
28584a593fb3SPascal van Leeuwen 	},
28594a593fb3SPascal van Leeuwen };
2860a6061921SPascal van Leeuwen 
2861a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_setkey(struct crypto_aead *ctfm,
2862a6061921SPascal van Leeuwen 				    const u8 *key, unsigned int len)
2863a6061921SPascal van Leeuwen {
2864a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_aead_ctx(ctfm);
2865a6061921SPascal van Leeuwen 
2866a6061921SPascal van Leeuwen 	if (ctx->aead  == EIP197_AEAD_TYPE_IPSEC_ESP &&
2867a6061921SPascal van Leeuwen 	    len > EIP197_AEAD_IPSEC_NONCE_SIZE) {
2868a6061921SPascal van Leeuwen 		/* ESP variant has nonce appended to key */
2869a6061921SPascal van Leeuwen 		len -= EIP197_AEAD_IPSEC_NONCE_SIZE;
2870a6061921SPascal van Leeuwen 		ctx->nonce = *(u32 *)(key + len);
2871a6061921SPascal van Leeuwen 	}
2872674f368aSEric Biggers 	if (len != CHACHA_KEY_SIZE)
2873a6061921SPascal van Leeuwen 		return -EINVAL;
2874674f368aSEric Biggers 
2875a6061921SPascal van Leeuwen 	safexcel_chacha20_setkey(ctx, key);
2876a6061921SPascal van Leeuwen 
2877a6061921SPascal van Leeuwen 	return 0;
2878a6061921SPascal van Leeuwen }
2879a6061921SPascal van Leeuwen 
2880a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_setauthsize(struct crypto_aead *tfm,
2881a6061921SPascal van Leeuwen 					 unsigned int authsize)
2882a6061921SPascal van Leeuwen {
2883a6061921SPascal van Leeuwen 	if (authsize != POLY1305_DIGEST_SIZE)
2884a6061921SPascal van Leeuwen 		return -EINVAL;
2885a6061921SPascal van Leeuwen 	return 0;
2886a6061921SPascal van Leeuwen }
2887a6061921SPascal van Leeuwen 
2888a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_crypt(struct aead_request *req,
2889a6061921SPascal van Leeuwen 					  enum safexcel_cipher_direction dir)
2890a6061921SPascal van Leeuwen {
2891a6061921SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
2892a6061921SPascal van Leeuwen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2893a6061921SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
2894a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2895a6061921SPascal van Leeuwen 	struct aead_request *subreq = aead_request_ctx(req);
2896a6061921SPascal van Leeuwen 	u32 key[CHACHA_KEY_SIZE / sizeof(u32) + 1];
289713a1bb93SPascal van Leeuwen 	int ret = 0;
2898a6061921SPascal van Leeuwen 
2899a6061921SPascal van Leeuwen 	/*
2900a6061921SPascal van Leeuwen 	 * Instead of wasting time detecting umpteen silly corner cases,
2901a6061921SPascal van Leeuwen 	 * just dump all "small" requests to the fallback implementation.
2902a6061921SPascal van Leeuwen 	 * HW would not be faster on such small requests anyway.
2903a6061921SPascal van Leeuwen 	 */
2904a6061921SPascal van Leeuwen 	if (likely((ctx->aead != EIP197_AEAD_TYPE_IPSEC_ESP ||
2905a6061921SPascal van Leeuwen 		    req->assoclen >= EIP197_AEAD_IPSEC_IV_SIZE) &&
2906a6061921SPascal van Leeuwen 		   req->cryptlen > POLY1305_DIGEST_SIZE)) {
2907a6061921SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, dir);
2908a6061921SPascal van Leeuwen 	}
2909a6061921SPascal van Leeuwen 
2910a6061921SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
291113a1bb93SPascal van Leeuwen 	memcpy(key, ctx->key, CHACHA_KEY_SIZE);
2912a6061921SPascal van Leeuwen 	if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
2913a6061921SPascal van Leeuwen 		/* ESP variant has nonce appended to the key */
2914a6061921SPascal van Leeuwen 		key[CHACHA_KEY_SIZE / sizeof(u32)] = ctx->nonce;
2915a6061921SPascal van Leeuwen 		ret = crypto_aead_setkey(ctx->fback, (u8 *)key,
2916a6061921SPascal van Leeuwen 					 CHACHA_KEY_SIZE +
2917a6061921SPascal van Leeuwen 					 EIP197_AEAD_IPSEC_NONCE_SIZE);
2918a6061921SPascal van Leeuwen 	} else {
2919a6061921SPascal van Leeuwen 		ret = crypto_aead_setkey(ctx->fback, (u8 *)key,
2920a6061921SPascal van Leeuwen 					 CHACHA_KEY_SIZE);
2921a6061921SPascal van Leeuwen 	}
2922a6061921SPascal van Leeuwen 	if (ret) {
2923a6061921SPascal van Leeuwen 		crypto_aead_clear_flags(aead, CRYPTO_TFM_REQ_MASK);
2924a6061921SPascal van Leeuwen 		crypto_aead_set_flags(aead, crypto_aead_get_flags(ctx->fback) &
2925a6061921SPascal van Leeuwen 					    CRYPTO_TFM_REQ_MASK);
2926a6061921SPascal van Leeuwen 		return ret;
2927a6061921SPascal van Leeuwen 	}
2928a6061921SPascal van Leeuwen 
2929a6061921SPascal van Leeuwen 	aead_request_set_tfm(subreq, ctx->fback);
2930a6061921SPascal van Leeuwen 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
2931a6061921SPascal van Leeuwen 				  req->base.data);
2932a6061921SPascal van Leeuwen 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
2933a6061921SPascal van Leeuwen 			       req->iv);
2934a6061921SPascal van Leeuwen 	aead_request_set_ad(subreq, req->assoclen);
2935a6061921SPascal van Leeuwen 
2936a6061921SPascal van Leeuwen 	return (dir ==  SAFEXCEL_ENCRYPT) ?
2937a6061921SPascal van Leeuwen 		crypto_aead_encrypt(subreq) :
2938a6061921SPascal van Leeuwen 		crypto_aead_decrypt(subreq);
2939a6061921SPascal van Leeuwen }
2940a6061921SPascal van Leeuwen 
2941a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_encrypt(struct aead_request *req)
2942a6061921SPascal van Leeuwen {
2943a6061921SPascal van Leeuwen 	return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_ENCRYPT);
2944a6061921SPascal van Leeuwen }
2945a6061921SPascal van Leeuwen 
2946a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_decrypt(struct aead_request *req)
2947a6061921SPascal van Leeuwen {
2948a6061921SPascal van Leeuwen 	return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_DECRYPT);
2949a6061921SPascal van Leeuwen }
2950a6061921SPascal van Leeuwen 
29511769f704SPascal van Leeuwen static int safexcel_aead_fallback_cra_init(struct crypto_tfm *tfm)
2952a6061921SPascal van Leeuwen {
2953a6061921SPascal van Leeuwen 	struct crypto_aead *aead = __crypto_aead_cast(tfm);
2954a6061921SPascal van Leeuwen 	struct aead_alg *alg = crypto_aead_alg(aead);
2955a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2956a6061921SPascal van Leeuwen 
2957a6061921SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
2958a6061921SPascal van Leeuwen 
2959a6061921SPascal van Leeuwen 	/* Allocate fallback implementation */
2960a6061921SPascal van Leeuwen 	ctx->fback = crypto_alloc_aead(alg->base.cra_name, 0,
2961a6061921SPascal van Leeuwen 				       CRYPTO_ALG_ASYNC |
2962a6061921SPascal van Leeuwen 				       CRYPTO_ALG_NEED_FALLBACK);
2963a6061921SPascal van Leeuwen 	if (IS_ERR(ctx->fback))
2964a6061921SPascal van Leeuwen 		return PTR_ERR(ctx->fback);
2965a6061921SPascal van Leeuwen 
2966a6061921SPascal van Leeuwen 	crypto_aead_set_reqsize(aead, max(sizeof(struct safexcel_cipher_req),
2967a6061921SPascal van Leeuwen 					  sizeof(struct aead_request) +
2968a6061921SPascal van Leeuwen 					  crypto_aead_reqsize(ctx->fback)));
2969a6061921SPascal van Leeuwen 
2970a6061921SPascal van Leeuwen 	return 0;
2971a6061921SPascal van Leeuwen }
2972a6061921SPascal van Leeuwen 
29731769f704SPascal van Leeuwen static int safexcel_aead_chachapoly_cra_init(struct crypto_tfm *tfm)
29741769f704SPascal van Leeuwen {
29751769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
29761769f704SPascal van Leeuwen 
29771769f704SPascal van Leeuwen 	safexcel_aead_fallback_cra_init(tfm);
29781769f704SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_CHACHA20;
29791769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32 |
29801769f704SPascal van Leeuwen 		    CONTEXT_CONTROL_CHACHA20_MODE_CALC_OTK;
2981098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
29821769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_POLY1305;
29831769f704SPascal van Leeuwen 	ctx->state_sz = 0; /* Precomputed by HW */
29841769f704SPascal van Leeuwen 	return 0;
29851769f704SPascal van Leeuwen }
29861769f704SPascal van Leeuwen 
29871769f704SPascal van Leeuwen static void safexcel_aead_fallback_cra_exit(struct crypto_tfm *tfm)
2988a6061921SPascal van Leeuwen {
2989a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2990a6061921SPascal van Leeuwen 
2991a6061921SPascal van Leeuwen 	crypto_free_aead(ctx->fback);
2992a6061921SPascal van Leeuwen 	safexcel_aead_cra_exit(tfm);
2993a6061921SPascal van Leeuwen }
2994a6061921SPascal van Leeuwen 
2995a6061921SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chachapoly = {
2996a6061921SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2997a6061921SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305,
2998a6061921SPascal van Leeuwen 	.alg.aead = {
2999a6061921SPascal van Leeuwen 		.setkey = safexcel_aead_chachapoly_setkey,
3000a6061921SPascal van Leeuwen 		.setauthsize = safexcel_aead_chachapoly_setauthsize,
3001a6061921SPascal van Leeuwen 		.encrypt = safexcel_aead_chachapoly_encrypt,
3002a6061921SPascal van Leeuwen 		.decrypt = safexcel_aead_chachapoly_decrypt,
3003a6061921SPascal van Leeuwen 		.ivsize = CHACHAPOLY_IV_SIZE,
3004a6061921SPascal van Leeuwen 		.maxauthsize = POLY1305_DIGEST_SIZE,
3005a6061921SPascal van Leeuwen 		.base = {
3006a6061921SPascal van Leeuwen 			.cra_name = "rfc7539(chacha20,poly1305)",
3007a6061921SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20-poly1305",
3008a6061921SPascal van Leeuwen 			/* +1 to put it above HW chacha + SW poly */
3009a6061921SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY + 1,
3010a6061921SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3011b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3012a6061921SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
3013a6061921SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
3014a6061921SPascal van Leeuwen 			.cra_blocksize = 1,
3015a6061921SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3016a6061921SPascal van Leeuwen 			.cra_alignmask = 0,
3017a6061921SPascal van Leeuwen 			.cra_init = safexcel_aead_chachapoly_cra_init,
30181769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
3019a6061921SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3020a6061921SPascal van Leeuwen 		},
3021a6061921SPascal van Leeuwen 	},
3022a6061921SPascal van Leeuwen };
3023a6061921SPascal van Leeuwen 
3024a6061921SPascal van Leeuwen static int safexcel_aead_chachapolyesp_cra_init(struct crypto_tfm *tfm)
3025a6061921SPascal van Leeuwen {
3026a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3027a6061921SPascal van Leeuwen 	int ret;
3028a6061921SPascal van Leeuwen 
3029a6061921SPascal van Leeuwen 	ret = safexcel_aead_chachapoly_cra_init(tfm);
3030a6061921SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3031098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3032a6061921SPascal van Leeuwen 	return ret;
3033a6061921SPascal van Leeuwen }
3034a6061921SPascal van Leeuwen 
3035a6061921SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chachapoly_esp = {
3036a6061921SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3037a6061921SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305,
3038a6061921SPascal van Leeuwen 	.alg.aead = {
3039a6061921SPascal van Leeuwen 		.setkey = safexcel_aead_chachapoly_setkey,
3040a6061921SPascal van Leeuwen 		.setauthsize = safexcel_aead_chachapoly_setauthsize,
3041a6061921SPascal van Leeuwen 		.encrypt = safexcel_aead_chachapoly_encrypt,
3042a6061921SPascal van Leeuwen 		.decrypt = safexcel_aead_chachapoly_decrypt,
3043a6061921SPascal van Leeuwen 		.ivsize = CHACHAPOLY_IV_SIZE - EIP197_AEAD_IPSEC_NONCE_SIZE,
3044a6061921SPascal van Leeuwen 		.maxauthsize = POLY1305_DIGEST_SIZE,
3045a6061921SPascal van Leeuwen 		.base = {
3046a6061921SPascal van Leeuwen 			.cra_name = "rfc7539esp(chacha20,poly1305)",
3047a6061921SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20-poly1305-esp",
3048a6061921SPascal van Leeuwen 			/* +1 to put it above HW chacha + SW poly */
3049a6061921SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY + 1,
3050a6061921SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3051b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3052a6061921SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
3053a6061921SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
3054a6061921SPascal van Leeuwen 			.cra_blocksize = 1,
3055a6061921SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3056a6061921SPascal van Leeuwen 			.cra_alignmask = 0,
3057a6061921SPascal van Leeuwen 			.cra_init = safexcel_aead_chachapolyesp_cra_init,
30581769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
3059a6061921SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3060a6061921SPascal van Leeuwen 		},
3061a6061921SPascal van Leeuwen 	},
3062a6061921SPascal van Leeuwen };
3063fcca797dSPascal van Leeuwen 
3064fcca797dSPascal van Leeuwen static int safexcel_skcipher_sm4_setkey(struct crypto_skcipher *ctfm,
3065fcca797dSPascal van Leeuwen 					const u8 *key, unsigned int len)
3066fcca797dSPascal van Leeuwen {
3067fcca797dSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3068fcca797dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
306918e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
3070fcca797dSPascal van Leeuwen 
3071674f368aSEric Biggers 	if (len != SM4_KEY_SIZE)
3072fcca797dSPascal van Leeuwen 		return -EINVAL;
3073fcca797dSPascal van Leeuwen 
307413a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
307513a1bb93SPascal van Leeuwen 		if (memcmp(ctx->key, key, SM4_KEY_SIZE))
3076fcca797dSPascal van Leeuwen 			ctx->base.needs_inv = true;
3077fcca797dSPascal van Leeuwen 
307813a1bb93SPascal van Leeuwen 	memcpy(ctx->key, key, SM4_KEY_SIZE);
3079fcca797dSPascal van Leeuwen 	ctx->key_len = SM4_KEY_SIZE;
3080fcca797dSPascal van Leeuwen 
3081fcca797dSPascal van Leeuwen 	return 0;
3082fcca797dSPascal van Leeuwen }
3083fcca797dSPascal van Leeuwen 
3084fcca797dSPascal van Leeuwen static int safexcel_sm4_blk_encrypt(struct skcipher_request *req)
3085fcca797dSPascal van Leeuwen {
3086fcca797dSPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
3087fcca797dSPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
3088fcca797dSPascal van Leeuwen 		return -EINVAL;
3089fcca797dSPascal van Leeuwen 	else
3090fcca797dSPascal van Leeuwen 		return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
3091fcca797dSPascal van Leeuwen 					  SAFEXCEL_ENCRYPT);
3092fcca797dSPascal van Leeuwen }
3093fcca797dSPascal van Leeuwen 
3094fcca797dSPascal van Leeuwen static int safexcel_sm4_blk_decrypt(struct skcipher_request *req)
3095fcca797dSPascal van Leeuwen {
3096fcca797dSPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
3097fcca797dSPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
3098fcca797dSPascal van Leeuwen 		return -EINVAL;
3099fcca797dSPascal van Leeuwen 	else
3100fcca797dSPascal van Leeuwen 		return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
3101fcca797dSPascal van Leeuwen 					  SAFEXCEL_DECRYPT);
3102fcca797dSPascal van Leeuwen }
3103fcca797dSPascal van Leeuwen 
3104fcca797dSPascal van Leeuwen static int safexcel_skcipher_sm4_ecb_cra_init(struct crypto_tfm *tfm)
3105fcca797dSPascal van Leeuwen {
3106fcca797dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3107fcca797dSPascal van Leeuwen 
3108fcca797dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
3109fcca797dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3110fcca797dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
3111098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
3112098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
3113fcca797dSPascal van Leeuwen 	return 0;
3114fcca797dSPascal van Leeuwen }
3115fcca797dSPascal van Leeuwen 
3116fcca797dSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ecb_sm4 = {
3117fcca797dSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
3118fcca797dSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
3119fcca797dSPascal van Leeuwen 	.alg.skcipher = {
3120fcca797dSPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
3121fcca797dSPascal van Leeuwen 		.encrypt = safexcel_sm4_blk_encrypt,
3122fcca797dSPascal van Leeuwen 		.decrypt = safexcel_sm4_blk_decrypt,
3123fcca797dSPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
3124fcca797dSPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
3125fcca797dSPascal van Leeuwen 		.base = {
3126fcca797dSPascal van Leeuwen 			.cra_name = "ecb(sm4)",
3127fcca797dSPascal van Leeuwen 			.cra_driver_name = "safexcel-ecb-sm4",
3128fcca797dSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3129fcca797dSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3130b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3131fcca797dSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3132fcca797dSPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
3133fcca797dSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3134fcca797dSPascal van Leeuwen 			.cra_alignmask = 0,
3135fcca797dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ecb_cra_init,
3136fcca797dSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
3137fcca797dSPascal van Leeuwen 			.cra_module = THIS_MODULE,
3138fcca797dSPascal van Leeuwen 		},
3139fcca797dSPascal van Leeuwen 	},
3140fcca797dSPascal van Leeuwen };
31416f2d1428SPascal van Leeuwen 
31426f2d1428SPascal van Leeuwen static int safexcel_skcipher_sm4_cbc_cra_init(struct crypto_tfm *tfm)
31436f2d1428SPascal van Leeuwen {
31446f2d1428SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
31456f2d1428SPascal van Leeuwen 
31466f2d1428SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
31476f2d1428SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3148098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
31496f2d1428SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
31506f2d1428SPascal van Leeuwen 	return 0;
31516f2d1428SPascal van Leeuwen }
31526f2d1428SPascal van Leeuwen 
31536f2d1428SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbc_sm4 = {
31546f2d1428SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
31556f2d1428SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
31566f2d1428SPascal van Leeuwen 	.alg.skcipher = {
31576f2d1428SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
31586f2d1428SPascal van Leeuwen 		.encrypt = safexcel_sm4_blk_encrypt,
31596f2d1428SPascal van Leeuwen 		.decrypt = safexcel_sm4_blk_decrypt,
31606f2d1428SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
31616f2d1428SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
31626f2d1428SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
31636f2d1428SPascal van Leeuwen 		.base = {
31646f2d1428SPascal van Leeuwen 			.cra_name = "cbc(sm4)",
31656f2d1428SPascal van Leeuwen 			.cra_driver_name = "safexcel-cbc-sm4",
31666f2d1428SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
31676f2d1428SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3168b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
31696f2d1428SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
31706f2d1428SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
31716f2d1428SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
31726f2d1428SPascal van Leeuwen 			.cra_alignmask = 0,
31736f2d1428SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_cbc_cra_init,
31746f2d1428SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
31756f2d1428SPascal van Leeuwen 			.cra_module = THIS_MODULE,
31766f2d1428SPascal van Leeuwen 		},
31776f2d1428SPascal van Leeuwen 	},
31786f2d1428SPascal van Leeuwen };
317903a6cfb9SPascal van Leeuwen 
318003a6cfb9SPascal van Leeuwen static int safexcel_skcipher_sm4_ofb_cra_init(struct crypto_tfm *tfm)
318103a6cfb9SPascal van Leeuwen {
318203a6cfb9SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
318303a6cfb9SPascal van Leeuwen 
318403a6cfb9SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
318503a6cfb9SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3186098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
318703a6cfb9SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB;
318803a6cfb9SPascal van Leeuwen 	return 0;
318903a6cfb9SPascal van Leeuwen }
319003a6cfb9SPascal van Leeuwen 
319103a6cfb9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ofb_sm4 = {
319203a6cfb9SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
319303a6cfb9SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB,
319403a6cfb9SPascal van Leeuwen 	.alg.skcipher = {
319503a6cfb9SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
319603a6cfb9SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
319703a6cfb9SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
319803a6cfb9SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
319903a6cfb9SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
320003a6cfb9SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
320103a6cfb9SPascal van Leeuwen 		.base = {
320203a6cfb9SPascal van Leeuwen 			.cra_name = "ofb(sm4)",
320303a6cfb9SPascal van Leeuwen 			.cra_driver_name = "safexcel-ofb-sm4",
320403a6cfb9SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
320503a6cfb9SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3206b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
320703a6cfb9SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
320803a6cfb9SPascal van Leeuwen 			.cra_blocksize = 1,
320903a6cfb9SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
321003a6cfb9SPascal van Leeuwen 			.cra_alignmask = 0,
321103a6cfb9SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ofb_cra_init,
321203a6cfb9SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
321303a6cfb9SPascal van Leeuwen 			.cra_module = THIS_MODULE,
321403a6cfb9SPascal van Leeuwen 		},
321503a6cfb9SPascal van Leeuwen 	},
321603a6cfb9SPascal van Leeuwen };
32177468ab22SPascal van Leeuwen 
32187468ab22SPascal van Leeuwen static int safexcel_skcipher_sm4_cfb_cra_init(struct crypto_tfm *tfm)
32197468ab22SPascal van Leeuwen {
32207468ab22SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
32217468ab22SPascal van Leeuwen 
32227468ab22SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
32237468ab22SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3224098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
32257468ab22SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB;
32267468ab22SPascal van Leeuwen 	return 0;
32277468ab22SPascal van Leeuwen }
32287468ab22SPascal van Leeuwen 
32297468ab22SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cfb_sm4 = {
32307468ab22SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
32317468ab22SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB,
32327468ab22SPascal van Leeuwen 	.alg.skcipher = {
32337468ab22SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
32347468ab22SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
32357468ab22SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
32367468ab22SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
32377468ab22SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
32387468ab22SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
32397468ab22SPascal van Leeuwen 		.base = {
32407468ab22SPascal van Leeuwen 			.cra_name = "cfb(sm4)",
32417468ab22SPascal van Leeuwen 			.cra_driver_name = "safexcel-cfb-sm4",
32427468ab22SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
32437468ab22SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3244b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
32457468ab22SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
32467468ab22SPascal van Leeuwen 			.cra_blocksize = 1,
32477468ab22SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
32487468ab22SPascal van Leeuwen 			.cra_alignmask = 0,
32497468ab22SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_cfb_cra_init,
32507468ab22SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
32517468ab22SPascal van Leeuwen 			.cra_module = THIS_MODULE,
32527468ab22SPascal van Leeuwen 		},
32537468ab22SPascal van Leeuwen 	},
32547468ab22SPascal van Leeuwen };
3255f77e5dc0SPascal van Leeuwen 
3256f77e5dc0SPascal van Leeuwen static int safexcel_skcipher_sm4ctr_setkey(struct crypto_skcipher *ctfm,
3257f77e5dc0SPascal van Leeuwen 					   const u8 *key, unsigned int len)
3258f77e5dc0SPascal van Leeuwen {
3259f77e5dc0SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3260f77e5dc0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3261f77e5dc0SPascal van Leeuwen 
3262f77e5dc0SPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
3263f77e5dc0SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
3264f77e5dc0SPascal van Leeuwen 	/* exclude the nonce here */
3265f77e5dc0SPascal van Leeuwen 	len -= CTR_RFC3686_NONCE_SIZE;
3266f77e5dc0SPascal van Leeuwen 
3267f77e5dc0SPascal van Leeuwen 	return safexcel_skcipher_sm4_setkey(ctfm, key, len);
3268f77e5dc0SPascal van Leeuwen }
3269f77e5dc0SPascal van Leeuwen 
3270f77e5dc0SPascal van Leeuwen static int safexcel_skcipher_sm4_ctr_cra_init(struct crypto_tfm *tfm)
3271f77e5dc0SPascal van Leeuwen {
3272f77e5dc0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3273f77e5dc0SPascal van Leeuwen 
3274f77e5dc0SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
3275f77e5dc0SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3276098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
3277f77e5dc0SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
3278f77e5dc0SPascal van Leeuwen 	return 0;
3279f77e5dc0SPascal van Leeuwen }
3280f77e5dc0SPascal van Leeuwen 
3281f77e5dc0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ctr_sm4 = {
3282f77e5dc0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
3283f77e5dc0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
3284f77e5dc0SPascal van Leeuwen 	.alg.skcipher = {
3285f77e5dc0SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4ctr_setkey,
3286f77e5dc0SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
3287f77e5dc0SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
3288f77e5dc0SPascal van Leeuwen 		/* Add nonce size */
3289f77e5dc0SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
3290f77e5dc0SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
3291f77e5dc0SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
3292f77e5dc0SPascal van Leeuwen 		.base = {
3293f77e5dc0SPascal van Leeuwen 			.cra_name = "rfc3686(ctr(sm4))",
3294f77e5dc0SPascal van Leeuwen 			.cra_driver_name = "safexcel-ctr-sm4",
3295f77e5dc0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3296f77e5dc0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3297b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3298f77e5dc0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3299f77e5dc0SPascal van Leeuwen 			.cra_blocksize = 1,
3300f77e5dc0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3301f77e5dc0SPascal van Leeuwen 			.cra_alignmask = 0,
3302f77e5dc0SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ctr_cra_init,
3303f77e5dc0SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
3304f77e5dc0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3305f77e5dc0SPascal van Leeuwen 		},
3306f77e5dc0SPascal van Leeuwen 	},
3307f77e5dc0SPascal van Leeuwen };
33081769f704SPascal van Leeuwen 
33091769f704SPascal van Leeuwen static int safexcel_aead_sm4_blk_encrypt(struct aead_request *req)
33101769f704SPascal van Leeuwen {
33111769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
33121769f704SPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
33131769f704SPascal van Leeuwen 		return -EINVAL;
33141769f704SPascal van Leeuwen 
33151769f704SPascal van Leeuwen 	return safexcel_queue_req(&req->base, aead_request_ctx(req),
33161769f704SPascal van Leeuwen 				  SAFEXCEL_ENCRYPT);
33171769f704SPascal van Leeuwen }
33181769f704SPascal van Leeuwen 
33191769f704SPascal van Leeuwen static int safexcel_aead_sm4_blk_decrypt(struct aead_request *req)
33201769f704SPascal van Leeuwen {
33211769f704SPascal van Leeuwen 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
33221769f704SPascal van Leeuwen 
33231769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
33241769f704SPascal van Leeuwen 	if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1))
33251769f704SPascal van Leeuwen 		return -EINVAL;
33261769f704SPascal van Leeuwen 
33271769f704SPascal van Leeuwen 	return safexcel_queue_req(&req->base, aead_request_ctx(req),
33281769f704SPascal van Leeuwen 				  SAFEXCEL_DECRYPT);
33291769f704SPascal van Leeuwen }
33301769f704SPascal van Leeuwen 
33311769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sha1_cra_init(struct crypto_tfm *tfm)
33321769f704SPascal van Leeuwen {
33331769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33341769f704SPascal van Leeuwen 
33351769f704SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
33361769f704SPascal van Leeuwen 	ctx->alg = SAFEXCEL_SM4;
3337098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
33381769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
33391769f704SPascal van Leeuwen 	ctx->state_sz = SHA1_DIGEST_SIZE;
33401769f704SPascal van Leeuwen 	return 0;
33411769f704SPascal van Leeuwen }
33421769f704SPascal van Leeuwen 
33431769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_sm4 = {
33441769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
33451769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1,
33461769f704SPascal van Leeuwen 	.alg.aead = {
33471769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
33481769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_sm4_blk_encrypt,
33491769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_sm4_blk_decrypt,
33501769f704SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
33511769f704SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
33521769f704SPascal van Leeuwen 		.base = {
33531769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(sm4))",
33541769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-sm4",
33551769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
33561769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3357b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
33581769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
33591769f704SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
33601769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
33611769f704SPascal van Leeuwen 			.cra_alignmask = 0,
33621769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4cbc_sha1_cra_init,
33631769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
33641769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
33651769f704SPascal van Leeuwen 		},
33661769f704SPascal van Leeuwen 	},
33671769f704SPascal van Leeuwen };
33681769f704SPascal van Leeuwen 
33691769f704SPascal van Leeuwen static int safexcel_aead_fallback_setkey(struct crypto_aead *ctfm,
33701769f704SPascal van Leeuwen 					 const u8 *key, unsigned int len)
33711769f704SPascal van Leeuwen {
33721769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
33731769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33741769f704SPascal van Leeuwen 
33751769f704SPascal van Leeuwen 	/* Keep fallback cipher synchronized */
33761769f704SPascal van Leeuwen 	return crypto_aead_setkey(ctx->fback, (u8 *)key, len) ?:
33771769f704SPascal van Leeuwen 	       safexcel_aead_setkey(ctfm, key, len);
33781769f704SPascal van Leeuwen }
33791769f704SPascal van Leeuwen 
33801769f704SPascal van Leeuwen static int safexcel_aead_fallback_setauthsize(struct crypto_aead *ctfm,
33811769f704SPascal van Leeuwen 					      unsigned int authsize)
33821769f704SPascal van Leeuwen {
33831769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
33841769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33851769f704SPascal van Leeuwen 
33861769f704SPascal van Leeuwen 	/* Keep fallback cipher synchronized */
33871769f704SPascal van Leeuwen 	return crypto_aead_setauthsize(ctx->fback, authsize);
33881769f704SPascal van Leeuwen }
33891769f704SPascal van Leeuwen 
33901769f704SPascal van Leeuwen static int safexcel_aead_fallback_crypt(struct aead_request *req,
33911769f704SPascal van Leeuwen 					enum safexcel_cipher_direction dir)
33921769f704SPascal van Leeuwen {
33931769f704SPascal van Leeuwen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
33941769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
33951769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33961769f704SPascal van Leeuwen 	struct aead_request *subreq = aead_request_ctx(req);
33971769f704SPascal van Leeuwen 
33981769f704SPascal van Leeuwen 	aead_request_set_tfm(subreq, ctx->fback);
33991769f704SPascal van Leeuwen 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
34001769f704SPascal van Leeuwen 				  req->base.data);
34011769f704SPascal van Leeuwen 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
34021769f704SPascal van Leeuwen 			       req->iv);
34031769f704SPascal van Leeuwen 	aead_request_set_ad(subreq, req->assoclen);
34041769f704SPascal van Leeuwen 
34051769f704SPascal van Leeuwen 	return (dir ==  SAFEXCEL_ENCRYPT) ?
34061769f704SPascal van Leeuwen 		crypto_aead_encrypt(subreq) :
34071769f704SPascal van Leeuwen 		crypto_aead_decrypt(subreq);
34081769f704SPascal van Leeuwen }
34091769f704SPascal van Leeuwen 
34101769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_encrypt(struct aead_request *req)
34111769f704SPascal van Leeuwen {
34121769f704SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
34131769f704SPascal van Leeuwen 
34141769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
34151769f704SPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
34161769f704SPascal van Leeuwen 		return -EINVAL;
34171769f704SPascal van Leeuwen 	else if (req->cryptlen || req->assoclen) /* If input length > 0 only */
34181769f704SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
34191769f704SPascal van Leeuwen 
34201769f704SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
34211769f704SPascal van Leeuwen 	return safexcel_aead_fallback_crypt(req, SAFEXCEL_ENCRYPT);
34221769f704SPascal van Leeuwen }
34231769f704SPascal van Leeuwen 
34241769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_decrypt(struct aead_request *req)
34251769f704SPascal van Leeuwen {
34261769f704SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
34271769f704SPascal van Leeuwen 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
34281769f704SPascal van Leeuwen 
34291769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
34301769f704SPascal van Leeuwen 	if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1))
34311769f704SPascal van Leeuwen 		return -EINVAL;
34321769f704SPascal van Leeuwen 	else if (req->cryptlen > crypto_aead_authsize(tfm) || req->assoclen)
34331769f704SPascal van Leeuwen 		/* If input length > 0 only */
34341769f704SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
34351769f704SPascal van Leeuwen 
34361769f704SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
34371769f704SPascal van Leeuwen 	return safexcel_aead_fallback_crypt(req, SAFEXCEL_DECRYPT);
34381769f704SPascal van Leeuwen }
34391769f704SPascal van Leeuwen 
34401769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_cra_init(struct crypto_tfm *tfm)
34411769f704SPascal van Leeuwen {
34421769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34431769f704SPascal van Leeuwen 
34441769f704SPascal van Leeuwen 	safexcel_aead_fallback_cra_init(tfm);
34451769f704SPascal van Leeuwen 	ctx->alg = SAFEXCEL_SM4;
3446098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
34471769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
34481769f704SPascal van Leeuwen 	ctx->state_sz = SM3_DIGEST_SIZE;
34491769f704SPascal van Leeuwen 	return 0;
34501769f704SPascal van Leeuwen }
34511769f704SPascal van Leeuwen 
34521769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_cbc_sm4 = {
34531769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
34541769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3,
34551769f704SPascal van Leeuwen 	.alg.aead = {
34561769f704SPascal van Leeuwen 		.setkey = safexcel_aead_fallback_setkey,
34571769f704SPascal van Leeuwen 		.setauthsize = safexcel_aead_fallback_setauthsize,
34581769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_sm4cbc_sm3_encrypt,
34591769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_sm4cbc_sm3_decrypt,
34601769f704SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
34611769f704SPascal van Leeuwen 		.maxauthsize = SM3_DIGEST_SIZE,
34621769f704SPascal van Leeuwen 		.base = {
34631769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sm3),cbc(sm4))",
34641769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sm3-cbc-sm4",
34651769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
34661769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3467b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
34681769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
34691769f704SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
34701769f704SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
34711769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
34721769f704SPascal van Leeuwen 			.cra_alignmask = 0,
34731769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4cbc_sm3_cra_init,
34741769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
34751769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
34761769f704SPascal van Leeuwen 		},
34771769f704SPascal van Leeuwen 	},
34781769f704SPascal van Leeuwen };
34791769f704SPascal van Leeuwen 
34801769f704SPascal van Leeuwen static int safexcel_aead_sm4ctr_sha1_cra_init(struct crypto_tfm *tfm)
34811769f704SPascal van Leeuwen {
34821769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34831769f704SPascal van Leeuwen 
34841769f704SPascal van Leeuwen 	safexcel_aead_sm4cbc_sha1_cra_init(tfm);
34851769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
34861769f704SPascal van Leeuwen 	return 0;
34871769f704SPascal van Leeuwen }
34881769f704SPascal van Leeuwen 
34891769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_sm4 = {
34901769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
34911769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1,
34921769f704SPascal van Leeuwen 	.alg.aead = {
34931769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
34941769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
34951769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
34961769f704SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
34971769f704SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
34981769f704SPascal van Leeuwen 		.base = {
34991769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),rfc3686(ctr(sm4)))",
35001769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-sm4",
35011769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
35021769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3503b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
35041769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
35051769f704SPascal van Leeuwen 			.cra_blocksize = 1,
35061769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
35071769f704SPascal van Leeuwen 			.cra_alignmask = 0,
35081769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4ctr_sha1_cra_init,
35091769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
35101769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
35111769f704SPascal van Leeuwen 		},
35121769f704SPascal van Leeuwen 	},
35131769f704SPascal van Leeuwen };
35141769f704SPascal van Leeuwen 
35151769f704SPascal van Leeuwen static int safexcel_aead_sm4ctr_sm3_cra_init(struct crypto_tfm *tfm)
35161769f704SPascal van Leeuwen {
35171769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
35181769f704SPascal van Leeuwen 
35191769f704SPascal van Leeuwen 	safexcel_aead_sm4cbc_sm3_cra_init(tfm);
35201769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
35211769f704SPascal van Leeuwen 	return 0;
35221769f704SPascal van Leeuwen }
35231769f704SPascal van Leeuwen 
35241769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_ctr_sm4 = {
35251769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
35261769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3,
35271769f704SPascal van Leeuwen 	.alg.aead = {
35281769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
35291769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
35301769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
35311769f704SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
35321769f704SPascal van Leeuwen 		.maxauthsize = SM3_DIGEST_SIZE,
35331769f704SPascal van Leeuwen 		.base = {
35341769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sm3),rfc3686(ctr(sm4)))",
35351769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sm3-ctr-sm4",
35361769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
35371769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3538b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
35391769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
35401769f704SPascal van Leeuwen 			.cra_blocksize = 1,
35411769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
35421769f704SPascal van Leeuwen 			.cra_alignmask = 0,
35431769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4ctr_sm3_cra_init,
35441769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
35451769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
35461769f704SPascal van Leeuwen 		},
35471769f704SPascal van Leeuwen 	},
35481769f704SPascal van Leeuwen };
3549a19052d4SPascal van Leeuwen 
3550a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_setkey(struct crypto_aead *ctfm, const u8 *key,
3551a19052d4SPascal van Leeuwen 				       unsigned int len)
3552a19052d4SPascal van Leeuwen {
3553a19052d4SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
3554a19052d4SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3555a19052d4SPascal van Leeuwen 
3556a19052d4SPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
3557a19052d4SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
3558a19052d4SPascal van Leeuwen 
3559a19052d4SPascal van Leeuwen 	len -= CTR_RFC3686_NONCE_SIZE;
3560a19052d4SPascal van Leeuwen 	return safexcel_aead_gcm_setkey(ctfm, key, len);
3561a19052d4SPascal van Leeuwen }
3562a19052d4SPascal van Leeuwen 
3563a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_setauthsize(struct crypto_aead *tfm,
3564a19052d4SPascal van Leeuwen 					    unsigned int authsize)
3565a19052d4SPascal van Leeuwen {
3566a19052d4SPascal van Leeuwen 	return crypto_rfc4106_check_authsize(authsize);
3567a19052d4SPascal van Leeuwen }
3568a19052d4SPascal van Leeuwen 
3569a19052d4SPascal van Leeuwen static int safexcel_rfc4106_encrypt(struct aead_request *req)
3570a19052d4SPascal van Leeuwen {
3571a19052d4SPascal van Leeuwen 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
3572a19052d4SPascal van Leeuwen 	       safexcel_aead_encrypt(req);
3573a19052d4SPascal van Leeuwen }
3574a19052d4SPascal van Leeuwen 
3575a19052d4SPascal van Leeuwen static int safexcel_rfc4106_decrypt(struct aead_request *req)
3576a19052d4SPascal van Leeuwen {
3577a19052d4SPascal van Leeuwen 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
3578a19052d4SPascal van Leeuwen 	       safexcel_aead_decrypt(req);
3579a19052d4SPascal van Leeuwen }
3580a19052d4SPascal van Leeuwen 
3581a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_cra_init(struct crypto_tfm *tfm)
3582a19052d4SPascal van Leeuwen {
3583a19052d4SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3584a19052d4SPascal van Leeuwen 	int ret;
3585a19052d4SPascal van Leeuwen 
3586a19052d4SPascal van Leeuwen 	ret = safexcel_aead_gcm_cra_init(tfm);
3587a19052d4SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3588098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3589a19052d4SPascal van Leeuwen 	return ret;
3590a19052d4SPascal van Leeuwen }
3591a19052d4SPascal van Leeuwen 
3592a19052d4SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4106_gcm = {
3593a19052d4SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3594a19052d4SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
3595a19052d4SPascal van Leeuwen 	.alg.aead = {
3596a19052d4SPascal van Leeuwen 		.setkey = safexcel_rfc4106_gcm_setkey,
3597a19052d4SPascal van Leeuwen 		.setauthsize = safexcel_rfc4106_gcm_setauthsize,
3598a19052d4SPascal van Leeuwen 		.encrypt = safexcel_rfc4106_encrypt,
3599a19052d4SPascal van Leeuwen 		.decrypt = safexcel_rfc4106_decrypt,
3600a19052d4SPascal van Leeuwen 		.ivsize = GCM_RFC4106_IV_SIZE,
3601a19052d4SPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
3602a19052d4SPascal van Leeuwen 		.base = {
3603a19052d4SPascal van Leeuwen 			.cra_name = "rfc4106(gcm(aes))",
3604a19052d4SPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4106-gcm-aes",
3605a19052d4SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3606a19052d4SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3607b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3608a19052d4SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3609a19052d4SPascal van Leeuwen 			.cra_blocksize = 1,
3610a19052d4SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3611a19052d4SPascal van Leeuwen 			.cra_alignmask = 0,
3612a19052d4SPascal van Leeuwen 			.cra_init = safexcel_rfc4106_gcm_cra_init,
3613a19052d4SPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
3614a19052d4SPascal van Leeuwen 		},
3615a19052d4SPascal van Leeuwen 	},
3616a19052d4SPascal van Leeuwen };
361792c60cefSPascal van Leeuwen 
361892c60cefSPascal van Leeuwen static int safexcel_rfc4543_gcm_setauthsize(struct crypto_aead *tfm,
361992c60cefSPascal van Leeuwen 					    unsigned int authsize)
362092c60cefSPascal van Leeuwen {
362192c60cefSPascal van Leeuwen 	if (authsize != GHASH_DIGEST_SIZE)
362292c60cefSPascal van Leeuwen 		return -EINVAL;
362392c60cefSPascal van Leeuwen 
362492c60cefSPascal van Leeuwen 	return 0;
362592c60cefSPascal van Leeuwen }
362692c60cefSPascal van Leeuwen 
362792c60cefSPascal van Leeuwen static int safexcel_rfc4543_gcm_cra_init(struct crypto_tfm *tfm)
362892c60cefSPascal van Leeuwen {
362992c60cefSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
363092c60cefSPascal van Leeuwen 	int ret;
363192c60cefSPascal van Leeuwen 
363292c60cefSPascal van Leeuwen 	ret = safexcel_aead_gcm_cra_init(tfm);
363392c60cefSPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP_GMAC;
363492c60cefSPascal van Leeuwen 	return ret;
363592c60cefSPascal van Leeuwen }
363692c60cefSPascal van Leeuwen 
363792c60cefSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4543_gcm = {
363892c60cefSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
363992c60cefSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
364092c60cefSPascal van Leeuwen 	.alg.aead = {
364192c60cefSPascal van Leeuwen 		.setkey = safexcel_rfc4106_gcm_setkey,
364292c60cefSPascal van Leeuwen 		.setauthsize = safexcel_rfc4543_gcm_setauthsize,
364392c60cefSPascal van Leeuwen 		.encrypt = safexcel_rfc4106_encrypt,
364492c60cefSPascal van Leeuwen 		.decrypt = safexcel_rfc4106_decrypt,
364592c60cefSPascal van Leeuwen 		.ivsize = GCM_RFC4543_IV_SIZE,
364692c60cefSPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
364792c60cefSPascal van Leeuwen 		.base = {
364892c60cefSPascal van Leeuwen 			.cra_name = "rfc4543(gcm(aes))",
364992c60cefSPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4543-gcm-aes",
365092c60cefSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
365192c60cefSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3652b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
365392c60cefSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
365492c60cefSPascal van Leeuwen 			.cra_blocksize = 1,
365592c60cefSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
365692c60cefSPascal van Leeuwen 			.cra_alignmask = 0,
365792c60cefSPascal van Leeuwen 			.cra_init = safexcel_rfc4543_gcm_cra_init,
365892c60cefSPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
365992c60cefSPascal van Leeuwen 		},
366092c60cefSPascal van Leeuwen 	},
366192c60cefSPascal van Leeuwen };
3662a9a89624SPascal van Leeuwen 
3663a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_setkey(struct crypto_aead *ctfm, const u8 *key,
3664a9a89624SPascal van Leeuwen 				       unsigned int len)
3665a9a89624SPascal van Leeuwen {
3666a9a89624SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
3667a9a89624SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3668a9a89624SPascal van Leeuwen 
3669a9a89624SPascal van Leeuwen 	/* First byte of the nonce = L = always 3 for RFC4309 (4 byte ctr) */
3670a9a89624SPascal van Leeuwen 	*(u8 *)&ctx->nonce = EIP197_AEAD_IPSEC_COUNTER_SIZE - 1;
3671a9a89624SPascal van Leeuwen 	/* last 3 bytes of key are the nonce! */
3672a9a89624SPascal van Leeuwen 	memcpy((u8 *)&ctx->nonce + 1, key + len -
3673a9a89624SPascal van Leeuwen 	       EIP197_AEAD_IPSEC_CCM_NONCE_SIZE,
3674a9a89624SPascal van Leeuwen 	       EIP197_AEAD_IPSEC_CCM_NONCE_SIZE);
3675a9a89624SPascal van Leeuwen 
3676a9a89624SPascal van Leeuwen 	len -= EIP197_AEAD_IPSEC_CCM_NONCE_SIZE;
3677a9a89624SPascal van Leeuwen 	return safexcel_aead_ccm_setkey(ctfm, key, len);
3678a9a89624SPascal van Leeuwen }
3679a9a89624SPascal van Leeuwen 
3680a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_setauthsize(struct crypto_aead *tfm,
3681a9a89624SPascal van Leeuwen 					    unsigned int authsize)
3682a9a89624SPascal van Leeuwen {
3683a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3684a9a89624SPascal van Leeuwen 	switch (authsize) {
3685a9a89624SPascal van Leeuwen 	case 8:
3686a9a89624SPascal van Leeuwen 	case 12:
3687a9a89624SPascal van Leeuwen 	case 16:
3688a9a89624SPascal van Leeuwen 		break;
3689a9a89624SPascal van Leeuwen 	default:
3690a9a89624SPascal van Leeuwen 		return -EINVAL;
3691a9a89624SPascal van Leeuwen 	}
3692a9a89624SPascal van Leeuwen 
3693a9a89624SPascal van Leeuwen 	return 0;
3694a9a89624SPascal van Leeuwen }
3695a9a89624SPascal van Leeuwen 
3696a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_encrypt(struct aead_request *req)
3697a9a89624SPascal van Leeuwen {
3698a9a89624SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
3699a9a89624SPascal van Leeuwen 
3700a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3701a9a89624SPascal van Leeuwen 	if (req->assoclen != 16 && req->assoclen != 20)
3702a9a89624SPascal van Leeuwen 		return -EINVAL;
3703a9a89624SPascal van Leeuwen 
3704a9a89624SPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
3705a9a89624SPascal van Leeuwen }
3706a9a89624SPascal van Leeuwen 
3707a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_decrypt(struct aead_request *req)
3708a9a89624SPascal van Leeuwen {
3709a9a89624SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
3710a9a89624SPascal van Leeuwen 
3711a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3712a9a89624SPascal van Leeuwen 	if (req->assoclen != 16 && req->assoclen != 20)
3713a9a89624SPascal van Leeuwen 		return -EINVAL;
3714a9a89624SPascal van Leeuwen 
3715a9a89624SPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
3716a9a89624SPascal van Leeuwen }
3717a9a89624SPascal van Leeuwen 
3718a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_cra_init(struct crypto_tfm *tfm)
3719a9a89624SPascal van Leeuwen {
3720a9a89624SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3721a9a89624SPascal van Leeuwen 	int ret;
3722a9a89624SPascal van Leeuwen 
3723a9a89624SPascal van Leeuwen 	ret = safexcel_aead_ccm_cra_init(tfm);
3724a9a89624SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3725098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3726a9a89624SPascal van Leeuwen 	return ret;
3727a9a89624SPascal van Leeuwen }
3728a9a89624SPascal van Leeuwen 
3729a9a89624SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4309_ccm = {
3730a9a89624SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3731a9a89624SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL,
3732a9a89624SPascal van Leeuwen 	.alg.aead = {
3733a9a89624SPascal van Leeuwen 		.setkey = safexcel_rfc4309_ccm_setkey,
3734a9a89624SPascal van Leeuwen 		.setauthsize = safexcel_rfc4309_ccm_setauthsize,
3735a9a89624SPascal van Leeuwen 		.encrypt = safexcel_rfc4309_ccm_encrypt,
3736a9a89624SPascal van Leeuwen 		.decrypt = safexcel_rfc4309_ccm_decrypt,
3737a9a89624SPascal van Leeuwen 		.ivsize = EIP197_AEAD_IPSEC_IV_SIZE,
3738a9a89624SPascal van Leeuwen 		.maxauthsize = AES_BLOCK_SIZE,
3739a9a89624SPascal van Leeuwen 		.base = {
3740a9a89624SPascal van Leeuwen 			.cra_name = "rfc4309(ccm(aes))",
3741a9a89624SPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4309-ccm-aes",
3742a9a89624SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3743a9a89624SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3744b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3745a9a89624SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3746a9a89624SPascal van Leeuwen 			.cra_blocksize = 1,
3747a9a89624SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3748a9a89624SPascal van Leeuwen 			.cra_alignmask = 0,
3749a9a89624SPascal van Leeuwen 			.cra_init = safexcel_rfc4309_ccm_cra_init,
3750a9a89624SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
3751a9a89624SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3752a9a89624SPascal van Leeuwen 		},
3753a9a89624SPascal van Leeuwen 	},
3754a9a89624SPascal van Leeuwen };
3755