1301422e3SAntoine Tenart // SPDX-License-Identifier: GPL-2.0
21b44c5a6SAntoine Ténart /*
31b44c5a6SAntoine Ténart  * Copyright (C) 2017 Marvell
41b44c5a6SAntoine Ténart  *
51b44c5a6SAntoine Ténart  * Antoine Tenart <antoine.tenart@free-electrons.com>
61b44c5a6SAntoine Ténart  */
71b44c5a6SAntoine Ténart 
84a593fb3SPascal van Leeuwen #include <asm/unaligned.h>
91b44c5a6SAntoine Ténart #include <linux/device.h>
101b44c5a6SAntoine Ténart #include <linux/dma-mapping.h>
111b44c5a6SAntoine Ténart #include <linux/dmapool.h>
12f6beaea3SAntoine Tenart #include <crypto/aead.h>
131b44c5a6SAntoine Ténart #include <crypto/aes.h>
14f6beaea3SAntoine Tenart #include <crypto/authenc.h>
154a593fb3SPascal van Leeuwen #include <crypto/chacha.h>
16f26882a3SPascal van Leeuwen #include <crypto/ctr.h>
1704007b0eSArd Biesheuvel #include <crypto/internal/des.h>
183e450886SPascal van Leeuwen #include <crypto/gcm.h>
193e450886SPascal van Leeuwen #include <crypto/ghash.h>
20a6061921SPascal van Leeuwen #include <crypto/poly1305.h>
21a24d22b2SEric Biggers #include <crypto/sha1.h>
22a24d22b2SEric Biggers #include <crypto/sha2.h>
231769f704SPascal van Leeuwen #include <crypto/sm3.h>
24fcca797dSPascal van Leeuwen #include <crypto/sm4.h>
25c7da38a7SPascal van Leeuwen #include <crypto/xts.h>
261b44c5a6SAntoine Ténart #include <crypto/skcipher.h>
27f6beaea3SAntoine Tenart #include <crypto/internal/aead.h>
281eb7b403SOfer Heifetz #include <crypto/internal/skcipher.h>
291b44c5a6SAntoine Ténart 
301b44c5a6SAntoine Ténart #include "safexcel.h"
311b44c5a6SAntoine Ténart 
321b44c5a6SAntoine Ténart enum safexcel_cipher_direction {
331b44c5a6SAntoine Ténart 	SAFEXCEL_ENCRYPT,
341b44c5a6SAntoine Ténart 	SAFEXCEL_DECRYPT,
351b44c5a6SAntoine Ténart };
361b44c5a6SAntoine Ténart 
37a7dea8c0SOfer Heifetz enum safexcel_cipher_alg {
38a7dea8c0SOfer Heifetz 	SAFEXCEL_DES,
3962469879SOfer Heifetz 	SAFEXCEL_3DES,
40a7dea8c0SOfer Heifetz 	SAFEXCEL_AES,
414a593fb3SPascal van Leeuwen 	SAFEXCEL_CHACHA20,
42fcca797dSPascal van Leeuwen 	SAFEXCEL_SM4,
43a7dea8c0SOfer Heifetz };
44a7dea8c0SOfer Heifetz 
451b44c5a6SAntoine Ténart struct safexcel_cipher_ctx {
461b44c5a6SAntoine Ténart 	struct safexcel_context base;
471b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv;
481b44c5a6SAntoine Ténart 
491b44c5a6SAntoine Ténart 	u32 mode;
50a7dea8c0SOfer Heifetz 	enum safexcel_cipher_alg alg;
51098e51e5SPascal van Leeuwen 	u8 aead; /* !=0=AEAD, 2=IPSec ESP AEAD, 3=IPsec ESP GMAC */
52098e51e5SPascal van Leeuwen 	u8 xcm;  /* 0=authenc, 1=GCM, 2 reserved for CCM */
53098e51e5SPascal van Leeuwen 	u8 aadskip;
54098e51e5SPascal van Leeuwen 	u8 blocksz;
55098e51e5SPascal van Leeuwen 	u32 ivmask;
56098e51e5SPascal van Leeuwen 	u32 ctrinit;
571b44c5a6SAntoine Ténart 
58c7da38a7SPascal van Leeuwen 	__le32 key[16];
5954f9e8faSPascal van Leeuwen 	u32 nonce;
60c7da38a7SPascal van Leeuwen 	unsigned int key_len, xts;
61f6beaea3SAntoine Tenart 
62f6beaea3SAntoine Tenart 	/* All the below is AEAD specific */
63a7dea8c0SOfer Heifetz 	u32 hash_alg;
64f6beaea3SAntoine Tenart 	u32 state_sz;
653e450886SPascal van Leeuwen 
66a6061921SPascal van Leeuwen 	struct crypto_aead *fback;
671b44c5a6SAntoine Ténart };
681b44c5a6SAntoine Ténart 
691eb7b403SOfer Heifetz struct safexcel_cipher_req {
70847ccfc5SOfer Heifetz 	enum safexcel_cipher_direction direction;
7189332590SAntoine Tenart 	/* Number of result descriptors associated to the request */
7289332590SAntoine Tenart 	unsigned int rdescs;
731eb7b403SOfer Heifetz 	bool needs_inv;
7419b347b3SPascal van Leeuwen 	int  nr_src, nr_dst;
751eb7b403SOfer Heifetz };
761eb7b403SOfer Heifetz 
safexcel_skcipher_iv(struct safexcel_cipher_ctx * ctx,u8 * iv,struct safexcel_command_desc * cdesc)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 
safexcel_skcipher_token(struct safexcel_cipher_ctx * ctx,u8 * iv,struct safexcel_command_desc * cdesc,struct safexcel_token * atoken,u32 length)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 
safexcel_aead_iv(struct safexcel_cipher_ctx * ctx,u8 * iv,struct safexcel_command_desc * cdesc)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 
safexcel_aead_token(struct safexcel_cipher_ctx * ctx,u8 * iv,struct safexcel_command_desc * cdesc,struct safexcel_token * atoken,enum safexcel_cipher_direction direction,u32 cryptlen,u32 assoclen,u32 digestsize)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 
safexcel_skcipher_aes_setkey(struct crypto_skcipher * ctfm,const u8 * key,unsigned int len)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 
safexcel_aead_setkey(struct crypto_aead * ctfm,const u8 * key,unsigned int len)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 
safexcel_context_control(struct safexcel_cipher_ctx * ctx,struct crypto_async_request * async,struct safexcel_cipher_req * sreq,struct safexcel_command_desc * cdesc)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 
safexcel_handle_req_result(struct safexcel_crypto_priv * priv,int ring,struct crypto_async_request * async,struct scatterlist * src,struct scatterlist * dst,unsigned int cryptlen,struct safexcel_cipher_req * sreq,bool * should_complete,int * ret)6071eb7b403SOfer Heifetz static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int ring,
6081b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
6098ac1283eSAntoine Tenart 				      struct scatterlist *src,
6108ac1283eSAntoine Tenart 				      struct scatterlist *dst,
6118ac1283eSAntoine Tenart 				      unsigned int cryptlen,
6128ac1283eSAntoine Tenart 				      struct safexcel_cipher_req *sreq,
6131b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
6141b44c5a6SAntoine Ténart {
6155bdb6e6aSPascal van Leeuwen 	struct skcipher_request *areq = skcipher_request_cast(async);
6165bdb6e6aSPascal van Leeuwen 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq);
6175bdb6e6aSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(skcipher);
6181b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
6191b44c5a6SAntoine Ténart 	int ndesc = 0;
6201b44c5a6SAntoine Ténart 
6211b44c5a6SAntoine Ténart 	*ret = 0;
6221b44c5a6SAntoine Ténart 
62389332590SAntoine Tenart 	if (unlikely(!sreq->rdescs))
62489332590SAntoine Tenart 		return 0;
62589332590SAntoine Tenart 
62689332590SAntoine Tenart 	while (sreq->rdescs--) {
6271b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
6281b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
6291b44c5a6SAntoine Ténart 			dev_err(priv->dev,
6301b44c5a6SAntoine Ténart 				"cipher: result: could not retrieve the result descriptor\n");
6311b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
6321b44c5a6SAntoine Ténart 			break;
6331b44c5a6SAntoine Ténart 		}
6341b44c5a6SAntoine Ténart 
635bdfd1909SAntoine Tenart 		if (likely(!*ret))
636bdfd1909SAntoine Tenart 			*ret = safexcel_rdesc_check_errors(priv, rdesc);
6371b44c5a6SAntoine Ténart 
6381b44c5a6SAntoine Ténart 		ndesc++;
63989332590SAntoine Tenart 	}
6401b44c5a6SAntoine Ténart 
6411b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
6421b44c5a6SAntoine Ténart 
6438ac1283eSAntoine Tenart 	if (src == dst) {
64449186a7dSPeter Harliman Liem 		if (sreq->nr_src > 0)
64549186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
64649186a7dSPeter Harliman Liem 				     DMA_BIDIRECTIONAL);
6471b44c5a6SAntoine Ténart 	} else {
64849186a7dSPeter Harliman Liem 		if (sreq->nr_src > 0)
64949186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
65049186a7dSPeter Harliman Liem 				     DMA_TO_DEVICE);
65149186a7dSPeter Harliman Liem 		if (sreq->nr_dst > 0)
65249186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, dst, sreq->nr_dst,
65349186a7dSPeter Harliman Liem 				     DMA_FROM_DEVICE);
6541b44c5a6SAntoine Ténart 	}
6551b44c5a6SAntoine Ténart 
6565bdb6e6aSPascal van Leeuwen 	/*
6575bdb6e6aSPascal van Leeuwen 	 * Update IV in req from last crypto output word for CBC modes
6585bdb6e6aSPascal van Leeuwen 	 */
6595bdb6e6aSPascal van Leeuwen 	if ((!ctx->aead) && (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) &&
6605bdb6e6aSPascal van Leeuwen 	    (sreq->direction == SAFEXCEL_ENCRYPT)) {
6615bdb6e6aSPascal van Leeuwen 		/* For encrypt take the last output word */
66219b347b3SPascal van Leeuwen 		sg_pcopy_to_buffer(dst, sreq->nr_dst, areq->iv,
6635bdb6e6aSPascal van Leeuwen 				   crypto_skcipher_ivsize(skcipher),
6645bdb6e6aSPascal van Leeuwen 				   (cryptlen -
6655bdb6e6aSPascal van Leeuwen 				    crypto_skcipher_ivsize(skcipher)));
6665bdb6e6aSPascal van Leeuwen 	}
6675bdb6e6aSPascal van Leeuwen 
6681b44c5a6SAntoine Ténart 	*should_complete = true;
6691b44c5a6SAntoine Ténart 
6701b44c5a6SAntoine Ténart 	return ndesc;
6711b44c5a6SAntoine Ténart }
6721b44c5a6SAntoine Ténart 
safexcel_send_req(struct crypto_async_request * base,int ring,struct safexcel_cipher_req * sreq,struct scatterlist * src,struct scatterlist * dst,unsigned int cryptlen,unsigned int assoclen,unsigned int digestsize,u8 * iv,int * commands,int * results)673a7dea8c0SOfer Heifetz static int safexcel_send_req(struct crypto_async_request *base, int ring,
6748ac1283eSAntoine Tenart 			     struct safexcel_cipher_req *sreq,
6758ac1283eSAntoine Tenart 			     struct scatterlist *src, struct scatterlist *dst,
676f6beaea3SAntoine Tenart 			     unsigned int cryptlen, unsigned int assoclen,
677f6beaea3SAntoine Tenart 			     unsigned int digestsize, u8 *iv, int *commands,
6788ac1283eSAntoine Tenart 			     int *results)
6791b44c5a6SAntoine Ténart {
6805bdb6e6aSPascal van Leeuwen 	struct skcipher_request *areq = skcipher_request_cast(base);
6815bdb6e6aSPascal van Leeuwen 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq);
6828ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
68318e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
6841b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc;
68519b347b3SPascal van Leeuwen 	struct safexcel_command_desc *first_cdesc = NULL;
686e5c8ee1fSAntoine Tenart 	struct safexcel_result_desc *rdesc, *first_rdesc = NULL;
6871b44c5a6SAntoine Ténart 	struct scatterlist *sg;
68819b347b3SPascal van Leeuwen 	unsigned int totlen;
68919b347b3SPascal van Leeuwen 	unsigned int totlen_src = cryptlen + assoclen;
69019b347b3SPascal van Leeuwen 	unsigned int totlen_dst = totlen_src;
691098e51e5SPascal van Leeuwen 	struct safexcel_token *atoken;
69219b347b3SPascal van Leeuwen 	int n_cdesc = 0, n_rdesc = 0;
69319b347b3SPascal van Leeuwen 	int queued, i, ret = 0;
69419b347b3SPascal van Leeuwen 	bool first = true;
6951b44c5a6SAntoine Ténart 
69619b347b3SPascal van Leeuwen 	sreq->nr_src = sg_nents_for_len(src, totlen_src);
69719b347b3SPascal van Leeuwen 
69819b347b3SPascal van Leeuwen 	if (ctx->aead) {
69919b347b3SPascal van Leeuwen 		/*
70019b347b3SPascal van Leeuwen 		 * AEAD has auth tag appended to output for encrypt and
70119b347b3SPascal van Leeuwen 		 * removed from the output for decrypt!
70219b347b3SPascal van Leeuwen 		 */
70319b347b3SPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_DECRYPT)
70419b347b3SPascal van Leeuwen 			totlen_dst -= digestsize;
70519b347b3SPascal van Leeuwen 		else
70619b347b3SPascal van Leeuwen 			totlen_dst += digestsize;
70719b347b3SPascal van Leeuwen 
70819b347b3SPascal van Leeuwen 		memcpy(ctx->base.ctxr->data + ctx->key_len / sizeof(u32),
70978cf1c8bSHerbert Xu 		       &ctx->base.ipad, ctx->state_sz);
7103e450886SPascal van Leeuwen 		if (!ctx->xcm)
7113e450886SPascal van Leeuwen 			memcpy(ctx->base.ctxr->data + (ctx->key_len +
71278cf1c8bSHerbert Xu 			       ctx->state_sz) / sizeof(u32), &ctx->base.opad,
7133e450886SPascal van Leeuwen 			       ctx->state_sz);
71419b347b3SPascal van Leeuwen 	} else if ((ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) &&
7155bdb6e6aSPascal van Leeuwen 		   (sreq->direction == SAFEXCEL_DECRYPT)) {
7165bdb6e6aSPascal van Leeuwen 		/*
7175bdb6e6aSPascal van Leeuwen 		 * Save IV from last crypto input word for CBC modes in decrypt
7185bdb6e6aSPascal van Leeuwen 		 * direction. Need to do this first in case of inplace operation
7195bdb6e6aSPascal van Leeuwen 		 * as it will be overwritten.
7205bdb6e6aSPascal van Leeuwen 		 */
72119b347b3SPascal van Leeuwen 		sg_pcopy_to_buffer(src, sreq->nr_src, areq->iv,
7225bdb6e6aSPascal van Leeuwen 				   crypto_skcipher_ivsize(skcipher),
72319b347b3SPascal van Leeuwen 				   (totlen_src -
7245bdb6e6aSPascal van Leeuwen 				    crypto_skcipher_ivsize(skcipher)));
7255bdb6e6aSPascal van Leeuwen 	}
7265bdb6e6aSPascal van Leeuwen 
72719b347b3SPascal van Leeuwen 	sreq->nr_dst = sg_nents_for_len(dst, totlen_dst);
7281b44c5a6SAntoine Ténart 
72919b347b3SPascal van Leeuwen 	/*
73019b347b3SPascal van Leeuwen 	 * Remember actual input length, source buffer length may be
73119b347b3SPascal van Leeuwen 	 * updated in case of inline operation below.
73219b347b3SPascal van Leeuwen 	 */
73319b347b3SPascal van Leeuwen 	totlen = totlen_src;
73419b347b3SPascal van Leeuwen 	queued = totlen_src;
73519b347b3SPascal van Leeuwen 
73619b347b3SPascal van Leeuwen 	if (src == dst) {
73719b347b3SPascal van Leeuwen 		sreq->nr_src = max(sreq->nr_src, sreq->nr_dst);
73819b347b3SPascal van Leeuwen 		sreq->nr_dst = sreq->nr_src;
73919b347b3SPascal van Leeuwen 		if (unlikely((totlen_src || totlen_dst) &&
74019b347b3SPascal van Leeuwen 		    (sreq->nr_src <= 0))) {
74119b347b3SPascal van Leeuwen 			dev_err(priv->dev, "In-place buffer not large enough (need %d bytes)!",
74219b347b3SPascal van Leeuwen 				max(totlen_src, totlen_dst));
7431b44c5a6SAntoine Ténart 			return -EINVAL;
7441b44c5a6SAntoine Ténart 		}
745*8084b788SNikita Zhandarovich 		if (sreq->nr_src > 0 &&
746*8084b788SNikita Zhandarovich 		    !dma_map_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL))
747*8084b788SNikita Zhandarovich 			return -EIO;
74819b347b3SPascal van Leeuwen 	} else {
74919b347b3SPascal van Leeuwen 		if (unlikely(totlen_src && (sreq->nr_src <= 0))) {
75019b347b3SPascal van Leeuwen 			dev_err(priv->dev, "Source buffer not large enough (need %d bytes)!",
75119b347b3SPascal van Leeuwen 				totlen_src);
75219b347b3SPascal van Leeuwen 			return -EINVAL;
75319b347b3SPascal van Leeuwen 		}
75449186a7dSPeter Harliman Liem 
755*8084b788SNikita Zhandarovich 		if (sreq->nr_src > 0 &&
756*8084b788SNikita Zhandarovich 		    !dma_map_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE))
757*8084b788SNikita Zhandarovich 			return -EIO;
75819b347b3SPascal van Leeuwen 
75919b347b3SPascal van Leeuwen 		if (unlikely(totlen_dst && (sreq->nr_dst <= 0))) {
76019b347b3SPascal van Leeuwen 			dev_err(priv->dev, "Dest buffer not large enough (need %d bytes)!",
76119b347b3SPascal van Leeuwen 				totlen_dst);
76249186a7dSPeter Harliman Liem 			ret = -EINVAL;
76349186a7dSPeter Harliman Liem 			goto unmap;
76419b347b3SPascal van Leeuwen 		}
76549186a7dSPeter Harliman Liem 
766*8084b788SNikita Zhandarovich 		if (sreq->nr_dst > 0 &&
767*8084b788SNikita Zhandarovich 		    !dma_map_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE)) {
768*8084b788SNikita Zhandarovich 			ret = -EIO;
769*8084b788SNikita Zhandarovich 			goto unmap;
770*8084b788SNikita Zhandarovich 		}
7711b44c5a6SAntoine Ténart 	}
7721b44c5a6SAntoine Ténart 
7731b44c5a6SAntoine Ténart 	memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len);
7741b44c5a6SAntoine Ténart 
775cb97aa94SPascal van Leeuwen 	if (!totlen) {
776cb97aa94SPascal van Leeuwen 		/*
777cb97aa94SPascal van Leeuwen 		 * The EIP97 cannot deal with zero length input packets!
778cb97aa94SPascal van Leeuwen 		 * So stuff a dummy command descriptor indicating a 1 byte
779cb97aa94SPascal van Leeuwen 		 * (dummy) input packet, using the context record as source.
780cb97aa94SPascal van Leeuwen 		 */
781cb97aa94SPascal van Leeuwen 		first_cdesc = safexcel_add_cdesc(priv, ring,
782cb97aa94SPascal van Leeuwen 						 1, 1, ctx->base.ctxr_dma,
783cb97aa94SPascal van Leeuwen 						 1, 1, ctx->base.ctxr_dma,
784cb97aa94SPascal van Leeuwen 						 &atoken);
785cb97aa94SPascal van Leeuwen 		if (IS_ERR(first_cdesc)) {
786cb97aa94SPascal van Leeuwen 			/* No space left in the command descriptor ring */
787cb97aa94SPascal van Leeuwen 			ret = PTR_ERR(first_cdesc);
788cb97aa94SPascal van Leeuwen 			goto cdesc_rollback;
789cb97aa94SPascal van Leeuwen 		}
790cb97aa94SPascal van Leeuwen 		n_cdesc = 1;
791cb97aa94SPascal van Leeuwen 		goto skip_cdesc;
792cb97aa94SPascal van Leeuwen 	}
793f6beaea3SAntoine Tenart 
7941b44c5a6SAntoine Ténart 	/* command descriptors */
79519b347b3SPascal van Leeuwen 	for_each_sg(src, sg, sreq->nr_src, i) {
7961b44c5a6SAntoine Ténart 		int len = sg_dma_len(sg);
7971b44c5a6SAntoine Ténart 
7981b44c5a6SAntoine Ténart 		/* Do not overflow the request */
799cb97aa94SPascal van Leeuwen 		if (queued < len)
8001b44c5a6SAntoine Ténart 			len = queued;
8011b44c5a6SAntoine Ténart 
80219b347b3SPascal van Leeuwen 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
80319b347b3SPascal van Leeuwen 					   !(queued - len),
804f6beaea3SAntoine Tenart 					   sg_dma_address(sg), len, totlen,
805098e51e5SPascal van Leeuwen 					   ctx->base.ctxr_dma, &atoken);
8061b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
8071b44c5a6SAntoine Ténart 			/* No space left in the command descriptor ring */
8081b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
8091b44c5a6SAntoine Ténart 			goto cdesc_rollback;
8101b44c5a6SAntoine Ténart 		}
8111b44c5a6SAntoine Ténart 
812cb97aa94SPascal van Leeuwen 		if (!n_cdesc)
81319b347b3SPascal van Leeuwen 			first_cdesc = cdesc;
8141b44c5a6SAntoine Ténart 
815cb97aa94SPascal van Leeuwen 		n_cdesc++;
8161b44c5a6SAntoine Ténart 		queued -= len;
8171b44c5a6SAntoine Ténart 		if (!queued)
8181b44c5a6SAntoine Ténart 			break;
8191b44c5a6SAntoine Ténart 	}
820cb97aa94SPascal van Leeuwen skip_cdesc:
82119b347b3SPascal van Leeuwen 	/* Add context control words and token to first command descriptor */
82219b347b3SPascal van Leeuwen 	safexcel_context_control(ctx, base, sreq, first_cdesc);
82319b347b3SPascal van Leeuwen 	if (ctx->aead)
824098e51e5SPascal van Leeuwen 		safexcel_aead_token(ctx, iv, first_cdesc, atoken,
82519b347b3SPascal van Leeuwen 				    sreq->direction, cryptlen,
82619b347b3SPascal van Leeuwen 				    assoclen, digestsize);
82719b347b3SPascal van Leeuwen 	else
828098e51e5SPascal van Leeuwen 		safexcel_skcipher_token(ctx, iv, first_cdesc, atoken,
82919b347b3SPascal van Leeuwen 					cryptlen);
83019b347b3SPascal van Leeuwen 
8311b44c5a6SAntoine Ténart 	/* result descriptors */
83219b347b3SPascal van Leeuwen 	for_each_sg(dst, sg, sreq->nr_dst, i) {
83319b347b3SPascal van Leeuwen 		bool last = (i == sreq->nr_dst - 1);
8341b44c5a6SAntoine Ténart 		u32 len = sg_dma_len(sg);
8351b44c5a6SAntoine Ténart 
83619b347b3SPascal van Leeuwen 		/* only allow the part of the buffer we know we need */
83719b347b3SPascal van Leeuwen 		if (len > totlen_dst)
83819b347b3SPascal van Leeuwen 			len = totlen_dst;
83919b347b3SPascal van Leeuwen 		if (unlikely(!len))
84019b347b3SPascal van Leeuwen 			break;
84119b347b3SPascal van Leeuwen 		totlen_dst -= len;
84219b347b3SPascal van Leeuwen 
84319b347b3SPascal van Leeuwen 		/* skip over AAD space in buffer - not written */
84419b347b3SPascal van Leeuwen 		if (assoclen) {
84519b347b3SPascal van Leeuwen 			if (assoclen >= len) {
84619b347b3SPascal van Leeuwen 				assoclen -= len;
84719b347b3SPascal van Leeuwen 				continue;
84819b347b3SPascal van Leeuwen 			}
8491b44c5a6SAntoine Ténart 			rdesc = safexcel_add_rdesc(priv, ring, first, last,
85019b347b3SPascal van Leeuwen 						   sg_dma_address(sg) +
85119b347b3SPascal van Leeuwen 						   assoclen,
85219b347b3SPascal van Leeuwen 						   len - assoclen);
85319b347b3SPascal van Leeuwen 			assoclen = 0;
85419b347b3SPascal van Leeuwen 		} else {
85519b347b3SPascal van Leeuwen 			rdesc = safexcel_add_rdesc(priv, ring, first, last,
85619b347b3SPascal van Leeuwen 						   sg_dma_address(sg),
85719b347b3SPascal van Leeuwen 						   len);
85819b347b3SPascal van Leeuwen 		}
8591b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
8601b44c5a6SAntoine Ténart 			/* No space left in the result descriptor ring */
8611b44c5a6SAntoine Ténart 			ret = PTR_ERR(rdesc);
8621b44c5a6SAntoine Ténart 			goto rdesc_rollback;
8631b44c5a6SAntoine Ténart 		}
86419b347b3SPascal van Leeuwen 		if (first) {
8659744fec9SOfer Heifetz 			first_rdesc = rdesc;
86619b347b3SPascal van Leeuwen 			first = false;
86719b347b3SPascal van Leeuwen 		}
8681b44c5a6SAntoine Ténart 		n_rdesc++;
8691b44c5a6SAntoine Ténart 	}
8701b44c5a6SAntoine Ténart 
87119b347b3SPascal van Leeuwen 	if (unlikely(first)) {
87219b347b3SPascal van Leeuwen 		/*
87319b347b3SPascal van Leeuwen 		 * Special case: AEAD decrypt with only AAD data.
87419b347b3SPascal van Leeuwen 		 * In this case there is NO output data from the engine,
87519b347b3SPascal van Leeuwen 		 * but the engine still needs a result descriptor!
87619b347b3SPascal van Leeuwen 		 * Create a dummy one just for catching the result token.
87719b347b3SPascal van Leeuwen 		 */
87819b347b3SPascal van Leeuwen 		rdesc = safexcel_add_rdesc(priv, ring, true, true, 0, 0);
87919b347b3SPascal van Leeuwen 		if (IS_ERR(rdesc)) {
88019b347b3SPascal van Leeuwen 			/* No space left in the result descriptor ring */
88119b347b3SPascal van Leeuwen 			ret = PTR_ERR(rdesc);
88219b347b3SPascal van Leeuwen 			goto rdesc_rollback;
88319b347b3SPascal van Leeuwen 		}
88419b347b3SPascal van Leeuwen 		first_rdesc = rdesc;
88519b347b3SPascal van Leeuwen 		n_rdesc = 1;
88619b347b3SPascal van Leeuwen 	}
88719b347b3SPascal van Leeuwen 
8889744fec9SOfer Heifetz 	safexcel_rdr_req_set(priv, ring, first_rdesc, base);
88997858434SAntoine Ténart 
8901b44c5a6SAntoine Ténart 	*commands = n_cdesc;
891152bdf4cSOfer Heifetz 	*results = n_rdesc;
8921b44c5a6SAntoine Ténart 	return 0;
8931b44c5a6SAntoine Ténart 
8941b44c5a6SAntoine Ténart rdesc_rollback:
8951b44c5a6SAntoine Ténart 	for (i = 0; i < n_rdesc; i++)
8961b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].rdr);
8971b44c5a6SAntoine Ténart cdesc_rollback:
8981b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
8991b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
90049186a7dSPeter Harliman Liem unmap:
9018ac1283eSAntoine Tenart 	if (src == dst) {
90249186a7dSPeter Harliman Liem 		if (sreq->nr_src > 0)
90349186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
90449186a7dSPeter Harliman Liem 				     DMA_BIDIRECTIONAL);
9051b44c5a6SAntoine Ténart 	} else {
90649186a7dSPeter Harliman Liem 		if (sreq->nr_src > 0)
90749186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
90849186a7dSPeter Harliman Liem 				     DMA_TO_DEVICE);
90949186a7dSPeter Harliman Liem 		if (sreq->nr_dst > 0)
91049186a7dSPeter Harliman Liem 			dma_unmap_sg(priv->dev, dst, sreq->nr_dst,
91149186a7dSPeter Harliman Liem 				     DMA_FROM_DEVICE);
9121b44c5a6SAntoine Ténart 	}
9131b44c5a6SAntoine Ténart 
9141b44c5a6SAntoine Ténart 	return ret;
9151b44c5a6SAntoine Ténart }
9161b44c5a6SAntoine Ténart 
safexcel_handle_inv_result(struct safexcel_crypto_priv * priv,int ring,struct crypto_async_request * base,struct safexcel_cipher_req * sreq,bool * should_complete,int * ret)9171b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
9181b44c5a6SAntoine Ténart 				      int ring,
9198ac1283eSAntoine Tenart 				      struct crypto_async_request *base,
92089332590SAntoine Tenart 				      struct safexcel_cipher_req *sreq,
9211b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
9221b44c5a6SAntoine Ténart {
9238ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
9241b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
9251b44c5a6SAntoine Ténart 	int ndesc = 0, enq_ret;
9261b44c5a6SAntoine Ténart 
9271b44c5a6SAntoine Ténart 	*ret = 0;
9281b44c5a6SAntoine Ténart 
92989332590SAntoine Tenart 	if (unlikely(!sreq->rdescs))
93089332590SAntoine Tenart 		return 0;
93189332590SAntoine Tenart 
93289332590SAntoine Tenart 	while (sreq->rdescs--) {
9331b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
9341b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
9351b44c5a6SAntoine Ténart 			dev_err(priv->dev,
9361b44c5a6SAntoine Ténart 				"cipher: invalidate: could not retrieve the result descriptor\n");
9371b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
9381b44c5a6SAntoine Ténart 			break;
9391b44c5a6SAntoine Ténart 		}
9401b44c5a6SAntoine Ténart 
941cda3e73aSAntoine Tenart 		if (likely(!*ret))
942cda3e73aSAntoine Tenart 			*ret = safexcel_rdesc_check_errors(priv, rdesc);
9431b44c5a6SAntoine Ténart 
9441b44c5a6SAntoine Ténart 		ndesc++;
94589332590SAntoine Tenart 	}
9461b44c5a6SAntoine Ténart 
9471b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
9481b44c5a6SAntoine Ténart 
9491b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
9501b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
9511b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
9521b44c5a6SAntoine Ténart 
9531b44c5a6SAntoine Ténart 		*should_complete = true;
9541b44c5a6SAntoine Ténart 
9551b44c5a6SAntoine Ténart 		return ndesc;
9561b44c5a6SAntoine Ténart 	}
9571b44c5a6SAntoine Ténart 
95886671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
95986671abbSAntoine Ténart 	ctx->base.ring = ring;
9601b44c5a6SAntoine Ténart 
96186671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
9628ac1283eSAntoine Tenart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
96386671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
9641b44c5a6SAntoine Ténart 
9651b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
9661b44c5a6SAntoine Ténart 		*ret = enq_ret;
9671b44c5a6SAntoine Ténart 
9688472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
9698472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
97086671abbSAntoine Ténart 
9711b44c5a6SAntoine Ténart 	*should_complete = false;
9721b44c5a6SAntoine Ténart 
9731b44c5a6SAntoine Ténart 	return ndesc;
9741b44c5a6SAntoine Ténart }
9751b44c5a6SAntoine Ténart 
safexcel_skcipher_handle_result(struct safexcel_crypto_priv * priv,int ring,struct crypto_async_request * async,bool * should_complete,int * ret)9768ac1283eSAntoine Tenart static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv,
9778ac1283eSAntoine Tenart 					   int ring,
9781eb7b403SOfer Heifetz 					   struct crypto_async_request *async,
9791eb7b403SOfer Heifetz 					   bool *should_complete, int *ret)
9801eb7b403SOfer Heifetz {
9811eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
9821eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
9831eb7b403SOfer Heifetz 	int err;
9841eb7b403SOfer Heifetz 
9851eb7b403SOfer Heifetz 	if (sreq->needs_inv) {
9861eb7b403SOfer Heifetz 		sreq->needs_inv = false;
98789332590SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async, sreq,
9881eb7b403SOfer Heifetz 						 should_complete, ret);
9891eb7b403SOfer Heifetz 	} else {
9908ac1283eSAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
9918ac1283eSAntoine Tenart 						 req->dst, req->cryptlen, sreq,
9921eb7b403SOfer Heifetz 						 should_complete, ret);
9931eb7b403SOfer Heifetz 	}
9941eb7b403SOfer Heifetz 
9951eb7b403SOfer Heifetz 	return err;
9961eb7b403SOfer Heifetz }
9971eb7b403SOfer Heifetz 
safexcel_aead_handle_result(struct safexcel_crypto_priv * priv,int ring,struct crypto_async_request * async,bool * should_complete,int * ret)998f6beaea3SAntoine Tenart static int safexcel_aead_handle_result(struct safexcel_crypto_priv *priv,
999f6beaea3SAntoine Tenart 				       int ring,
1000f6beaea3SAntoine Tenart 				       struct crypto_async_request *async,
1001f6beaea3SAntoine Tenart 				       bool *should_complete, int *ret)
1002f6beaea3SAntoine Tenart {
1003f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
1004f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1005f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
1006f6beaea3SAntoine Tenart 	int err;
1007f6beaea3SAntoine Tenart 
1008f6beaea3SAntoine Tenart 	if (sreq->needs_inv) {
1009f6beaea3SAntoine Tenart 		sreq->needs_inv = false;
101089332590SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async, sreq,
1011f6beaea3SAntoine Tenart 						 should_complete, ret);
1012f6beaea3SAntoine Tenart 	} else {
1013f6beaea3SAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
1014f6beaea3SAntoine Tenart 						 req->dst,
1015f6beaea3SAntoine Tenart 						 req->cryptlen + crypto_aead_authsize(tfm),
1016f6beaea3SAntoine Tenart 						 sreq, should_complete, ret);
1017f6beaea3SAntoine Tenart 	}
1018f6beaea3SAntoine Tenart 
1019f6beaea3SAntoine Tenart 	return err;
1020f6beaea3SAntoine Tenart }
1021f6beaea3SAntoine Tenart 
safexcel_cipher_send_inv(struct crypto_async_request * base,int ring,int * commands,int * results)10228ac1283eSAntoine Tenart static int safexcel_cipher_send_inv(struct crypto_async_request *base,
10239744fec9SOfer Heifetz 				    int ring, int *commands, int *results)
10241b44c5a6SAntoine Ténart {
10258ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
102618e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
10271b44c5a6SAntoine Ténart 	int ret;
10281b44c5a6SAntoine Ténart 
10299744fec9SOfer Heifetz 	ret = safexcel_invalidate_cache(base, priv, ctx->base.ctxr_dma, ring);
10301b44c5a6SAntoine Ténart 	if (unlikely(ret))
10311b44c5a6SAntoine Ténart 		return ret;
10321b44c5a6SAntoine Ténart 
10331b44c5a6SAntoine Ténart 	*commands = 1;
10341b44c5a6SAntoine Ténart 	*results = 1;
10351b44c5a6SAntoine Ténart 
10361b44c5a6SAntoine Ténart 	return 0;
10371b44c5a6SAntoine Ténart }
10381b44c5a6SAntoine Ténart 
safexcel_skcipher_send(struct crypto_async_request * async,int ring,int * commands,int * results)10398ac1283eSAntoine Tenart static int safexcel_skcipher_send(struct crypto_async_request *async, int ring,
10401eb7b403SOfer Heifetz 				  int *commands, int *results)
10411eb7b403SOfer Heifetz {
10421eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
1043871df319SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
10441eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
104518e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
10461eb7b403SOfer Heifetz 	int ret;
10471eb7b403SOfer Heifetz 
104853c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv);
1049871df319SAntoine Ténart 
10505bdb6e6aSPascal van Leeuwen 	if (sreq->needs_inv) {
10519744fec9SOfer Heifetz 		ret = safexcel_cipher_send_inv(async, ring, commands, results);
10525bdb6e6aSPascal van Leeuwen 	} else {
10535bdb6e6aSPascal van Leeuwen 		struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
10545bdb6e6aSPascal van Leeuwen 		u8 input_iv[AES_BLOCK_SIZE];
10555bdb6e6aSPascal van Leeuwen 
10565bdb6e6aSPascal van Leeuwen 		/*
10575bdb6e6aSPascal van Leeuwen 		 * Save input IV in case of CBC decrypt mode
10585bdb6e6aSPascal van Leeuwen 		 * Will be overwritten with output IV prior to use!
10595bdb6e6aSPascal van Leeuwen 		 */
10605bdb6e6aSPascal van Leeuwen 		memcpy(input_iv, req->iv, crypto_skcipher_ivsize(skcipher));
10615bdb6e6aSPascal van Leeuwen 
10629744fec9SOfer Heifetz 		ret = safexcel_send_req(async, ring, sreq, req->src,
10635bdb6e6aSPascal van Leeuwen 					req->dst, req->cryptlen, 0, 0, input_iv,
1064f6beaea3SAntoine Tenart 					commands, results);
10655bdb6e6aSPascal van Leeuwen 	}
106689332590SAntoine Tenart 
106789332590SAntoine Tenart 	sreq->rdescs = *results;
1068f6beaea3SAntoine Tenart 	return ret;
1069f6beaea3SAntoine Tenart }
1070f6beaea3SAntoine Tenart 
safexcel_aead_send(struct crypto_async_request * async,int ring,int * commands,int * results)1071f6beaea3SAntoine Tenart static int safexcel_aead_send(struct crypto_async_request *async, int ring,
10729744fec9SOfer Heifetz 			      int *commands, int *results)
1073f6beaea3SAntoine Tenart {
1074f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
1075f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1076f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
1077f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
107818e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
1079f6beaea3SAntoine Tenart 	int ret;
1080f6beaea3SAntoine Tenart 
108153c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv);
1082f6beaea3SAntoine Tenart 
1083f6beaea3SAntoine Tenart 	if (sreq->needs_inv)
10849744fec9SOfer Heifetz 		ret = safexcel_cipher_send_inv(async, ring, commands, results);
1085f6beaea3SAntoine Tenart 	else
10869744fec9SOfer Heifetz 		ret = safexcel_send_req(async, ring, sreq, req->src, req->dst,
10879744fec9SOfer Heifetz 					req->cryptlen, req->assoclen,
1088f6beaea3SAntoine Tenart 					crypto_aead_authsize(tfm), req->iv,
10891eb7b403SOfer Heifetz 					commands, results);
109089332590SAntoine Tenart 	sreq->rdescs = *results;
10911eb7b403SOfer Heifetz 	return ret;
10921eb7b403SOfer Heifetz }
10931eb7b403SOfer Heifetz 
safexcel_cipher_exit_inv(struct crypto_tfm * tfm,struct crypto_async_request * base,struct safexcel_cipher_req * sreq,struct crypto_wait * result)10948ac1283eSAntoine Tenart static int safexcel_cipher_exit_inv(struct crypto_tfm *tfm,
10958ac1283eSAntoine Tenart 				    struct crypto_async_request *base,
10968ac1283eSAntoine Tenart 				    struct safexcel_cipher_req *sreq,
1097acc3f550SHerbert Xu 				    struct crypto_wait *result)
10981b44c5a6SAntoine Ténart {
10991b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
110018e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
110186671abbSAntoine Ténart 	int ring = ctx->base.ring;
1102acc3f550SHerbert Xu 	int err;
11031b44c5a6SAntoine Ténart 
11048ac1283eSAntoine Tenart 	ctx = crypto_tfm_ctx(base->tfm);
11051b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
11061eb7b403SOfer Heifetz 	sreq->needs_inv = true;
11071b44c5a6SAntoine Ténart 
110886671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
11098ac1283eSAntoine Tenart 	crypto_enqueue_request(&priv->ring[ring].queue, base);
111086671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
11111b44c5a6SAntoine Ténart 
11128472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
11138472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
11141b44c5a6SAntoine Ténart 
1115acc3f550SHerbert Xu 	err = crypto_wait_req(-EINPROGRESS, result);
11161b44c5a6SAntoine Ténart 
1117acc3f550SHerbert Xu 	if (err) {
11181b44c5a6SAntoine Ténart 		dev_warn(priv->dev,
11191b44c5a6SAntoine Ténart 			"cipher: sync: invalidate: completion error %d\n",
1120acc3f550SHerbert Xu 			 err);
1121acc3f550SHerbert Xu 		return err;
11221b44c5a6SAntoine Ténart 	}
11231b44c5a6SAntoine Ténart 
11241b44c5a6SAntoine Ténart 	return 0;
11251b44c5a6SAntoine Ténart }
11261b44c5a6SAntoine Ténart 
safexcel_skcipher_exit_inv(struct crypto_tfm * tfm)11278ac1283eSAntoine Tenart static int safexcel_skcipher_exit_inv(struct crypto_tfm *tfm)
11288ac1283eSAntoine Tenart {
11298ac1283eSAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, skcipher, EIP197_SKCIPHER_REQ_SIZE);
11308ac1283eSAntoine Tenart 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
1131acc3f550SHerbert Xu 	DECLARE_CRYPTO_WAIT(result);
11328ac1283eSAntoine Tenart 
11338ac1283eSAntoine Tenart 	memset(req, 0, sizeof(struct skcipher_request));
11348ac1283eSAntoine Tenart 
11358ac1283eSAntoine Tenart 	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1136acc3f550SHerbert Xu 				      crypto_req_done, &result);
11378ac1283eSAntoine Tenart 	skcipher_request_set_tfm(req, __crypto_skcipher_cast(tfm));
11388ac1283eSAntoine Tenart 
11398ac1283eSAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
11408ac1283eSAntoine Tenart }
11418ac1283eSAntoine Tenart 
safexcel_aead_exit_inv(struct crypto_tfm * tfm)1142f6beaea3SAntoine Tenart static int safexcel_aead_exit_inv(struct crypto_tfm *tfm)
1143f6beaea3SAntoine Tenart {
1144f6beaea3SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, aead, EIP197_AEAD_REQ_SIZE);
1145f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
1146acc3f550SHerbert Xu 	DECLARE_CRYPTO_WAIT(result);
1147f6beaea3SAntoine Tenart 
1148f6beaea3SAntoine Tenart 	memset(req, 0, sizeof(struct aead_request));
1149f6beaea3SAntoine Tenart 
1150f6beaea3SAntoine Tenart 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1151acc3f550SHerbert Xu 				  crypto_req_done, &result);
1152f6beaea3SAntoine Tenart 	aead_request_set_tfm(req, __crypto_aead_cast(tfm));
1153f6beaea3SAntoine Tenart 
1154f6beaea3SAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
1155f6beaea3SAntoine Tenart }
1156f6beaea3SAntoine Tenart 
safexcel_queue_req(struct crypto_async_request * base,struct safexcel_cipher_req * sreq,enum safexcel_cipher_direction dir)1157a7dea8c0SOfer Heifetz static int safexcel_queue_req(struct crypto_async_request *base,
11588ac1283eSAntoine Tenart 			struct safexcel_cipher_req *sreq,
115993369b5dSPascal van Leeuwen 			enum safexcel_cipher_direction dir)
11601b44c5a6SAntoine Ténart {
11618ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
116218e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
116386671abbSAntoine Ténart 	int ret, ring;
11641b44c5a6SAntoine Ténart 
11651eb7b403SOfer Heifetz 	sreq->needs_inv = false;
1166847ccfc5SOfer Heifetz 	sreq->direction = dir;
11671b44c5a6SAntoine Ténart 
11681b44c5a6SAntoine Ténart 	if (ctx->base.ctxr) {
116953c83e91SAntoine Tenart 		if (priv->flags & EIP197_TRC_CACHE && ctx->base.needs_inv) {
11701eb7b403SOfer Heifetz 			sreq->needs_inv = true;
11711eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
11721eb7b403SOfer Heifetz 		}
11731b44c5a6SAntoine Ténart 	} else {
11741b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
11751b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
11768ac1283eSAntoine Tenart 						 EIP197_GFP_FLAGS(*base),
11771b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
11781b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
11791b44c5a6SAntoine Ténart 			return -ENOMEM;
11801b44c5a6SAntoine Ténart 	}
11811b44c5a6SAntoine Ténart 
118286671abbSAntoine Ténart 	ring = ctx->base.ring;
11831b44c5a6SAntoine Ténart 
118486671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
11858ac1283eSAntoine Tenart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
118686671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
118786671abbSAntoine Ténart 
11888472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
11898472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
11901b44c5a6SAntoine Ténart 
11911b44c5a6SAntoine Ténart 	return ret;
11921b44c5a6SAntoine Ténart }
11931b44c5a6SAntoine Ténart 
safexcel_encrypt(struct skcipher_request * req)119493369b5dSPascal van Leeuwen static int safexcel_encrypt(struct skcipher_request *req)
11951b44c5a6SAntoine Ténart {
1196a7dea8c0SOfer Heifetz 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
119793369b5dSPascal van Leeuwen 			SAFEXCEL_ENCRYPT);
11981b44c5a6SAntoine Ténart }
11991b44c5a6SAntoine Ténart 
safexcel_decrypt(struct skcipher_request * req)120093369b5dSPascal van Leeuwen static int safexcel_decrypt(struct skcipher_request *req)
12011b44c5a6SAntoine Ténart {
1202a7dea8c0SOfer Heifetz 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
120393369b5dSPascal van Leeuwen 			SAFEXCEL_DECRYPT);
12041b44c5a6SAntoine Ténart }
12051b44c5a6SAntoine Ténart 
safexcel_skcipher_cra_init(struct crypto_tfm * tfm)12061b44c5a6SAntoine Ténart static int safexcel_skcipher_cra_init(struct crypto_tfm *tfm)
12071b44c5a6SAntoine Ténart {
12081b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
12091b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
12101b44c5a6SAntoine Ténart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
12111b44c5a6SAntoine Ténart 			     alg.skcipher.base);
12121b44c5a6SAntoine Ténart 
12131eb7b403SOfer Heifetz 	crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm),
12141eb7b403SOfer Heifetz 				    sizeof(struct safexcel_cipher_req));
12151b44c5a6SAntoine Ténart 
121618e51895SHerbert Xu 	ctx->base.priv = tmpl->priv;
12178ac1283eSAntoine Tenart 
12188ac1283eSAntoine Tenart 	ctx->base.send = safexcel_skcipher_send;
12198ac1283eSAntoine Tenart 	ctx->base.handle_result = safexcel_skcipher_handle_result;
1220098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD;
1221098e51e5SPascal van Leeuwen 	ctx->ctrinit = 1;
12228ac1283eSAntoine Tenart 	return 0;
12238ac1283eSAntoine Tenart }
12248ac1283eSAntoine Tenart 
safexcel_cipher_cra_exit(struct crypto_tfm * tfm)12258ac1283eSAntoine Tenart static int safexcel_cipher_cra_exit(struct crypto_tfm *tfm)
12268ac1283eSAntoine Tenart {
12278ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
12288ac1283eSAntoine Tenart 
1229ce679559SAntoine Tenart 	memzero_explicit(ctx->key, sizeof(ctx->key));
12308ac1283eSAntoine Tenart 
12318ac1283eSAntoine Tenart 	/* context not allocated, skip invalidation */
12328ac1283eSAntoine Tenart 	if (!ctx->base.ctxr)
12338ac1283eSAntoine Tenart 		return -ENOMEM;
12348ac1283eSAntoine Tenart 
1235ce679559SAntoine Tenart 	memzero_explicit(ctx->base.ctxr->data, sizeof(ctx->base.ctxr->data));
12361b44c5a6SAntoine Ténart 	return 0;
12371b44c5a6SAntoine Ténart }
12381b44c5a6SAntoine Ténart 
safexcel_skcipher_cra_exit(struct crypto_tfm * tfm)12391b44c5a6SAntoine Ténart static void safexcel_skcipher_cra_exit(struct crypto_tfm *tfm)
12401b44c5a6SAntoine Ténart {
12411b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
124218e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
12431b44c5a6SAntoine Ténart 	int ret;
12441b44c5a6SAntoine Ténart 
12458ac1283eSAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
12461b44c5a6SAntoine Ténart 		return;
12471b44c5a6SAntoine Ténart 
124853c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
12498ac1283eSAntoine Tenart 		ret = safexcel_skcipher_exit_inv(tfm);
12501b44c5a6SAntoine Ténart 		if (ret)
12518ac1283eSAntoine Tenart 			dev_warn(priv->dev, "skcipher: invalidation error %d\n",
12528ac1283eSAntoine Tenart 				 ret);
1253871df319SAntoine Ténart 	} else {
1254871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
1255871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
1256871df319SAntoine Ténart 	}
12571b44c5a6SAntoine Ténart }
12581b44c5a6SAntoine Ténart 
safexcel_aead_cra_exit(struct crypto_tfm * tfm)1259f6beaea3SAntoine Tenart static void safexcel_aead_cra_exit(struct crypto_tfm *tfm)
1260f6beaea3SAntoine Tenart {
1261f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
126218e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
1263f6beaea3SAntoine Tenart 	int ret;
1264f6beaea3SAntoine Tenart 
1265f6beaea3SAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
1266f6beaea3SAntoine Tenart 		return;
1267f6beaea3SAntoine Tenart 
126853c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
1269f6beaea3SAntoine Tenart 		ret = safexcel_aead_exit_inv(tfm);
1270f6beaea3SAntoine Tenart 		if (ret)
1271f6beaea3SAntoine Tenart 			dev_warn(priv->dev, "aead: invalidation error %d\n",
1272f6beaea3SAntoine Tenart 				 ret);
1273f6beaea3SAntoine Tenart 	} else {
1274f6beaea3SAntoine Tenart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
1275f6beaea3SAntoine Tenart 			      ctx->base.ctxr_dma);
1276f6beaea3SAntoine Tenart 	}
1277f6beaea3SAntoine Tenart }
1278f6beaea3SAntoine Tenart 
safexcel_skcipher_aes_ecb_cra_init(struct crypto_tfm * tfm)127993369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_ecb_cra_init(struct crypto_tfm *tfm)
128093369b5dSPascal van Leeuwen {
128193369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
128293369b5dSPascal van Leeuwen 
128393369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
128493369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
128593369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1286098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1287098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
128893369b5dSPascal van Leeuwen 	return 0;
128993369b5dSPascal van Leeuwen }
129093369b5dSPascal van Leeuwen 
12911b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_ecb_aes = {
12921b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1293062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
12941b44c5a6SAntoine Ténart 	.alg.skcipher = {
12958ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
129693369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
129793369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
12981b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
12991b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
13001b44c5a6SAntoine Ténart 		.base = {
13011b44c5a6SAntoine Ténart 			.cra_name = "ecb(aes)",
13021b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-ecb-aes",
1303aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
13042c95e6d9SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1305b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
13061b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
13071b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
13081b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
13091b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
131093369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ecb_cra_init,
13111b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
13121b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
13131b44c5a6SAntoine Ténart 		},
13141b44c5a6SAntoine Ténart 	},
13151b44c5a6SAntoine Ténart };
13161b44c5a6SAntoine Ténart 
safexcel_skcipher_aes_cbc_cra_init(struct crypto_tfm * tfm)131793369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_cbc_cra_init(struct crypto_tfm *tfm)
13181b44c5a6SAntoine Ténart {
131993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
13201b44c5a6SAntoine Ténart 
132193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
132293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1323098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
132493369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
132593369b5dSPascal van Leeuwen 	return 0;
13261b44c5a6SAntoine Ténart }
13271b44c5a6SAntoine Ténart 
13281b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_cbc_aes = {
13291b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1330062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
13311b44c5a6SAntoine Ténart 	.alg.skcipher = {
13328ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
133393369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
133493369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
13351b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
13361b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
13371b44c5a6SAntoine Ténart 		.ivsize = AES_BLOCK_SIZE,
13381b44c5a6SAntoine Ténart 		.base = {
13391b44c5a6SAntoine Ténart 			.cra_name = "cbc(aes)",
13401b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-cbc-aes",
1341aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
13422c95e6d9SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1343b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
13441b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
13451b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
13461b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
13471b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
134893369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_cbc_cra_init,
13491b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
13501b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
13511b44c5a6SAntoine Ténart 		},
13521b44c5a6SAntoine Ténart 	},
13531b44c5a6SAntoine Ténart };
1354f6beaea3SAntoine Tenart 
safexcel_skcipher_aes_cfb_cra_init(struct crypto_tfm * tfm)135548e97afaSPascal van Leeuwen static int safexcel_skcipher_aes_cfb_cra_init(struct crypto_tfm *tfm)
135648e97afaSPascal van Leeuwen {
135748e97afaSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
135848e97afaSPascal van Leeuwen 
135948e97afaSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
136048e97afaSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1361098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
136248e97afaSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB;
136348e97afaSPascal van Leeuwen 	return 0;
136448e97afaSPascal van Leeuwen }
136548e97afaSPascal van Leeuwen 
136648e97afaSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cfb_aes = {
136748e97afaSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
136848e97afaSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XFB,
136948e97afaSPascal van Leeuwen 	.alg.skcipher = {
137048e97afaSPascal van Leeuwen 		.setkey = safexcel_skcipher_aes_setkey,
137148e97afaSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
137248e97afaSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
137348e97afaSPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE,
137448e97afaSPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE,
137548e97afaSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
137648e97afaSPascal van Leeuwen 		.base = {
137748e97afaSPascal van Leeuwen 			.cra_name = "cfb(aes)",
137848e97afaSPascal van Leeuwen 			.cra_driver_name = "safexcel-cfb-aes",
137948e97afaSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
138048e97afaSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1381b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
138248e97afaSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
138348e97afaSPascal van Leeuwen 			.cra_blocksize = 1,
138448e97afaSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
138548e97afaSPascal van Leeuwen 			.cra_alignmask = 0,
138648e97afaSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_cfb_cra_init,
138748e97afaSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
138848e97afaSPascal van Leeuwen 			.cra_module = THIS_MODULE,
138948e97afaSPascal van Leeuwen 		},
139048e97afaSPascal van Leeuwen 	},
139148e97afaSPascal van Leeuwen };
139248e97afaSPascal van Leeuwen 
safexcel_skcipher_aes_ofb_cra_init(struct crypto_tfm * tfm)139350485dfbSPascal van Leeuwen static int safexcel_skcipher_aes_ofb_cra_init(struct crypto_tfm *tfm)
139450485dfbSPascal van Leeuwen {
139550485dfbSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
139650485dfbSPascal van Leeuwen 
139750485dfbSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
139850485dfbSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1399098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
140050485dfbSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB;
140150485dfbSPascal van Leeuwen 	return 0;
140250485dfbSPascal van Leeuwen }
140350485dfbSPascal van Leeuwen 
140450485dfbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ofb_aes = {
140550485dfbSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
140650485dfbSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XFB,
140750485dfbSPascal van Leeuwen 	.alg.skcipher = {
140850485dfbSPascal van Leeuwen 		.setkey = safexcel_skcipher_aes_setkey,
140950485dfbSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
141050485dfbSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
141150485dfbSPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE,
141250485dfbSPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE,
141350485dfbSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
141450485dfbSPascal van Leeuwen 		.base = {
141550485dfbSPascal van Leeuwen 			.cra_name = "ofb(aes)",
141650485dfbSPascal van Leeuwen 			.cra_driver_name = "safexcel-ofb-aes",
141750485dfbSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
141850485dfbSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1419b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
142050485dfbSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
142150485dfbSPascal van Leeuwen 			.cra_blocksize = 1,
142250485dfbSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
142350485dfbSPascal van Leeuwen 			.cra_alignmask = 0,
142450485dfbSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ofb_cra_init,
142550485dfbSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
142650485dfbSPascal van Leeuwen 			.cra_module = THIS_MODULE,
142750485dfbSPascal van Leeuwen 		},
142850485dfbSPascal van Leeuwen 	},
142950485dfbSPascal van Leeuwen };
143050485dfbSPascal van Leeuwen 
safexcel_skcipher_aesctr_setkey(struct crypto_skcipher * ctfm,const u8 * key,unsigned int len)143154f9e8faSPascal van Leeuwen static int safexcel_skcipher_aesctr_setkey(struct crypto_skcipher *ctfm,
143254f9e8faSPascal van Leeuwen 					   const u8 *key, unsigned int len)
143354f9e8faSPascal van Leeuwen {
143454f9e8faSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
143554f9e8faSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
143618e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
143754f9e8faSPascal van Leeuwen 	struct crypto_aes_ctx aes;
143854f9e8faSPascal van Leeuwen 	int ret, i;
143954f9e8faSPascal van Leeuwen 	unsigned int keylen;
144054f9e8faSPascal van Leeuwen 
144154f9e8faSPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
1442f26882a3SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
144354f9e8faSPascal van Leeuwen 	/* exclude the nonce here */
1444f26882a3SPascal van Leeuwen 	keylen = len - CTR_RFC3686_NONCE_SIZE;
144554f9e8faSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, keylen);
1446674f368aSEric Biggers 	if (ret)
144754f9e8faSPascal van Leeuwen 		return ret;
144854f9e8faSPascal van Leeuwen 
144954f9e8faSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
145054f9e8faSPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
145113a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
145254f9e8faSPascal van Leeuwen 				ctx->base.needs_inv = true;
145354f9e8faSPascal van Leeuwen 				break;
145454f9e8faSPascal van Leeuwen 			}
145554f9e8faSPascal van Leeuwen 		}
145654f9e8faSPascal van Leeuwen 	}
145754f9e8faSPascal van Leeuwen 
145854f9e8faSPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
145954f9e8faSPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
146054f9e8faSPascal van Leeuwen 
146154f9e8faSPascal van Leeuwen 	ctx->key_len = keylen;
146254f9e8faSPascal van Leeuwen 
146354f9e8faSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
146454f9e8faSPascal van Leeuwen 	return 0;
146554f9e8faSPascal van Leeuwen }
146654f9e8faSPascal van Leeuwen 
safexcel_skcipher_aes_ctr_cra_init(struct crypto_tfm * tfm)146793369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_ctr_cra_init(struct crypto_tfm *tfm)
146893369b5dSPascal van Leeuwen {
146993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
147093369b5dSPascal van Leeuwen 
147193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
147293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
1473098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
147493369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
147593369b5dSPascal van Leeuwen 	return 0;
147693369b5dSPascal van Leeuwen }
147793369b5dSPascal van Leeuwen 
147854f9e8faSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ctr_aes = {
147954f9e8faSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1480062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
148154f9e8faSPascal van Leeuwen 	.alg.skcipher = {
148254f9e8faSPascal van Leeuwen 		.setkey = safexcel_skcipher_aesctr_setkey,
148393369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
148493369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1485f26882a3SPascal van Leeuwen 		/* Add nonce size */
1486f26882a3SPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
1487f26882a3SPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
1488f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
148954f9e8faSPascal van Leeuwen 		.base = {
149054f9e8faSPascal van Leeuwen 			.cra_name = "rfc3686(ctr(aes))",
149154f9e8faSPascal van Leeuwen 			.cra_driver_name = "safexcel-ctr-aes",
1492aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
149354f9e8faSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1494b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
149554f9e8faSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
149654f9e8faSPascal van Leeuwen 			.cra_blocksize = 1,
149754f9e8faSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
149854f9e8faSPascal van Leeuwen 			.cra_alignmask = 0,
149993369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ctr_cra_init,
150054f9e8faSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
150154f9e8faSPascal van Leeuwen 			.cra_module = THIS_MODULE,
150254f9e8faSPascal van Leeuwen 		},
150354f9e8faSPascal van Leeuwen 	},
150454f9e8faSPascal van Leeuwen };
150554f9e8faSPascal van Leeuwen 
safexcel_des_setkey(struct crypto_skcipher * ctfm,const u8 * key,unsigned int len)1506a7dea8c0SOfer Heifetz static int safexcel_des_setkey(struct crypto_skcipher *ctfm, const u8 *key,
1507a7dea8c0SOfer Heifetz 			       unsigned int len)
1508a7dea8c0SOfer Heifetz {
150921f5a15eSArd Biesheuvel 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
151018e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
1511a7dea8c0SOfer Heifetz 	int ret;
1512a7dea8c0SOfer Heifetz 
151321f5a15eSArd Biesheuvel 	ret = verify_skcipher_des_key(ctfm, key);
151421f5a15eSArd Biesheuvel 	if (ret)
151521f5a15eSArd Biesheuvel 		return ret;
1516a7dea8c0SOfer Heifetz 
1517a7dea8c0SOfer Heifetz 	/* if context exits and key changed, need to invalidate it */
1518177e358cSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
1519a7dea8c0SOfer Heifetz 		if (memcmp(ctx->key, key, len))
1520a7dea8c0SOfer Heifetz 			ctx->base.needs_inv = true;
1521a7dea8c0SOfer Heifetz 
1522a7dea8c0SOfer Heifetz 	memcpy(ctx->key, key, len);
1523a7dea8c0SOfer Heifetz 	ctx->key_len = len;
1524a7dea8c0SOfer Heifetz 
1525a7dea8c0SOfer Heifetz 	return 0;
1526a7dea8c0SOfer Heifetz }
1527a7dea8c0SOfer Heifetz 
safexcel_skcipher_des_cbc_cra_init(struct crypto_tfm * tfm)152893369b5dSPascal van Leeuwen static int safexcel_skcipher_des_cbc_cra_init(struct crypto_tfm *tfm)
152993369b5dSPascal van Leeuwen {
153093369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
153193369b5dSPascal van Leeuwen 
153293369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
153393369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_DES;
1534098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
1535098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
153693369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
153793369b5dSPascal van Leeuwen 	return 0;
153893369b5dSPascal van Leeuwen }
153993369b5dSPascal van Leeuwen 
1540a7dea8c0SOfer Heifetz struct safexcel_alg_template safexcel_alg_cbc_des = {
1541a7dea8c0SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1542062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
1543a7dea8c0SOfer Heifetz 	.alg.skcipher = {
1544a7dea8c0SOfer Heifetz 		.setkey = safexcel_des_setkey,
154593369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
154693369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1547a7dea8c0SOfer Heifetz 		.min_keysize = DES_KEY_SIZE,
1548a7dea8c0SOfer Heifetz 		.max_keysize = DES_KEY_SIZE,
1549a7dea8c0SOfer Heifetz 		.ivsize = DES_BLOCK_SIZE,
1550a7dea8c0SOfer Heifetz 		.base = {
1551a7dea8c0SOfer Heifetz 			.cra_name = "cbc(des)",
1552a7dea8c0SOfer Heifetz 			.cra_driver_name = "safexcel-cbc-des",
1553aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
15542b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1555b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1556a7dea8c0SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1557a7dea8c0SOfer Heifetz 			.cra_blocksize = DES_BLOCK_SIZE,
1558a7dea8c0SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1559a7dea8c0SOfer Heifetz 			.cra_alignmask = 0,
156093369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des_cbc_cra_init,
1561a7dea8c0SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
1562a7dea8c0SOfer Heifetz 			.cra_module = THIS_MODULE,
1563a7dea8c0SOfer Heifetz 		},
1564a7dea8c0SOfer Heifetz 	},
1565a7dea8c0SOfer Heifetz };
1566a7dea8c0SOfer Heifetz 
safexcel_skcipher_des_ecb_cra_init(struct crypto_tfm * tfm)156793369b5dSPascal van Leeuwen static int safexcel_skcipher_des_ecb_cra_init(struct crypto_tfm *tfm)
1568a7dea8c0SOfer Heifetz {
156993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1570a7dea8c0SOfer Heifetz 
157193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
157293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_DES;
157393369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1574098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1575098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
157693369b5dSPascal van Leeuwen 	return 0;
1577a7dea8c0SOfer Heifetz }
1578a7dea8c0SOfer Heifetz 
1579a7dea8c0SOfer Heifetz struct safexcel_alg_template safexcel_alg_ecb_des = {
1580a7dea8c0SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1581062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
1582a7dea8c0SOfer Heifetz 	.alg.skcipher = {
1583a7dea8c0SOfer Heifetz 		.setkey = safexcel_des_setkey,
158493369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
158593369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1586a7dea8c0SOfer Heifetz 		.min_keysize = DES_KEY_SIZE,
1587a7dea8c0SOfer Heifetz 		.max_keysize = DES_KEY_SIZE,
1588a7dea8c0SOfer Heifetz 		.base = {
1589a7dea8c0SOfer Heifetz 			.cra_name = "ecb(des)",
1590a7dea8c0SOfer Heifetz 			.cra_driver_name = "safexcel-ecb-des",
1591aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
15922b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1593b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1594a7dea8c0SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1595a7dea8c0SOfer Heifetz 			.cra_blocksize = DES_BLOCK_SIZE,
1596a7dea8c0SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1597a7dea8c0SOfer Heifetz 			.cra_alignmask = 0,
159893369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des_ecb_cra_init,
1599a7dea8c0SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
1600a7dea8c0SOfer Heifetz 			.cra_module = THIS_MODULE,
1601a7dea8c0SOfer Heifetz 		},
1602a7dea8c0SOfer Heifetz 	},
1603a7dea8c0SOfer Heifetz };
160462469879SOfer Heifetz 
safexcel_des3_ede_setkey(struct crypto_skcipher * ctfm,const u8 * key,unsigned int len)160562469879SOfer Heifetz static int safexcel_des3_ede_setkey(struct crypto_skcipher *ctfm,
160662469879SOfer Heifetz 				   const u8 *key, unsigned int len)
160762469879SOfer Heifetz {
160867ac62bfSHerbert Xu 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
160918e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
161067ac62bfSHerbert Xu 	int err;
161162469879SOfer Heifetz 
161221f5a15eSArd Biesheuvel 	err = verify_skcipher_des3_key(ctfm, key);
161321f5a15eSArd Biesheuvel 	if (err)
161467ac62bfSHerbert Xu 		return err;
161562469879SOfer Heifetz 
161662469879SOfer Heifetz 	/* if context exits and key changed, need to invalidate it */
1617177e358cSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
161862469879SOfer Heifetz 		if (memcmp(ctx->key, key, len))
161962469879SOfer Heifetz 			ctx->base.needs_inv = true;
162062469879SOfer Heifetz 
162162469879SOfer Heifetz 	memcpy(ctx->key, key, len);
162262469879SOfer Heifetz 	ctx->key_len = len;
162362469879SOfer Heifetz 
162462469879SOfer Heifetz 	return 0;
162562469879SOfer Heifetz }
162662469879SOfer Heifetz 
safexcel_skcipher_des3_cbc_cra_init(struct crypto_tfm * tfm)162793369b5dSPascal van Leeuwen static int safexcel_skcipher_des3_cbc_cra_init(struct crypto_tfm *tfm)
162893369b5dSPascal van Leeuwen {
162993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
163093369b5dSPascal van Leeuwen 
163193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
163293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_3DES;
1633098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1634098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
163593369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
163693369b5dSPascal van Leeuwen 	return 0;
163793369b5dSPascal van Leeuwen }
163893369b5dSPascal van Leeuwen 
163962469879SOfer Heifetz struct safexcel_alg_template safexcel_alg_cbc_des3_ede = {
164062469879SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1641062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
164262469879SOfer Heifetz 	.alg.skcipher = {
164362469879SOfer Heifetz 		.setkey = safexcel_des3_ede_setkey,
164493369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
164593369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
164662469879SOfer Heifetz 		.min_keysize = DES3_EDE_KEY_SIZE,
164762469879SOfer Heifetz 		.max_keysize = DES3_EDE_KEY_SIZE,
164862469879SOfer Heifetz 		.ivsize = DES3_EDE_BLOCK_SIZE,
164962469879SOfer Heifetz 		.base = {
165062469879SOfer Heifetz 			.cra_name = "cbc(des3_ede)",
165162469879SOfer Heifetz 			.cra_driver_name = "safexcel-cbc-des3_ede",
1652aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
16532b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1654b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
165562469879SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
165662469879SOfer Heifetz 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
165762469879SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
165862469879SOfer Heifetz 			.cra_alignmask = 0,
165993369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des3_cbc_cra_init,
166062469879SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
166162469879SOfer Heifetz 			.cra_module = THIS_MODULE,
166262469879SOfer Heifetz 		},
166362469879SOfer Heifetz 	},
166462469879SOfer Heifetz };
166562469879SOfer Heifetz 
safexcel_skcipher_des3_ecb_cra_init(struct crypto_tfm * tfm)166693369b5dSPascal van Leeuwen static int safexcel_skcipher_des3_ecb_cra_init(struct crypto_tfm *tfm)
166762469879SOfer Heifetz {
166893369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
166962469879SOfer Heifetz 
167093369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
167193369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_3DES;
167293369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
1673098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
1674098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
167593369b5dSPascal van Leeuwen 	return 0;
167662469879SOfer Heifetz }
167762469879SOfer Heifetz 
167862469879SOfer Heifetz struct safexcel_alg_template safexcel_alg_ecb_des3_ede = {
167962469879SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1680062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
168162469879SOfer Heifetz 	.alg.skcipher = {
168262469879SOfer Heifetz 		.setkey = safexcel_des3_ede_setkey,
168393369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
168493369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
168562469879SOfer Heifetz 		.min_keysize = DES3_EDE_KEY_SIZE,
168662469879SOfer Heifetz 		.max_keysize = DES3_EDE_KEY_SIZE,
168762469879SOfer Heifetz 		.base = {
168862469879SOfer Heifetz 			.cra_name = "ecb(des3_ede)",
168962469879SOfer Heifetz 			.cra_driver_name = "safexcel-ecb-des3_ede",
1690aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
16912b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1692b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
169362469879SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
169462469879SOfer Heifetz 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
169562469879SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
169662469879SOfer Heifetz 			.cra_alignmask = 0,
169793369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des3_ecb_cra_init,
169862469879SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
169962469879SOfer Heifetz 			.cra_module = THIS_MODULE,
170062469879SOfer Heifetz 		},
170162469879SOfer Heifetz 	},
170262469879SOfer Heifetz };
170362469879SOfer Heifetz 
safexcel_aead_encrypt(struct aead_request * req)170493369b5dSPascal van Leeuwen static int safexcel_aead_encrypt(struct aead_request *req)
1705f6beaea3SAntoine Tenart {
1706f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
1707f6beaea3SAntoine Tenart 
170893369b5dSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
1709f6beaea3SAntoine Tenart }
1710f6beaea3SAntoine Tenart 
safexcel_aead_decrypt(struct aead_request * req)171193369b5dSPascal van Leeuwen static int safexcel_aead_decrypt(struct aead_request *req)
1712f6beaea3SAntoine Tenart {
1713f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
1714f6beaea3SAntoine Tenart 
171593369b5dSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
1716f6beaea3SAntoine Tenart }
1717f6beaea3SAntoine Tenart 
safexcel_aead_cra_init(struct crypto_tfm * tfm)1718f6beaea3SAntoine Tenart static int safexcel_aead_cra_init(struct crypto_tfm *tfm)
1719f6beaea3SAntoine Tenart {
1720f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1721f6beaea3SAntoine Tenart 	struct safexcel_alg_template *tmpl =
1722f6beaea3SAntoine Tenart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
1723f6beaea3SAntoine Tenart 			     alg.aead.base);
1724f6beaea3SAntoine Tenart 
1725f6beaea3SAntoine Tenart 	crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
1726f6beaea3SAntoine Tenart 				sizeof(struct safexcel_cipher_req));
1727f6beaea3SAntoine Tenart 
172818e51895SHerbert Xu 	ctx->base.priv = tmpl->priv;
1729f6beaea3SAntoine Tenart 
17300e17e362SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES; /* default */
1731098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
1732098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD;
1733098e51e5SPascal van Leeuwen 	ctx->ctrinit = 1;
173493369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; /* default */
1735f6beaea3SAntoine Tenart 	ctx->aead = true;
1736f6beaea3SAntoine Tenart 	ctx->base.send = safexcel_aead_send;
1737f6beaea3SAntoine Tenart 	ctx->base.handle_result = safexcel_aead_handle_result;
1738f6beaea3SAntoine Tenart 	return 0;
1739f6beaea3SAntoine Tenart }
1740f6beaea3SAntoine Tenart 
safexcel_aead_sha1_cra_init(struct crypto_tfm * tfm)174101ba061dSAntoine Tenart static int safexcel_aead_sha1_cra_init(struct crypto_tfm *tfm)
174201ba061dSAntoine Tenart {
174301ba061dSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
174401ba061dSAntoine Tenart 
174501ba061dSAntoine Tenart 	safexcel_aead_cra_init(tfm);
1746a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
174701ba061dSAntoine Tenart 	ctx->state_sz = SHA1_DIGEST_SIZE;
174801ba061dSAntoine Tenart 	return 0;
174901ba061dSAntoine Tenart }
175001ba061dSAntoine Tenart 
175101ba061dSAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_aes = {
175201ba061dSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1753062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA1,
175401ba061dSAntoine Tenart 	.alg.aead = {
175577cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
175693369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
175793369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
175801ba061dSAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
175901ba061dSAntoine Tenart 		.maxauthsize = SHA1_DIGEST_SIZE,
176001ba061dSAntoine Tenart 		.base = {
176101ba061dSAntoine Tenart 			.cra_name = "authenc(hmac(sha1),cbc(aes))",
176201ba061dSAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-aes",
1763aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
17643f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1765b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
176601ba061dSAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
176701ba061dSAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
176801ba061dSAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
176901ba061dSAntoine Tenart 			.cra_alignmask = 0,
177001ba061dSAntoine Tenart 			.cra_init = safexcel_aead_sha1_cra_init,
177101ba061dSAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
177201ba061dSAntoine Tenart 			.cra_module = THIS_MODULE,
177301ba061dSAntoine Tenart 		},
177401ba061dSAntoine Tenart 	},
177501ba061dSAntoine Tenart };
177601ba061dSAntoine Tenart 
safexcel_aead_sha256_cra_init(struct crypto_tfm * tfm)1777f6beaea3SAntoine Tenart static int safexcel_aead_sha256_cra_init(struct crypto_tfm *tfm)
1778f6beaea3SAntoine Tenart {
1779f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1780f6beaea3SAntoine Tenart 
1781f6beaea3SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1782a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1783f6beaea3SAntoine Tenart 	ctx->state_sz = SHA256_DIGEST_SIZE;
1784f6beaea3SAntoine Tenart 	return 0;
1785f6beaea3SAntoine Tenart }
1786f6beaea3SAntoine Tenart 
1787f6beaea3SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_aes = {
1788f6beaea3SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1789062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
1790f6beaea3SAntoine Tenart 	.alg.aead = {
179177cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
179293369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
179393369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1794f6beaea3SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1795f6beaea3SAntoine Tenart 		.maxauthsize = SHA256_DIGEST_SIZE,
1796f6beaea3SAntoine Tenart 		.base = {
1797f6beaea3SAntoine Tenart 			.cra_name = "authenc(hmac(sha256),cbc(aes))",
1798f6beaea3SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-aes",
1799aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18003f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1801b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1802f6beaea3SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1803f6beaea3SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1804f6beaea3SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1805f6beaea3SAntoine Tenart 			.cra_alignmask = 0,
1806f6beaea3SAntoine Tenart 			.cra_init = safexcel_aead_sha256_cra_init,
1807f6beaea3SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1808f6beaea3SAntoine Tenart 			.cra_module = THIS_MODULE,
1809f6beaea3SAntoine Tenart 		},
1810f6beaea3SAntoine Tenart 	},
1811f6beaea3SAntoine Tenart };
1812678b2878SAntoine Tenart 
safexcel_aead_sha224_cra_init(struct crypto_tfm * tfm)1813678b2878SAntoine Tenart static int safexcel_aead_sha224_cra_init(struct crypto_tfm *tfm)
1814678b2878SAntoine Tenart {
1815678b2878SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1816678b2878SAntoine Tenart 
1817678b2878SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1818a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1819678b2878SAntoine Tenart 	ctx->state_sz = SHA256_DIGEST_SIZE;
1820678b2878SAntoine Tenart 	return 0;
1821678b2878SAntoine Tenart }
1822678b2878SAntoine Tenart 
1823678b2878SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_aes = {
1824678b2878SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1825062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
1826678b2878SAntoine Tenart 	.alg.aead = {
182777cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
182893369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
182993369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1830678b2878SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1831678b2878SAntoine Tenart 		.maxauthsize = SHA224_DIGEST_SIZE,
1832678b2878SAntoine Tenart 		.base = {
1833678b2878SAntoine Tenart 			.cra_name = "authenc(hmac(sha224),cbc(aes))",
1834678b2878SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-aes",
1835aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18363f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1837b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1838678b2878SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1839678b2878SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1840678b2878SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1841678b2878SAntoine Tenart 			.cra_alignmask = 0,
1842678b2878SAntoine Tenart 			.cra_init = safexcel_aead_sha224_cra_init,
1843678b2878SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1844678b2878SAntoine Tenart 			.cra_module = THIS_MODULE,
1845678b2878SAntoine Tenart 		},
1846678b2878SAntoine Tenart 	},
1847678b2878SAntoine Tenart };
184887eee125SAntoine Tenart 
safexcel_aead_sha512_cra_init(struct crypto_tfm * tfm)184987eee125SAntoine Tenart static int safexcel_aead_sha512_cra_init(struct crypto_tfm *tfm)
185087eee125SAntoine Tenart {
185187eee125SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
185287eee125SAntoine Tenart 
185387eee125SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1854a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
185587eee125SAntoine Tenart 	ctx->state_sz = SHA512_DIGEST_SIZE;
185687eee125SAntoine Tenart 	return 0;
185787eee125SAntoine Tenart }
185887eee125SAntoine Tenart 
185987eee125SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_aes = {
186087eee125SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1861062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
186287eee125SAntoine Tenart 	.alg.aead = {
186377cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
186493369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
186593369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
186687eee125SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
186787eee125SAntoine Tenart 		.maxauthsize = SHA512_DIGEST_SIZE,
186887eee125SAntoine Tenart 		.base = {
186987eee125SAntoine Tenart 			.cra_name = "authenc(hmac(sha512),cbc(aes))",
187087eee125SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-aes",
1871aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18723f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1873b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
187487eee125SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
187587eee125SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
187687eee125SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
187787eee125SAntoine Tenart 			.cra_alignmask = 0,
187887eee125SAntoine Tenart 			.cra_init = safexcel_aead_sha512_cra_init,
187987eee125SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
188087eee125SAntoine Tenart 			.cra_module = THIS_MODULE,
188187eee125SAntoine Tenart 		},
188287eee125SAntoine Tenart 	},
188387eee125SAntoine Tenart };
1884ea23cb53SAntoine Tenart 
safexcel_aead_sha384_cra_init(struct crypto_tfm * tfm)1885ea23cb53SAntoine Tenart static int safexcel_aead_sha384_cra_init(struct crypto_tfm *tfm)
1886ea23cb53SAntoine Tenart {
1887ea23cb53SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1888ea23cb53SAntoine Tenart 
1889ea23cb53SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1890a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
1891ea23cb53SAntoine Tenart 	ctx->state_sz = SHA512_DIGEST_SIZE;
1892ea23cb53SAntoine Tenart 	return 0;
1893ea23cb53SAntoine Tenart }
1894ea23cb53SAntoine Tenart 
1895ea23cb53SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_aes = {
1896ea23cb53SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1897062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
1898ea23cb53SAntoine Tenart 	.alg.aead = {
189977cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
190093369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
190193369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1902ea23cb53SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1903ea23cb53SAntoine Tenart 		.maxauthsize = SHA384_DIGEST_SIZE,
1904ea23cb53SAntoine Tenart 		.base = {
1905ea23cb53SAntoine Tenart 			.cra_name = "authenc(hmac(sha384),cbc(aes))",
1906ea23cb53SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-aes",
1907aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
19083f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1909b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1910ea23cb53SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1911ea23cb53SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1912ea23cb53SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1913ea23cb53SAntoine Tenart 			.cra_alignmask = 0,
1914ea23cb53SAntoine Tenart 			.cra_init = safexcel_aead_sha384_cra_init,
1915ea23cb53SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1916ea23cb53SAntoine Tenart 			.cra_module = THIS_MODULE,
1917ea23cb53SAntoine Tenart 		},
1918ea23cb53SAntoine Tenart 	},
1919ea23cb53SAntoine Tenart };
192077cdd4efSPascal van Leeuwen 
safexcel_aead_sha1_des3_cra_init(struct crypto_tfm * tfm)19210e17e362SPascal van Leeuwen static int safexcel_aead_sha1_des3_cra_init(struct crypto_tfm *tfm)
19220e17e362SPascal van Leeuwen {
19230e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
19240e17e362SPascal van Leeuwen 
19250e17e362SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
19260e17e362SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1927098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1928098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
19290e17e362SPascal van Leeuwen 	return 0;
19300e17e362SPascal van Leeuwen }
19310e17e362SPascal van Leeuwen 
193277cdd4efSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des3_ede = {
193377cdd4efSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1934062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1,
193577cdd4efSPascal van Leeuwen 	.alg.aead = {
193677cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
193793369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
193893369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
193977cdd4efSPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
194077cdd4efSPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
194177cdd4efSPascal van Leeuwen 		.base = {
194277cdd4efSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
194377cdd4efSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des3_ede",
1944aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
194577cdd4efSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1946b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
194777cdd4efSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
194877cdd4efSPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
194977cdd4efSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
195077cdd4efSPascal van Leeuwen 			.cra_alignmask = 0,
19510e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_des3_cra_init,
19520e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
19530e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
19540e17e362SPascal van Leeuwen 		},
19550e17e362SPascal van Leeuwen 	},
19560e17e362SPascal van Leeuwen };
19570e17e362SPascal van Leeuwen 
safexcel_aead_sha256_des3_cra_init(struct crypto_tfm * tfm)1958f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha256_des3_cra_init(struct crypto_tfm *tfm)
1959f0a8bdf0SPascal van Leeuwen {
1960f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1961f0a8bdf0SPascal van Leeuwen 
1962f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
1963f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1964098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
1965098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
1966f0a8bdf0SPascal van Leeuwen 	return 0;
1967f0a8bdf0SPascal van Leeuwen }
1968f0a8bdf0SPascal van Leeuwen 
1969f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des3_ede = {
1970f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1971f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
1972f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
1973f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
1974f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
1975f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1976f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
1977f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
1978f0a8bdf0SPascal van Leeuwen 		.base = {
1979f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
1980f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des3_ede",
1981f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
1982f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1983b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
1984f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1985f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1986f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1987f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
1988f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_des3_cra_init,
1989f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
1990f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
1991f0a8bdf0SPascal van Leeuwen 		},
1992f0a8bdf0SPascal van Leeuwen 	},
1993f0a8bdf0SPascal van Leeuwen };
1994f0a8bdf0SPascal van Leeuwen 
safexcel_aead_sha224_des3_cra_init(struct crypto_tfm * tfm)1995f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha224_des3_cra_init(struct crypto_tfm *tfm)
1996f0a8bdf0SPascal van Leeuwen {
1997f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1998f0a8bdf0SPascal van Leeuwen 
1999f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
2000f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
2001098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
2002098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2003f0a8bdf0SPascal van Leeuwen 	return 0;
2004f0a8bdf0SPascal van Leeuwen }
2005f0a8bdf0SPascal van Leeuwen 
2006f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des3_ede = {
2007f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2008f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2009f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2010f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2011f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2012f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2013f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2014f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
2015f0a8bdf0SPascal van Leeuwen 		.base = {
2016f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),cbc(des3_ede))",
2017f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des3_ede",
2018f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2019f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2020b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2021f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2022f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2023f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2024f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2025f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_des3_cra_init,
2026f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2027f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2028f0a8bdf0SPascal van Leeuwen 		},
2029f0a8bdf0SPascal van Leeuwen 	},
2030f0a8bdf0SPascal van Leeuwen };
2031f0a8bdf0SPascal van Leeuwen 
safexcel_aead_sha512_des3_cra_init(struct crypto_tfm * tfm)2032f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha512_des3_cra_init(struct crypto_tfm *tfm)
2033f0a8bdf0SPascal van Leeuwen {
2034f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2035f0a8bdf0SPascal van Leeuwen 
2036f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
2037f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
2038098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
2039098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2040f0a8bdf0SPascal van Leeuwen 	return 0;
2041f0a8bdf0SPascal van Leeuwen }
2042f0a8bdf0SPascal van Leeuwen 
2043f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des3_ede = {
2044f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2045f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2046f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2047f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2048f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2049f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2050f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2051f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
2052f0a8bdf0SPascal van Leeuwen 		.base = {
2053f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),cbc(des3_ede))",
2054f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des3_ede",
2055f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2056f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2057b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2058f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2059f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2060f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2061f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2062f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_des3_cra_init,
2063f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2064f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2065f0a8bdf0SPascal van Leeuwen 		},
2066f0a8bdf0SPascal van Leeuwen 	},
2067f0a8bdf0SPascal van Leeuwen };
2068f0a8bdf0SPascal van Leeuwen 
safexcel_aead_sha384_des3_cra_init(struct crypto_tfm * tfm)2069f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha384_des3_cra_init(struct crypto_tfm *tfm)
2070f0a8bdf0SPascal van Leeuwen {
2071f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2072f0a8bdf0SPascal van Leeuwen 
2073f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
2074f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
2075098e51e5SPascal van Leeuwen 	ctx->blocksz = DES3_EDE_BLOCK_SIZE;
2076098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2077f0a8bdf0SPascal van Leeuwen 	return 0;
2078f0a8bdf0SPascal van Leeuwen }
2079f0a8bdf0SPascal van Leeuwen 
2080f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des3_ede = {
2081f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2082f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2083f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
2084f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2085f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2086f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2087f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
2088f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
2089f0a8bdf0SPascal van Leeuwen 		.base = {
2090f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),cbc(des3_ede))",
2091f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des3_ede",
2092f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2093f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2094b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2095f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2096f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2097f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2098f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2099f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_des3_cra_init,
2100f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2101f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2102f0a8bdf0SPascal van Leeuwen 		},
2103f0a8bdf0SPascal van Leeuwen 	},
2104f0a8bdf0SPascal van Leeuwen };
2105f0a8bdf0SPascal van Leeuwen 
safexcel_aead_sha1_des_cra_init(struct crypto_tfm * tfm)2106bb7679b8SPascal van Leeuwen static int safexcel_aead_sha1_des_cra_init(struct crypto_tfm *tfm)
2107bb7679b8SPascal van Leeuwen {
2108bb7679b8SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2109bb7679b8SPascal van Leeuwen 
2110bb7679b8SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
2111bb7679b8SPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2112098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2113098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2114bb7679b8SPascal van Leeuwen 	return 0;
2115bb7679b8SPascal van Leeuwen }
2116bb7679b8SPascal van Leeuwen 
2117bb7679b8SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des = {
2118bb7679b8SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2119bb7679b8SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1,
2120bb7679b8SPascal van Leeuwen 	.alg.aead = {
2121bb7679b8SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2122bb7679b8SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2123bb7679b8SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2124bb7679b8SPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2125bb7679b8SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
2126bb7679b8SPascal van Leeuwen 		.base = {
2127bb7679b8SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(des))",
2128bb7679b8SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des",
2129bb7679b8SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2130bb7679b8SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2131b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2132bb7679b8SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2133bb7679b8SPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2134bb7679b8SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2135bb7679b8SPascal van Leeuwen 			.cra_alignmask = 0,
2136bb7679b8SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_des_cra_init,
2137bb7679b8SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2138bb7679b8SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2139bb7679b8SPascal van Leeuwen 		},
2140bb7679b8SPascal van Leeuwen 	},
2141bb7679b8SPascal van Leeuwen };
2142bb7679b8SPascal van Leeuwen 
safexcel_aead_sha256_des_cra_init(struct crypto_tfm * tfm)2143457a6fdfSPascal van Leeuwen static int safexcel_aead_sha256_des_cra_init(struct crypto_tfm *tfm)
2144457a6fdfSPascal van Leeuwen {
2145457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2146457a6fdfSPascal van Leeuwen 
2147457a6fdfSPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
2148457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2149098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2150098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2151457a6fdfSPascal van Leeuwen 	return 0;
2152457a6fdfSPascal van Leeuwen }
2153457a6fdfSPascal van Leeuwen 
2154457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des = {
2155457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2156457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2157457a6fdfSPascal van Leeuwen 	.alg.aead = {
2158457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2159457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2160457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2161457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2162457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
2163457a6fdfSPascal van Leeuwen 		.base = {
2164457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),cbc(des))",
2165457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des",
2166457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2167457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2168b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2169457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2170457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2171457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2172457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2173457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_des_cra_init,
2174457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2175457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2176457a6fdfSPascal van Leeuwen 		},
2177457a6fdfSPascal van Leeuwen 	},
2178457a6fdfSPascal van Leeuwen };
2179457a6fdfSPascal van Leeuwen 
safexcel_aead_sha224_des_cra_init(struct crypto_tfm * tfm)2180457a6fdfSPascal van Leeuwen static int safexcel_aead_sha224_des_cra_init(struct crypto_tfm *tfm)
2181457a6fdfSPascal van Leeuwen {
2182457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2183457a6fdfSPascal van Leeuwen 
2184457a6fdfSPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
2185457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2186098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2187098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2188457a6fdfSPascal van Leeuwen 	return 0;
2189457a6fdfSPascal van Leeuwen }
2190457a6fdfSPascal van Leeuwen 
2191457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des = {
2192457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2193457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2194457a6fdfSPascal van Leeuwen 	.alg.aead = {
2195457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2196457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2197457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2198457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2199457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
2200457a6fdfSPascal van Leeuwen 		.base = {
2201457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),cbc(des))",
2202457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des",
2203457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2204457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2205b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2206457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2207457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2208457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2209457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2210457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_des_cra_init,
2211457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2212457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2213457a6fdfSPascal van Leeuwen 		},
2214457a6fdfSPascal van Leeuwen 	},
2215457a6fdfSPascal van Leeuwen };
2216457a6fdfSPascal van Leeuwen 
safexcel_aead_sha512_des_cra_init(struct crypto_tfm * tfm)2217457a6fdfSPascal van Leeuwen static int safexcel_aead_sha512_des_cra_init(struct crypto_tfm *tfm)
2218457a6fdfSPascal van Leeuwen {
2219457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2220457a6fdfSPascal van Leeuwen 
2221457a6fdfSPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
2222457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2223098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2224098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2225457a6fdfSPascal van Leeuwen 	return 0;
2226457a6fdfSPascal van Leeuwen }
2227457a6fdfSPascal van Leeuwen 
2228457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des = {
2229457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2230457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2231457a6fdfSPascal van Leeuwen 	.alg.aead = {
2232457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2233457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2234457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2235457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2236457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
2237457a6fdfSPascal van Leeuwen 		.base = {
2238457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),cbc(des))",
2239457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des",
2240457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2241457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2242b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2243457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2244457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2245457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2246457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2247457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_des_cra_init,
2248457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2249457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2250457a6fdfSPascal van Leeuwen 		},
2251457a6fdfSPascal van Leeuwen 	},
2252457a6fdfSPascal van Leeuwen };
2253457a6fdfSPascal van Leeuwen 
safexcel_aead_sha384_des_cra_init(struct crypto_tfm * tfm)2254457a6fdfSPascal van Leeuwen static int safexcel_aead_sha384_des_cra_init(struct crypto_tfm *tfm)
2255457a6fdfSPascal van Leeuwen {
2256457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2257457a6fdfSPascal van Leeuwen 
2258457a6fdfSPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
2259457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2260098e51e5SPascal van Leeuwen 	ctx->blocksz = DES_BLOCK_SIZE;
2261098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
2262457a6fdfSPascal van Leeuwen 	return 0;
2263457a6fdfSPascal van Leeuwen }
2264457a6fdfSPascal van Leeuwen 
2265457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des = {
2266457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2267457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2268457a6fdfSPascal van Leeuwen 	.alg.aead = {
2269457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2270457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2271457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2272457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2273457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
2274457a6fdfSPascal van Leeuwen 		.base = {
2275457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),cbc(des))",
2276457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des",
2277457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2278457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2279b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2280457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2281457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2282457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2283457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2284457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_des_cra_init,
2285457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2286457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2287457a6fdfSPascal van Leeuwen 		},
2288457a6fdfSPascal van Leeuwen 	},
2289457a6fdfSPascal van Leeuwen };
2290457a6fdfSPascal van Leeuwen 
safexcel_aead_sha1_ctr_cra_init(struct crypto_tfm * tfm)22910e17e362SPascal van Leeuwen static int safexcel_aead_sha1_ctr_cra_init(struct crypto_tfm *tfm)
22920e17e362SPascal van Leeuwen {
22930e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
22940e17e362SPascal van Leeuwen 
22950e17e362SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
22960e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
22970e17e362SPascal van Leeuwen 	return 0;
22980e17e362SPascal van Leeuwen }
22990e17e362SPascal van Leeuwen 
23000e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_aes = {
23010e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2302062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA1,
23030e17e362SPascal van Leeuwen 	.alg.aead = {
23040e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
230593369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
230693369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2307f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23080e17e362SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
23090e17e362SPascal van Leeuwen 		.base = {
23100e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
23110e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-aes",
2312aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23130e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2314b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
23150e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23160e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23170e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23180e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23190e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_ctr_cra_init,
23200e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23210e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23220e17e362SPascal van Leeuwen 		},
23230e17e362SPascal van Leeuwen 	},
23240e17e362SPascal van Leeuwen };
23250e17e362SPascal van Leeuwen 
safexcel_aead_sha256_ctr_cra_init(struct crypto_tfm * tfm)23260e17e362SPascal van Leeuwen static int safexcel_aead_sha256_ctr_cra_init(struct crypto_tfm *tfm)
23270e17e362SPascal van Leeuwen {
23280e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23290e17e362SPascal van Leeuwen 
23300e17e362SPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
23310e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23320e17e362SPascal van Leeuwen 	return 0;
23330e17e362SPascal van Leeuwen }
23340e17e362SPascal van Leeuwen 
23350e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_ctr_aes = {
23360e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2337062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
23380e17e362SPascal van Leeuwen 	.alg.aead = {
23390e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
234093369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
234193369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2342f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23430e17e362SPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
23440e17e362SPascal van Leeuwen 		.base = {
23450e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
23460e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-ctr-aes",
2347aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23480e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2349b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
23500e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23510e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23520e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23530e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23540e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_ctr_cra_init,
23550e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23560e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23570e17e362SPascal van Leeuwen 		},
23580e17e362SPascal van Leeuwen 	},
23590e17e362SPascal van Leeuwen };
23600e17e362SPascal van Leeuwen 
safexcel_aead_sha224_ctr_cra_init(struct crypto_tfm * tfm)23610e17e362SPascal van Leeuwen static int safexcel_aead_sha224_ctr_cra_init(struct crypto_tfm *tfm)
23620e17e362SPascal van Leeuwen {
23630e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23640e17e362SPascal van Leeuwen 
23650e17e362SPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
23660e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23670e17e362SPascal van Leeuwen 	return 0;
23680e17e362SPascal van Leeuwen }
23690e17e362SPascal van Leeuwen 
23700e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_ctr_aes = {
23710e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2372062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
23730e17e362SPascal van Leeuwen 	.alg.aead = {
23740e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
237593369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
237693369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2377f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23780e17e362SPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
23790e17e362SPascal van Leeuwen 		.base = {
23800e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))",
23810e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-ctr-aes",
2382aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23830e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2384b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
23850e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23860e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23870e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23880e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23890e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_ctr_cra_init,
23900e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23910e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23920e17e362SPascal van Leeuwen 		},
23930e17e362SPascal van Leeuwen 	},
23940e17e362SPascal van Leeuwen };
23950e17e362SPascal van Leeuwen 
safexcel_aead_sha512_ctr_cra_init(struct crypto_tfm * tfm)23960e17e362SPascal van Leeuwen static int safexcel_aead_sha512_ctr_cra_init(struct crypto_tfm *tfm)
23970e17e362SPascal van Leeuwen {
23980e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23990e17e362SPascal van Leeuwen 
24000e17e362SPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
24010e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
24020e17e362SPascal van Leeuwen 	return 0;
24030e17e362SPascal van Leeuwen }
24040e17e362SPascal van Leeuwen 
24050e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_ctr_aes = {
24060e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2407062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
24080e17e362SPascal van Leeuwen 	.alg.aead = {
24090e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
241093369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
241193369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2412f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
24130e17e362SPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
24140e17e362SPascal van Leeuwen 		.base = {
24150e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
24160e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-ctr-aes",
2417aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
24180e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2419b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
24200e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
24210e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
24220e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
24230e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
24240e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_ctr_cra_init,
24250e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
24260e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
24270e17e362SPascal van Leeuwen 		},
24280e17e362SPascal van Leeuwen 	},
24290e17e362SPascal van Leeuwen };
24300e17e362SPascal van Leeuwen 
safexcel_aead_sha384_ctr_cra_init(struct crypto_tfm * tfm)24310e17e362SPascal van Leeuwen static int safexcel_aead_sha384_ctr_cra_init(struct crypto_tfm *tfm)
24320e17e362SPascal van Leeuwen {
24330e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
24340e17e362SPascal van Leeuwen 
24350e17e362SPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
24360e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
24370e17e362SPascal van Leeuwen 	return 0;
24380e17e362SPascal van Leeuwen }
24390e17e362SPascal van Leeuwen 
24400e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_ctr_aes = {
24410e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2442062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
24430e17e362SPascal van Leeuwen 	.alg.aead = {
24440e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
244593369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
244693369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2447f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
24480e17e362SPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
24490e17e362SPascal van Leeuwen 		.base = {
24500e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
24510e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-ctr-aes",
2452aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
24530e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2454b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
24550e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
24560e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
24570e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
24580e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
24590e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_ctr_cra_init,
246077cdd4efSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
246177cdd4efSPascal van Leeuwen 			.cra_module = THIS_MODULE,
246277cdd4efSPascal van Leeuwen 		},
246377cdd4efSPascal van Leeuwen 	},
246477cdd4efSPascal van Leeuwen };
2465c7da38a7SPascal van Leeuwen 
safexcel_skcipher_aesxts_setkey(struct crypto_skcipher * ctfm,const u8 * key,unsigned int len)2466c7da38a7SPascal van Leeuwen static int safexcel_skcipher_aesxts_setkey(struct crypto_skcipher *ctfm,
2467c7da38a7SPascal van Leeuwen 					   const u8 *key, unsigned int len)
2468c7da38a7SPascal van Leeuwen {
2469c7da38a7SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
2470c7da38a7SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
247118e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
2472c7da38a7SPascal van Leeuwen 	struct crypto_aes_ctx aes;
2473c7da38a7SPascal van Leeuwen 	int ret, i;
2474c7da38a7SPascal van Leeuwen 	unsigned int keylen;
2475c7da38a7SPascal van Leeuwen 
2476c7da38a7SPascal van Leeuwen 	/* Check for illegal XTS keys */
2477c7da38a7SPascal van Leeuwen 	ret = xts_verify_key(ctfm, key, len);
2478c7da38a7SPascal van Leeuwen 	if (ret)
2479c7da38a7SPascal van Leeuwen 		return ret;
2480c7da38a7SPascal van Leeuwen 
2481c7da38a7SPascal van Leeuwen 	/* Only half of the key data is cipher key */
2482c7da38a7SPascal van Leeuwen 	keylen = (len >> 1);
2483c7da38a7SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, keylen);
2484674f368aSEric Biggers 	if (ret)
2485c7da38a7SPascal van Leeuwen 		return ret;
2486c7da38a7SPascal van Leeuwen 
2487c7da38a7SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
2488c7da38a7SPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
248913a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
2490c7da38a7SPascal van Leeuwen 				ctx->base.needs_inv = true;
2491c7da38a7SPascal van Leeuwen 				break;
2492c7da38a7SPascal van Leeuwen 			}
2493c7da38a7SPascal van Leeuwen 		}
2494c7da38a7SPascal van Leeuwen 	}
2495c7da38a7SPascal van Leeuwen 
2496c7da38a7SPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
2497c7da38a7SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
2498c7da38a7SPascal van Leeuwen 
2499c7da38a7SPascal van Leeuwen 	/* The other half is the tweak key */
2500c7da38a7SPascal van Leeuwen 	ret = aes_expandkey(&aes, (u8 *)(key + keylen), keylen);
2501674f368aSEric Biggers 	if (ret)
2502c7da38a7SPascal van Leeuwen 		return ret;
2503c7da38a7SPascal van Leeuwen 
2504c7da38a7SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
2505c7da38a7SPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
250613a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i + keylen / sizeof(u32)]) !=
250713a1bb93SPascal van Leeuwen 			    aes.key_enc[i]) {
2508c7da38a7SPascal van Leeuwen 				ctx->base.needs_inv = true;
2509c7da38a7SPascal van Leeuwen 				break;
2510c7da38a7SPascal van Leeuwen 			}
2511c7da38a7SPascal van Leeuwen 		}
2512c7da38a7SPascal van Leeuwen 	}
2513c7da38a7SPascal van Leeuwen 
2514c7da38a7SPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
2515c7da38a7SPascal van Leeuwen 		ctx->key[i + keylen / sizeof(u32)] =
2516c7da38a7SPascal van Leeuwen 			cpu_to_le32(aes.key_enc[i]);
2517c7da38a7SPascal van Leeuwen 
2518c7da38a7SPascal van Leeuwen 	ctx->key_len = keylen << 1;
2519c7da38a7SPascal van Leeuwen 
2520c7da38a7SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
2521c7da38a7SPascal van Leeuwen 	return 0;
2522c7da38a7SPascal van Leeuwen }
2523c7da38a7SPascal van Leeuwen 
safexcel_skcipher_aes_xts_cra_init(struct crypto_tfm * tfm)2524c7da38a7SPascal van Leeuwen static int safexcel_skcipher_aes_xts_cra_init(struct crypto_tfm *tfm)
2525c7da38a7SPascal van Leeuwen {
2526c7da38a7SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2527c7da38a7SPascal van Leeuwen 
2528c7da38a7SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
2529c7da38a7SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
2530098e51e5SPascal van Leeuwen 	ctx->blocksz = AES_BLOCK_SIZE;
2531c7da38a7SPascal van Leeuwen 	ctx->xts  = 1;
2532c7da38a7SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XTS;
2533c7da38a7SPascal van Leeuwen 	return 0;
2534c7da38a7SPascal van Leeuwen }
2535c7da38a7SPascal van Leeuwen 
safexcel_encrypt_xts(struct skcipher_request * req)2536c7da38a7SPascal van Leeuwen static int safexcel_encrypt_xts(struct skcipher_request *req)
2537c7da38a7SPascal van Leeuwen {
2538c7da38a7SPascal van Leeuwen 	if (req->cryptlen < XTS_BLOCK_SIZE)
2539c7da38a7SPascal van Leeuwen 		return -EINVAL;
2540c7da38a7SPascal van Leeuwen 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2541c7da38a7SPascal van Leeuwen 				  SAFEXCEL_ENCRYPT);
2542c7da38a7SPascal van Leeuwen }
2543c7da38a7SPascal van Leeuwen 
safexcel_decrypt_xts(struct skcipher_request * req)2544c7da38a7SPascal van Leeuwen static int safexcel_decrypt_xts(struct skcipher_request *req)
2545c7da38a7SPascal van Leeuwen {
2546c7da38a7SPascal van Leeuwen 	if (req->cryptlen < XTS_BLOCK_SIZE)
2547c7da38a7SPascal van Leeuwen 		return -EINVAL;
2548c7da38a7SPascal van Leeuwen 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2549c7da38a7SPascal van Leeuwen 				  SAFEXCEL_DECRYPT);
2550c7da38a7SPascal van Leeuwen }
2551c7da38a7SPascal van Leeuwen 
2552c7da38a7SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xts_aes = {
2553c7da38a7SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
2554062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XTS,
2555c7da38a7SPascal van Leeuwen 	.alg.skcipher = {
2556c7da38a7SPascal van Leeuwen 		.setkey = safexcel_skcipher_aesxts_setkey,
2557c7da38a7SPascal van Leeuwen 		.encrypt = safexcel_encrypt_xts,
2558c7da38a7SPascal van Leeuwen 		.decrypt = safexcel_decrypt_xts,
2559c7da38a7SPascal van Leeuwen 		/* XTS actually uses 2 AES keys glued together */
2560c7da38a7SPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE * 2,
2561c7da38a7SPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE * 2,
2562c7da38a7SPascal van Leeuwen 		.ivsize = XTS_BLOCK_SIZE,
2563c7da38a7SPascal van Leeuwen 		.base = {
2564c7da38a7SPascal van Leeuwen 			.cra_name = "xts(aes)",
2565c7da38a7SPascal van Leeuwen 			.cra_driver_name = "safexcel-xts-aes",
2566aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2567c7da38a7SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2568b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
2569c7da38a7SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2570c7da38a7SPascal van Leeuwen 			.cra_blocksize = XTS_BLOCK_SIZE,
2571c7da38a7SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2572c7da38a7SPascal van Leeuwen 			.cra_alignmask = 0,
2573c7da38a7SPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_xts_cra_init,
2574c7da38a7SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
2575c7da38a7SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2576c7da38a7SPascal van Leeuwen 		},
2577c7da38a7SPascal van Leeuwen 	},
2578c7da38a7SPascal van Leeuwen };
25793e450886SPascal van Leeuwen 
safexcel_aead_gcm_setkey(struct crypto_aead * ctfm,const u8 * key,unsigned int len)25803e450886SPascal van Leeuwen static int safexcel_aead_gcm_setkey(struct crypto_aead *ctfm, const u8 *key,
25813e450886SPascal van Leeuwen 				    unsigned int len)
25823e450886SPascal van Leeuwen {
25833e450886SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
25843e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
258518e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
25863e450886SPascal van Leeuwen 	struct crypto_aes_ctx aes;
25873e450886SPascal van Leeuwen 	u32 hashkey[AES_BLOCK_SIZE >> 2];
25883e450886SPascal van Leeuwen 	int ret, i;
25893e450886SPascal van Leeuwen 
25903e450886SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
25913e450886SPascal van Leeuwen 	if (ret) {
25923e450886SPascal van Leeuwen 		memzero_explicit(&aes, sizeof(aes));
25933e450886SPascal van Leeuwen 		return ret;
25943e450886SPascal van Leeuwen 	}
25953e450886SPascal van Leeuwen 
25963e450886SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
25973e450886SPascal van Leeuwen 		for (i = 0; i < len / sizeof(u32); i++) {
259813a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
25993e450886SPascal van Leeuwen 				ctx->base.needs_inv = true;
26003e450886SPascal van Leeuwen 				break;
26013e450886SPascal van Leeuwen 			}
26023e450886SPascal van Leeuwen 		}
26033e450886SPascal van Leeuwen 	}
26043e450886SPascal van Leeuwen 
26053e450886SPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
26063e450886SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
26073e450886SPascal van Leeuwen 
26083e450886SPascal van Leeuwen 	ctx->key_len = len;
26093e450886SPascal van Leeuwen 
26103e450886SPascal van Leeuwen 	/* Compute hash key by encrypting zeroes with cipher key */
26113e450886SPascal van Leeuwen 	memset(hashkey, 0, AES_BLOCK_SIZE);
2612320406cbSPeter Harliman Liem 	aes_encrypt(&aes, (u8 *)hashkey, (u8 *)hashkey);
26133e450886SPascal van Leeuwen 
26143e450886SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
26153e450886SPascal van Leeuwen 		for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) {
261678cf1c8bSHerbert Xu 			if (be32_to_cpu(ctx->base.ipad.be[i]) != hashkey[i]) {
26173e450886SPascal van Leeuwen 				ctx->base.needs_inv = true;
26183e450886SPascal van Leeuwen 				break;
26193e450886SPascal van Leeuwen 			}
26203e450886SPascal van Leeuwen 		}
26213e450886SPascal van Leeuwen 	}
26223e450886SPascal van Leeuwen 
26233e450886SPascal van Leeuwen 	for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
262478cf1c8bSHerbert Xu 		ctx->base.ipad.be[i] = cpu_to_be32(hashkey[i]);
26253e450886SPascal van Leeuwen 
26263e450886SPascal van Leeuwen 	memzero_explicit(hashkey, AES_BLOCK_SIZE);
26273e450886SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
26283e450886SPascal van Leeuwen 	return 0;
26293e450886SPascal van Leeuwen }
26303e450886SPascal van Leeuwen 
safexcel_aead_gcm_cra_init(struct crypto_tfm * tfm)26313e450886SPascal van Leeuwen static int safexcel_aead_gcm_cra_init(struct crypto_tfm *tfm)
26323e450886SPascal van Leeuwen {
26333e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
26343e450886SPascal van Leeuwen 
26353e450886SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
26363e450886SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_GHASH;
26373e450886SPascal van Leeuwen 	ctx->state_sz = GHASH_BLOCK_SIZE;
26384eb76fafSPascal van Leeuwen 	ctx->xcm = EIP197_XCM_MODE_GCM;
26393e450886SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */
26403e450886SPascal van Leeuwen 
2641320406cbSPeter Harliman Liem 	return 0;
26423e450886SPascal van Leeuwen }
26433e450886SPascal van Leeuwen 
safexcel_aead_gcm_cra_exit(struct crypto_tfm * tfm)26443e450886SPascal van Leeuwen static void safexcel_aead_gcm_cra_exit(struct crypto_tfm *tfm)
26453e450886SPascal van Leeuwen {
26463e450886SPascal van Leeuwen 	safexcel_aead_cra_exit(tfm);
26473e450886SPascal van Leeuwen }
26483e450886SPascal van Leeuwen 
safexcel_aead_gcm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)26493e450886SPascal van Leeuwen static int safexcel_aead_gcm_setauthsize(struct crypto_aead *tfm,
26503e450886SPascal van Leeuwen 					 unsigned int authsize)
26513e450886SPascal van Leeuwen {
26523e450886SPascal van Leeuwen 	return crypto_gcm_check_authsize(authsize);
26533e450886SPascal van Leeuwen }
26543e450886SPascal van Leeuwen 
26553e450886SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_gcm = {
26563e450886SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
26573e450886SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
26583e450886SPascal van Leeuwen 	.alg.aead = {
26593e450886SPascal van Leeuwen 		.setkey = safexcel_aead_gcm_setkey,
26603e450886SPascal van Leeuwen 		.setauthsize = safexcel_aead_gcm_setauthsize,
26613e450886SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
26623e450886SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
26633e450886SPascal van Leeuwen 		.ivsize = GCM_AES_IV_SIZE,
26643e450886SPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
26653e450886SPascal van Leeuwen 		.base = {
26663e450886SPascal van Leeuwen 			.cra_name = "gcm(aes)",
26673e450886SPascal van Leeuwen 			.cra_driver_name = "safexcel-gcm-aes",
26683e450886SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
26693e450886SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2670b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
26713e450886SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
26723e450886SPascal van Leeuwen 			.cra_blocksize = 1,
26733e450886SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
26743e450886SPascal van Leeuwen 			.cra_alignmask = 0,
26753e450886SPascal van Leeuwen 			.cra_init = safexcel_aead_gcm_cra_init,
26763e450886SPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
26773e450886SPascal van Leeuwen 			.cra_module = THIS_MODULE,
26783e450886SPascal van Leeuwen 		},
26793e450886SPascal van Leeuwen 	},
26803e450886SPascal van Leeuwen };
26814eb76fafSPascal van Leeuwen 
safexcel_aead_ccm_setkey(struct crypto_aead * ctfm,const u8 * key,unsigned int len)26824eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_setkey(struct crypto_aead *ctfm, const u8 *key,
26834eb76fafSPascal van Leeuwen 				    unsigned int len)
26844eb76fafSPascal van Leeuwen {
26854eb76fafSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
26864eb76fafSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
268718e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
26884eb76fafSPascal van Leeuwen 	struct crypto_aes_ctx aes;
26894eb76fafSPascal van Leeuwen 	int ret, i;
26904eb76fafSPascal van Leeuwen 
26914eb76fafSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
26924eb76fafSPascal van Leeuwen 	if (ret) {
26934eb76fafSPascal van Leeuwen 		memzero_explicit(&aes, sizeof(aes));
26944eb76fafSPascal van Leeuwen 		return ret;
26954eb76fafSPascal van Leeuwen 	}
26964eb76fafSPascal van Leeuwen 
26974eb76fafSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
26984eb76fafSPascal van Leeuwen 		for (i = 0; i < len / sizeof(u32); i++) {
269913a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
27004eb76fafSPascal van Leeuwen 				ctx->base.needs_inv = true;
27014eb76fafSPascal van Leeuwen 				break;
27024eb76fafSPascal van Leeuwen 			}
27034eb76fafSPascal van Leeuwen 		}
27044eb76fafSPascal van Leeuwen 	}
27054eb76fafSPascal van Leeuwen 
27064eb76fafSPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++) {
27074eb76fafSPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
270878cf1c8bSHerbert Xu 		ctx->base.ipad.be[i + 2 * AES_BLOCK_SIZE / sizeof(u32)] =
27094eb76fafSPascal van Leeuwen 			cpu_to_be32(aes.key_enc[i]);
27104eb76fafSPascal van Leeuwen 	}
27114eb76fafSPascal van Leeuwen 
27124eb76fafSPascal van Leeuwen 	ctx->key_len = len;
27134eb76fafSPascal van Leeuwen 	ctx->state_sz = 2 * AES_BLOCK_SIZE + len;
27144eb76fafSPascal van Leeuwen 
27154eb76fafSPascal van Leeuwen 	if (len == AES_KEYSIZE_192)
27164eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
27174eb76fafSPascal van Leeuwen 	else if (len == AES_KEYSIZE_256)
27184eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
27194eb76fafSPascal van Leeuwen 	else
27204eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
27214eb76fafSPascal van Leeuwen 
27224eb76fafSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
27234eb76fafSPascal van Leeuwen 	return 0;
27244eb76fafSPascal van Leeuwen }
27254eb76fafSPascal van Leeuwen 
safexcel_aead_ccm_cra_init(struct crypto_tfm * tfm)27264eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_cra_init(struct crypto_tfm *tfm)
27274eb76fafSPascal van Leeuwen {
27284eb76fafSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
27294eb76fafSPascal van Leeuwen 
27304eb76fafSPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
27314eb76fafSPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
27324eb76fafSPascal van Leeuwen 	ctx->state_sz = 3 * AES_BLOCK_SIZE;
27334eb76fafSPascal van Leeuwen 	ctx->xcm = EIP197_XCM_MODE_CCM;
27344eb76fafSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */
2735098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
27364eb76fafSPascal van Leeuwen 	return 0;
27374eb76fafSPascal van Leeuwen }
27384eb76fafSPascal van Leeuwen 
safexcel_aead_ccm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)27394eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_setauthsize(struct crypto_aead *tfm,
27404eb76fafSPascal van Leeuwen 					 unsigned int authsize)
27414eb76fafSPascal van Leeuwen {
27424eb76fafSPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
27434eb76fafSPascal van Leeuwen 	switch (authsize) {
27444eb76fafSPascal van Leeuwen 	case 4:
27454eb76fafSPascal van Leeuwen 	case 6:
27464eb76fafSPascal van Leeuwen 	case 8:
27474eb76fafSPascal van Leeuwen 	case 10:
27484eb76fafSPascal van Leeuwen 	case 12:
27494eb76fafSPascal van Leeuwen 	case 14:
27504eb76fafSPascal van Leeuwen 	case 16:
27514eb76fafSPascal van Leeuwen 		break;
27524eb76fafSPascal van Leeuwen 	default:
27534eb76fafSPascal van Leeuwen 		return -EINVAL;
27544eb76fafSPascal van Leeuwen 	}
27554eb76fafSPascal van Leeuwen 
27564eb76fafSPascal van Leeuwen 	return 0;
27574eb76fafSPascal van Leeuwen }
27584eb76fafSPascal van Leeuwen 
safexcel_ccm_encrypt(struct aead_request * req)27594eb76fafSPascal van Leeuwen static int safexcel_ccm_encrypt(struct aead_request *req)
27604eb76fafSPascal van Leeuwen {
27614eb76fafSPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
27624eb76fafSPascal van Leeuwen 
27634eb76fafSPascal van Leeuwen 	if (req->iv[0] < 1 || req->iv[0] > 7)
27644eb76fafSPascal van Leeuwen 		return -EINVAL;
27654eb76fafSPascal van Leeuwen 
27664eb76fafSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
27674eb76fafSPascal van Leeuwen }
27684eb76fafSPascal van Leeuwen 
safexcel_ccm_decrypt(struct aead_request * req)27694eb76fafSPascal van Leeuwen static int safexcel_ccm_decrypt(struct aead_request *req)
27704eb76fafSPascal van Leeuwen {
27714eb76fafSPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
27724eb76fafSPascal van Leeuwen 
27734eb76fafSPascal van Leeuwen 	if (req->iv[0] < 1 || req->iv[0] > 7)
27744eb76fafSPascal van Leeuwen 		return -EINVAL;
27754eb76fafSPascal van Leeuwen 
27764eb76fafSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
27774eb76fafSPascal van Leeuwen }
27784eb76fafSPascal van Leeuwen 
27794eb76fafSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ccm = {
27804eb76fafSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
27814eb76fafSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL,
27824eb76fafSPascal van Leeuwen 	.alg.aead = {
27834eb76fafSPascal van Leeuwen 		.setkey = safexcel_aead_ccm_setkey,
27844eb76fafSPascal van Leeuwen 		.setauthsize = safexcel_aead_ccm_setauthsize,
27854eb76fafSPascal van Leeuwen 		.encrypt = safexcel_ccm_encrypt,
27864eb76fafSPascal van Leeuwen 		.decrypt = safexcel_ccm_decrypt,
27874eb76fafSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
27884eb76fafSPascal van Leeuwen 		.maxauthsize = AES_BLOCK_SIZE,
27894eb76fafSPascal van Leeuwen 		.base = {
27904eb76fafSPascal van Leeuwen 			.cra_name = "ccm(aes)",
27914eb76fafSPascal van Leeuwen 			.cra_driver_name = "safexcel-ccm-aes",
27924eb76fafSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
27934eb76fafSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2794b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
27954eb76fafSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
27964eb76fafSPascal van Leeuwen 			.cra_blocksize = 1,
27974eb76fafSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
27984eb76fafSPascal van Leeuwen 			.cra_alignmask = 0,
27994eb76fafSPascal van Leeuwen 			.cra_init = safexcel_aead_ccm_cra_init,
28004eb76fafSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
28014eb76fafSPascal van Leeuwen 			.cra_module = THIS_MODULE,
28024eb76fafSPascal van Leeuwen 		},
28034eb76fafSPascal van Leeuwen 	},
28044eb76fafSPascal van Leeuwen };
28054a593fb3SPascal van Leeuwen 
safexcel_chacha20_setkey(struct safexcel_cipher_ctx * ctx,const u8 * key)2806a6061921SPascal van Leeuwen static void safexcel_chacha20_setkey(struct safexcel_cipher_ctx *ctx,
2807a6061921SPascal van Leeuwen 				     const u8 *key)
28084a593fb3SPascal van Leeuwen {
280918e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
28104a593fb3SPascal van Leeuwen 
281113a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
281213a1bb93SPascal van Leeuwen 		if (memcmp(ctx->key, key, CHACHA_KEY_SIZE))
28134a593fb3SPascal van Leeuwen 			ctx->base.needs_inv = true;
28144a593fb3SPascal van Leeuwen 
281513a1bb93SPascal van Leeuwen 	memcpy(ctx->key, key, CHACHA_KEY_SIZE);
28164a593fb3SPascal van Leeuwen 	ctx->key_len = CHACHA_KEY_SIZE;
2817a6061921SPascal van Leeuwen }
2818a6061921SPascal van Leeuwen 
safexcel_skcipher_chacha20_setkey(struct crypto_skcipher * ctfm,const u8 * key,unsigned int len)2819a6061921SPascal van Leeuwen static int safexcel_skcipher_chacha20_setkey(struct crypto_skcipher *ctfm,
2820a6061921SPascal van Leeuwen 					     const u8 *key, unsigned int len)
2821a6061921SPascal van Leeuwen {
2822a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
2823a6061921SPascal van Leeuwen 
2824674f368aSEric Biggers 	if (len != CHACHA_KEY_SIZE)
2825a6061921SPascal van Leeuwen 		return -EINVAL;
2826674f368aSEric Biggers 
2827a6061921SPascal van Leeuwen 	safexcel_chacha20_setkey(ctx, key);
28284a593fb3SPascal van Leeuwen 
28294a593fb3SPascal van Leeuwen 	return 0;
28304a593fb3SPascal van Leeuwen }
28314a593fb3SPascal van Leeuwen 
safexcel_skcipher_chacha20_cra_init(struct crypto_tfm * tfm)28324a593fb3SPascal van Leeuwen static int safexcel_skcipher_chacha20_cra_init(struct crypto_tfm *tfm)
28334a593fb3SPascal van Leeuwen {
28344a593fb3SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
28354a593fb3SPascal van Leeuwen 
28364a593fb3SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
28374a593fb3SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_CHACHA20;
2838098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
28394a593fb3SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32;
28404a593fb3SPascal van Leeuwen 	return 0;
28414a593fb3SPascal van Leeuwen }
28424a593fb3SPascal van Leeuwen 
28434a593fb3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chacha20 = {
28444a593fb3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
28454a593fb3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20,
28464a593fb3SPascal van Leeuwen 	.alg.skcipher = {
28474a593fb3SPascal van Leeuwen 		.setkey = safexcel_skcipher_chacha20_setkey,
28484a593fb3SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
28494a593fb3SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
28504a593fb3SPascal van Leeuwen 		.min_keysize = CHACHA_KEY_SIZE,
28514a593fb3SPascal van Leeuwen 		.max_keysize = CHACHA_KEY_SIZE,
28524a593fb3SPascal van Leeuwen 		.ivsize = CHACHA_IV_SIZE,
28534a593fb3SPascal van Leeuwen 		.base = {
28544a593fb3SPascal van Leeuwen 			.cra_name = "chacha20",
28554a593fb3SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20",
28564a593fb3SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
28574a593fb3SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2858b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
28594a593fb3SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
28604a593fb3SPascal van Leeuwen 			.cra_blocksize = 1,
28614a593fb3SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
28624a593fb3SPascal van Leeuwen 			.cra_alignmask = 0,
28634a593fb3SPascal van Leeuwen 			.cra_init = safexcel_skcipher_chacha20_cra_init,
28644a593fb3SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
28654a593fb3SPascal van Leeuwen 			.cra_module = THIS_MODULE,
28664a593fb3SPascal van Leeuwen 		},
28674a593fb3SPascal van Leeuwen 	},
28684a593fb3SPascal van Leeuwen };
2869a6061921SPascal van Leeuwen 
safexcel_aead_chachapoly_setkey(struct crypto_aead * ctfm,const u8 * key,unsigned int len)2870a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_setkey(struct crypto_aead *ctfm,
2871a6061921SPascal van Leeuwen 				    const u8 *key, unsigned int len)
2872a6061921SPascal van Leeuwen {
2873a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_aead_ctx(ctfm);
2874a6061921SPascal van Leeuwen 
2875a6061921SPascal van Leeuwen 	if (ctx->aead  == EIP197_AEAD_TYPE_IPSEC_ESP &&
2876a6061921SPascal van Leeuwen 	    len > EIP197_AEAD_IPSEC_NONCE_SIZE) {
2877a6061921SPascal van Leeuwen 		/* ESP variant has nonce appended to key */
2878a6061921SPascal van Leeuwen 		len -= EIP197_AEAD_IPSEC_NONCE_SIZE;
2879a6061921SPascal van Leeuwen 		ctx->nonce = *(u32 *)(key + len);
2880a6061921SPascal van Leeuwen 	}
2881674f368aSEric Biggers 	if (len != CHACHA_KEY_SIZE)
2882a6061921SPascal van Leeuwen 		return -EINVAL;
2883674f368aSEric Biggers 
2884a6061921SPascal van Leeuwen 	safexcel_chacha20_setkey(ctx, key);
2885a6061921SPascal van Leeuwen 
2886a6061921SPascal van Leeuwen 	return 0;
2887a6061921SPascal van Leeuwen }
2888a6061921SPascal van Leeuwen 
safexcel_aead_chachapoly_setauthsize(struct crypto_aead * tfm,unsigned int authsize)2889a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_setauthsize(struct crypto_aead *tfm,
2890a6061921SPascal van Leeuwen 					 unsigned int authsize)
2891a6061921SPascal van Leeuwen {
2892a6061921SPascal van Leeuwen 	if (authsize != POLY1305_DIGEST_SIZE)
2893a6061921SPascal van Leeuwen 		return -EINVAL;
2894a6061921SPascal van Leeuwen 	return 0;
2895a6061921SPascal van Leeuwen }
2896a6061921SPascal van Leeuwen 
safexcel_aead_chachapoly_crypt(struct aead_request * req,enum safexcel_cipher_direction dir)2897a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_crypt(struct aead_request *req,
2898a6061921SPascal van Leeuwen 					  enum safexcel_cipher_direction dir)
2899a6061921SPascal van Leeuwen {
2900a6061921SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
2901a6061921SPascal van Leeuwen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2902a6061921SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
2903a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2904a6061921SPascal van Leeuwen 	struct aead_request *subreq = aead_request_ctx(req);
2905a6061921SPascal van Leeuwen 	u32 key[CHACHA_KEY_SIZE / sizeof(u32) + 1];
290613a1bb93SPascal van Leeuwen 	int ret = 0;
2907a6061921SPascal van Leeuwen 
2908a6061921SPascal van Leeuwen 	/*
2909a6061921SPascal van Leeuwen 	 * Instead of wasting time detecting umpteen silly corner cases,
2910a6061921SPascal van Leeuwen 	 * just dump all "small" requests to the fallback implementation.
2911a6061921SPascal van Leeuwen 	 * HW would not be faster on such small requests anyway.
2912a6061921SPascal van Leeuwen 	 */
2913a6061921SPascal van Leeuwen 	if (likely((ctx->aead != EIP197_AEAD_TYPE_IPSEC_ESP ||
2914a6061921SPascal van Leeuwen 		    req->assoclen >= EIP197_AEAD_IPSEC_IV_SIZE) &&
2915a6061921SPascal van Leeuwen 		   req->cryptlen > POLY1305_DIGEST_SIZE)) {
2916a6061921SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, dir);
2917a6061921SPascal van Leeuwen 	}
2918a6061921SPascal van Leeuwen 
2919a6061921SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
292013a1bb93SPascal van Leeuwen 	memcpy(key, ctx->key, CHACHA_KEY_SIZE);
2921a6061921SPascal van Leeuwen 	if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
2922a6061921SPascal van Leeuwen 		/* ESP variant has nonce appended to the key */
2923a6061921SPascal van Leeuwen 		key[CHACHA_KEY_SIZE / sizeof(u32)] = ctx->nonce;
2924a6061921SPascal van Leeuwen 		ret = crypto_aead_setkey(ctx->fback, (u8 *)key,
2925a6061921SPascal van Leeuwen 					 CHACHA_KEY_SIZE +
2926a6061921SPascal van Leeuwen 					 EIP197_AEAD_IPSEC_NONCE_SIZE);
2927a6061921SPascal van Leeuwen 	} else {
2928a6061921SPascal van Leeuwen 		ret = crypto_aead_setkey(ctx->fback, (u8 *)key,
2929a6061921SPascal van Leeuwen 					 CHACHA_KEY_SIZE);
2930a6061921SPascal van Leeuwen 	}
2931a6061921SPascal van Leeuwen 	if (ret) {
2932a6061921SPascal van Leeuwen 		crypto_aead_clear_flags(aead, CRYPTO_TFM_REQ_MASK);
2933a6061921SPascal van Leeuwen 		crypto_aead_set_flags(aead, crypto_aead_get_flags(ctx->fback) &
2934a6061921SPascal van Leeuwen 					    CRYPTO_TFM_REQ_MASK);
2935a6061921SPascal van Leeuwen 		return ret;
2936a6061921SPascal van Leeuwen 	}
2937a6061921SPascal van Leeuwen 
2938a6061921SPascal van Leeuwen 	aead_request_set_tfm(subreq, ctx->fback);
2939a6061921SPascal van Leeuwen 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
2940a6061921SPascal van Leeuwen 				  req->base.data);
2941a6061921SPascal van Leeuwen 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
2942a6061921SPascal van Leeuwen 			       req->iv);
2943a6061921SPascal van Leeuwen 	aead_request_set_ad(subreq, req->assoclen);
2944a6061921SPascal van Leeuwen 
2945a6061921SPascal van Leeuwen 	return (dir ==  SAFEXCEL_ENCRYPT) ?
2946a6061921SPascal van Leeuwen 		crypto_aead_encrypt(subreq) :
2947a6061921SPascal van Leeuwen 		crypto_aead_decrypt(subreq);
2948a6061921SPascal van Leeuwen }
2949a6061921SPascal van Leeuwen 
safexcel_aead_chachapoly_encrypt(struct aead_request * req)2950a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_encrypt(struct aead_request *req)
2951a6061921SPascal van Leeuwen {
2952a6061921SPascal van Leeuwen 	return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_ENCRYPT);
2953a6061921SPascal van Leeuwen }
2954a6061921SPascal van Leeuwen 
safexcel_aead_chachapoly_decrypt(struct aead_request * req)2955a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_decrypt(struct aead_request *req)
2956a6061921SPascal van Leeuwen {
2957a6061921SPascal van Leeuwen 	return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_DECRYPT);
2958a6061921SPascal van Leeuwen }
2959a6061921SPascal van Leeuwen 
safexcel_aead_fallback_cra_init(struct crypto_tfm * tfm)29601769f704SPascal van Leeuwen static int safexcel_aead_fallback_cra_init(struct crypto_tfm *tfm)
2961a6061921SPascal van Leeuwen {
2962a6061921SPascal van Leeuwen 	struct crypto_aead *aead = __crypto_aead_cast(tfm);
2963a6061921SPascal van Leeuwen 	struct aead_alg *alg = crypto_aead_alg(aead);
2964a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2965a6061921SPascal van Leeuwen 
2966a6061921SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
2967a6061921SPascal van Leeuwen 
2968a6061921SPascal van Leeuwen 	/* Allocate fallback implementation */
2969a6061921SPascal van Leeuwen 	ctx->fback = crypto_alloc_aead(alg->base.cra_name, 0,
2970a6061921SPascal van Leeuwen 				       CRYPTO_ALG_ASYNC |
2971a6061921SPascal van Leeuwen 				       CRYPTO_ALG_NEED_FALLBACK);
2972a6061921SPascal van Leeuwen 	if (IS_ERR(ctx->fback))
2973a6061921SPascal van Leeuwen 		return PTR_ERR(ctx->fback);
2974a6061921SPascal van Leeuwen 
2975a6061921SPascal van Leeuwen 	crypto_aead_set_reqsize(aead, max(sizeof(struct safexcel_cipher_req),
2976a6061921SPascal van Leeuwen 					  sizeof(struct aead_request) +
2977a6061921SPascal van Leeuwen 					  crypto_aead_reqsize(ctx->fback)));
2978a6061921SPascal van Leeuwen 
2979a6061921SPascal van Leeuwen 	return 0;
2980a6061921SPascal van Leeuwen }
2981a6061921SPascal van Leeuwen 
safexcel_aead_chachapoly_cra_init(struct crypto_tfm * tfm)29821769f704SPascal van Leeuwen static int safexcel_aead_chachapoly_cra_init(struct crypto_tfm *tfm)
29831769f704SPascal van Leeuwen {
29841769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
29851769f704SPascal van Leeuwen 
29861769f704SPascal van Leeuwen 	safexcel_aead_fallback_cra_init(tfm);
29871769f704SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_CHACHA20;
29881769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32 |
29891769f704SPascal van Leeuwen 		    CONTEXT_CONTROL_CHACHA20_MODE_CALC_OTK;
2990098e51e5SPascal van Leeuwen 	ctx->ctrinit = 0;
29911769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_POLY1305;
29921769f704SPascal van Leeuwen 	ctx->state_sz = 0; /* Precomputed by HW */
29931769f704SPascal van Leeuwen 	return 0;
29941769f704SPascal van Leeuwen }
29951769f704SPascal van Leeuwen 
safexcel_aead_fallback_cra_exit(struct crypto_tfm * tfm)29961769f704SPascal van Leeuwen static void safexcel_aead_fallback_cra_exit(struct crypto_tfm *tfm)
2997a6061921SPascal van Leeuwen {
2998a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2999a6061921SPascal van Leeuwen 
3000a6061921SPascal van Leeuwen 	crypto_free_aead(ctx->fback);
3001a6061921SPascal van Leeuwen 	safexcel_aead_cra_exit(tfm);
3002a6061921SPascal van Leeuwen }
3003a6061921SPascal van Leeuwen 
3004a6061921SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chachapoly = {
3005a6061921SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3006a6061921SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305,
3007a6061921SPascal van Leeuwen 	.alg.aead = {
3008a6061921SPascal van Leeuwen 		.setkey = safexcel_aead_chachapoly_setkey,
3009a6061921SPascal van Leeuwen 		.setauthsize = safexcel_aead_chachapoly_setauthsize,
3010a6061921SPascal van Leeuwen 		.encrypt = safexcel_aead_chachapoly_encrypt,
3011a6061921SPascal van Leeuwen 		.decrypt = safexcel_aead_chachapoly_decrypt,
3012a6061921SPascal van Leeuwen 		.ivsize = CHACHAPOLY_IV_SIZE,
3013a6061921SPascal van Leeuwen 		.maxauthsize = POLY1305_DIGEST_SIZE,
3014a6061921SPascal van Leeuwen 		.base = {
3015a6061921SPascal van Leeuwen 			.cra_name = "rfc7539(chacha20,poly1305)",
3016a6061921SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20-poly1305",
3017a6061921SPascal van Leeuwen 			/* +1 to put it above HW chacha + SW poly */
3018a6061921SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY + 1,
3019a6061921SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3020b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3021a6061921SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
3022a6061921SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
3023a6061921SPascal van Leeuwen 			.cra_blocksize = 1,
3024a6061921SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3025a6061921SPascal van Leeuwen 			.cra_alignmask = 0,
3026a6061921SPascal van Leeuwen 			.cra_init = safexcel_aead_chachapoly_cra_init,
30271769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
3028a6061921SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3029a6061921SPascal van Leeuwen 		},
3030a6061921SPascal van Leeuwen 	},
3031a6061921SPascal van Leeuwen };
3032a6061921SPascal van Leeuwen 
safexcel_aead_chachapolyesp_cra_init(struct crypto_tfm * tfm)3033a6061921SPascal van Leeuwen static int safexcel_aead_chachapolyesp_cra_init(struct crypto_tfm *tfm)
3034a6061921SPascal van Leeuwen {
3035a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3036a6061921SPascal van Leeuwen 	int ret;
3037a6061921SPascal van Leeuwen 
3038a6061921SPascal van Leeuwen 	ret = safexcel_aead_chachapoly_cra_init(tfm);
3039a6061921SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3040098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3041a6061921SPascal van Leeuwen 	return ret;
3042a6061921SPascal van Leeuwen }
3043a6061921SPascal van Leeuwen 
3044a6061921SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chachapoly_esp = {
3045a6061921SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3046a6061921SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305,
3047a6061921SPascal van Leeuwen 	.alg.aead = {
3048a6061921SPascal van Leeuwen 		.setkey = safexcel_aead_chachapoly_setkey,
3049a6061921SPascal van Leeuwen 		.setauthsize = safexcel_aead_chachapoly_setauthsize,
3050a6061921SPascal van Leeuwen 		.encrypt = safexcel_aead_chachapoly_encrypt,
3051a6061921SPascal van Leeuwen 		.decrypt = safexcel_aead_chachapoly_decrypt,
3052a6061921SPascal van Leeuwen 		.ivsize = CHACHAPOLY_IV_SIZE - EIP197_AEAD_IPSEC_NONCE_SIZE,
3053a6061921SPascal van Leeuwen 		.maxauthsize = POLY1305_DIGEST_SIZE,
3054a6061921SPascal van Leeuwen 		.base = {
3055a6061921SPascal van Leeuwen 			.cra_name = "rfc7539esp(chacha20,poly1305)",
3056a6061921SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20-poly1305-esp",
3057a6061921SPascal van Leeuwen 			/* +1 to put it above HW chacha + SW poly */
3058a6061921SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY + 1,
3059a6061921SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3060b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3061a6061921SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
3062a6061921SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
3063a6061921SPascal van Leeuwen 			.cra_blocksize = 1,
3064a6061921SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3065a6061921SPascal van Leeuwen 			.cra_alignmask = 0,
3066a6061921SPascal van Leeuwen 			.cra_init = safexcel_aead_chachapolyesp_cra_init,
30671769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
3068a6061921SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3069a6061921SPascal van Leeuwen 		},
3070a6061921SPascal van Leeuwen 	},
3071a6061921SPascal van Leeuwen };
3072fcca797dSPascal van Leeuwen 
safexcel_skcipher_sm4_setkey(struct crypto_skcipher * ctfm,const u8 * key,unsigned int len)3073fcca797dSPascal van Leeuwen static int safexcel_skcipher_sm4_setkey(struct crypto_skcipher *ctfm,
3074fcca797dSPascal van Leeuwen 					const u8 *key, unsigned int len)
3075fcca797dSPascal van Leeuwen {
3076fcca797dSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3077fcca797dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
307818e51895SHerbert Xu 	struct safexcel_crypto_priv *priv = ctx->base.priv;
3079fcca797dSPascal van Leeuwen 
3080674f368aSEric Biggers 	if (len != SM4_KEY_SIZE)
3081fcca797dSPascal van Leeuwen 		return -EINVAL;
3082fcca797dSPascal van Leeuwen 
308313a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
308413a1bb93SPascal van Leeuwen 		if (memcmp(ctx->key, key, SM4_KEY_SIZE))
3085fcca797dSPascal van Leeuwen 			ctx->base.needs_inv = true;
3086fcca797dSPascal van Leeuwen 
308713a1bb93SPascal van Leeuwen 	memcpy(ctx->key, key, SM4_KEY_SIZE);
3088fcca797dSPascal van Leeuwen 	ctx->key_len = SM4_KEY_SIZE;
3089fcca797dSPascal van Leeuwen 
3090fcca797dSPascal van Leeuwen 	return 0;
3091fcca797dSPascal van Leeuwen }
3092fcca797dSPascal van Leeuwen 
safexcel_sm4_blk_encrypt(struct skcipher_request * req)3093fcca797dSPascal van Leeuwen static int safexcel_sm4_blk_encrypt(struct skcipher_request *req)
3094fcca797dSPascal van Leeuwen {
3095fcca797dSPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
3096fcca797dSPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
3097fcca797dSPascal van Leeuwen 		return -EINVAL;
3098fcca797dSPascal van Leeuwen 	else
3099fcca797dSPascal van Leeuwen 		return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
3100fcca797dSPascal van Leeuwen 					  SAFEXCEL_ENCRYPT);
3101fcca797dSPascal van Leeuwen }
3102fcca797dSPascal van Leeuwen 
safexcel_sm4_blk_decrypt(struct skcipher_request * req)3103fcca797dSPascal van Leeuwen static int safexcel_sm4_blk_decrypt(struct skcipher_request *req)
3104fcca797dSPascal van Leeuwen {
3105fcca797dSPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
3106fcca797dSPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
3107fcca797dSPascal van Leeuwen 		return -EINVAL;
3108fcca797dSPascal van Leeuwen 	else
3109fcca797dSPascal van Leeuwen 		return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
3110fcca797dSPascal van Leeuwen 					  SAFEXCEL_DECRYPT);
3111fcca797dSPascal van Leeuwen }
3112fcca797dSPascal van Leeuwen 
safexcel_skcipher_sm4_ecb_cra_init(struct crypto_tfm * tfm)3113fcca797dSPascal van Leeuwen static int safexcel_skcipher_sm4_ecb_cra_init(struct crypto_tfm *tfm)
3114fcca797dSPascal van Leeuwen {
3115fcca797dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3116fcca797dSPascal van Leeuwen 
3117fcca797dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
3118fcca797dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3119fcca797dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
3120098e51e5SPascal van Leeuwen 	ctx->blocksz = 0;
3121098e51e5SPascal van Leeuwen 	ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD;
3122fcca797dSPascal van Leeuwen 	return 0;
3123fcca797dSPascal van Leeuwen }
3124fcca797dSPascal van Leeuwen 
3125fcca797dSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ecb_sm4 = {
3126fcca797dSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
3127fcca797dSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
3128fcca797dSPascal van Leeuwen 	.alg.skcipher = {
3129fcca797dSPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
3130fcca797dSPascal van Leeuwen 		.encrypt = safexcel_sm4_blk_encrypt,
3131fcca797dSPascal van Leeuwen 		.decrypt = safexcel_sm4_blk_decrypt,
3132fcca797dSPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
3133fcca797dSPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
3134fcca797dSPascal van Leeuwen 		.base = {
3135fcca797dSPascal van Leeuwen 			.cra_name = "ecb(sm4)",
3136fcca797dSPascal van Leeuwen 			.cra_driver_name = "safexcel-ecb-sm4",
3137fcca797dSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3138fcca797dSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3139b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3140fcca797dSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3141fcca797dSPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
3142fcca797dSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3143fcca797dSPascal van Leeuwen 			.cra_alignmask = 0,
3144fcca797dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ecb_cra_init,
3145fcca797dSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
3146fcca797dSPascal van Leeuwen 			.cra_module = THIS_MODULE,
3147fcca797dSPascal van Leeuwen 		},
3148fcca797dSPascal van Leeuwen 	},
3149fcca797dSPascal van Leeuwen };
31506f2d1428SPascal van Leeuwen 
safexcel_skcipher_sm4_cbc_cra_init(struct crypto_tfm * tfm)31516f2d1428SPascal van Leeuwen static int safexcel_skcipher_sm4_cbc_cra_init(struct crypto_tfm *tfm)
31526f2d1428SPascal van Leeuwen {
31536f2d1428SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
31546f2d1428SPascal van Leeuwen 
31556f2d1428SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
31566f2d1428SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3157098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
31586f2d1428SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
31596f2d1428SPascal van Leeuwen 	return 0;
31606f2d1428SPascal van Leeuwen }
31616f2d1428SPascal van Leeuwen 
31626f2d1428SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbc_sm4 = {
31636f2d1428SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
31646f2d1428SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
31656f2d1428SPascal van Leeuwen 	.alg.skcipher = {
31666f2d1428SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
31676f2d1428SPascal van Leeuwen 		.encrypt = safexcel_sm4_blk_encrypt,
31686f2d1428SPascal van Leeuwen 		.decrypt = safexcel_sm4_blk_decrypt,
31696f2d1428SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
31706f2d1428SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
31716f2d1428SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
31726f2d1428SPascal van Leeuwen 		.base = {
31736f2d1428SPascal van Leeuwen 			.cra_name = "cbc(sm4)",
31746f2d1428SPascal van Leeuwen 			.cra_driver_name = "safexcel-cbc-sm4",
31756f2d1428SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
31766f2d1428SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3177b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
31786f2d1428SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
31796f2d1428SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
31806f2d1428SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
31816f2d1428SPascal van Leeuwen 			.cra_alignmask = 0,
31826f2d1428SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_cbc_cra_init,
31836f2d1428SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
31846f2d1428SPascal van Leeuwen 			.cra_module = THIS_MODULE,
31856f2d1428SPascal van Leeuwen 		},
31866f2d1428SPascal van Leeuwen 	},
31876f2d1428SPascal van Leeuwen };
318803a6cfb9SPascal van Leeuwen 
safexcel_skcipher_sm4_ofb_cra_init(struct crypto_tfm * tfm)318903a6cfb9SPascal van Leeuwen static int safexcel_skcipher_sm4_ofb_cra_init(struct crypto_tfm *tfm)
319003a6cfb9SPascal van Leeuwen {
319103a6cfb9SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
319203a6cfb9SPascal van Leeuwen 
319303a6cfb9SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
319403a6cfb9SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3195098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
319603a6cfb9SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB;
319703a6cfb9SPascal van Leeuwen 	return 0;
319803a6cfb9SPascal van Leeuwen }
319903a6cfb9SPascal van Leeuwen 
320003a6cfb9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ofb_sm4 = {
320103a6cfb9SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
320203a6cfb9SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB,
320303a6cfb9SPascal van Leeuwen 	.alg.skcipher = {
320403a6cfb9SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
320503a6cfb9SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
320603a6cfb9SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
320703a6cfb9SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
320803a6cfb9SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
320903a6cfb9SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
321003a6cfb9SPascal van Leeuwen 		.base = {
321103a6cfb9SPascal van Leeuwen 			.cra_name = "ofb(sm4)",
321203a6cfb9SPascal van Leeuwen 			.cra_driver_name = "safexcel-ofb-sm4",
321303a6cfb9SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
321403a6cfb9SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3215b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
321603a6cfb9SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
321703a6cfb9SPascal van Leeuwen 			.cra_blocksize = 1,
321803a6cfb9SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
321903a6cfb9SPascal van Leeuwen 			.cra_alignmask = 0,
322003a6cfb9SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ofb_cra_init,
322103a6cfb9SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
322203a6cfb9SPascal van Leeuwen 			.cra_module = THIS_MODULE,
322303a6cfb9SPascal van Leeuwen 		},
322403a6cfb9SPascal van Leeuwen 	},
322503a6cfb9SPascal van Leeuwen };
32267468ab22SPascal van Leeuwen 
safexcel_skcipher_sm4_cfb_cra_init(struct crypto_tfm * tfm)32277468ab22SPascal van Leeuwen static int safexcel_skcipher_sm4_cfb_cra_init(struct crypto_tfm *tfm)
32287468ab22SPascal van Leeuwen {
32297468ab22SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
32307468ab22SPascal van Leeuwen 
32317468ab22SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
32327468ab22SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3233098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
32347468ab22SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB;
32357468ab22SPascal van Leeuwen 	return 0;
32367468ab22SPascal van Leeuwen }
32377468ab22SPascal van Leeuwen 
32387468ab22SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cfb_sm4 = {
32397468ab22SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
32407468ab22SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB,
32417468ab22SPascal van Leeuwen 	.alg.skcipher = {
32427468ab22SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
32437468ab22SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
32447468ab22SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
32457468ab22SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
32467468ab22SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
32477468ab22SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
32487468ab22SPascal van Leeuwen 		.base = {
32497468ab22SPascal van Leeuwen 			.cra_name = "cfb(sm4)",
32507468ab22SPascal van Leeuwen 			.cra_driver_name = "safexcel-cfb-sm4",
32517468ab22SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
32527468ab22SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3253b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
32547468ab22SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
32557468ab22SPascal van Leeuwen 			.cra_blocksize = 1,
32567468ab22SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
32577468ab22SPascal van Leeuwen 			.cra_alignmask = 0,
32587468ab22SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_cfb_cra_init,
32597468ab22SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
32607468ab22SPascal van Leeuwen 			.cra_module = THIS_MODULE,
32617468ab22SPascal van Leeuwen 		},
32627468ab22SPascal van Leeuwen 	},
32637468ab22SPascal van Leeuwen };
3264f77e5dc0SPascal van Leeuwen 
safexcel_skcipher_sm4ctr_setkey(struct crypto_skcipher * ctfm,const u8 * key,unsigned int len)3265f77e5dc0SPascal van Leeuwen static int safexcel_skcipher_sm4ctr_setkey(struct crypto_skcipher *ctfm,
3266f77e5dc0SPascal van Leeuwen 					   const u8 *key, unsigned int len)
3267f77e5dc0SPascal van Leeuwen {
3268f77e5dc0SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3269f77e5dc0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3270f77e5dc0SPascal van Leeuwen 
3271f77e5dc0SPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
3272f77e5dc0SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
3273f77e5dc0SPascal van Leeuwen 	/* exclude the nonce here */
3274f77e5dc0SPascal van Leeuwen 	len -= CTR_RFC3686_NONCE_SIZE;
3275f77e5dc0SPascal van Leeuwen 
3276f77e5dc0SPascal van Leeuwen 	return safexcel_skcipher_sm4_setkey(ctfm, key, len);
3277f77e5dc0SPascal van Leeuwen }
3278f77e5dc0SPascal van Leeuwen 
safexcel_skcipher_sm4_ctr_cra_init(struct crypto_tfm * tfm)3279f77e5dc0SPascal van Leeuwen static int safexcel_skcipher_sm4_ctr_cra_init(struct crypto_tfm *tfm)
3280f77e5dc0SPascal van Leeuwen {
3281f77e5dc0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3282f77e5dc0SPascal van Leeuwen 
3283f77e5dc0SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
3284f77e5dc0SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3285098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
3286f77e5dc0SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
3287f77e5dc0SPascal van Leeuwen 	return 0;
3288f77e5dc0SPascal van Leeuwen }
3289f77e5dc0SPascal van Leeuwen 
3290f77e5dc0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ctr_sm4 = {
3291f77e5dc0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
3292f77e5dc0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
3293f77e5dc0SPascal van Leeuwen 	.alg.skcipher = {
3294f77e5dc0SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4ctr_setkey,
3295f77e5dc0SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
3296f77e5dc0SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
3297f77e5dc0SPascal van Leeuwen 		/* Add nonce size */
3298f77e5dc0SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
3299f77e5dc0SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
3300f77e5dc0SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
3301f77e5dc0SPascal van Leeuwen 		.base = {
3302f77e5dc0SPascal van Leeuwen 			.cra_name = "rfc3686(ctr(sm4))",
3303f77e5dc0SPascal van Leeuwen 			.cra_driver_name = "safexcel-ctr-sm4",
3304f77e5dc0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3305f77e5dc0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3306b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3307f77e5dc0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3308f77e5dc0SPascal van Leeuwen 			.cra_blocksize = 1,
3309f77e5dc0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3310f77e5dc0SPascal van Leeuwen 			.cra_alignmask = 0,
3311f77e5dc0SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ctr_cra_init,
3312f77e5dc0SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
3313f77e5dc0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3314f77e5dc0SPascal van Leeuwen 		},
3315f77e5dc0SPascal van Leeuwen 	},
3316f77e5dc0SPascal van Leeuwen };
33171769f704SPascal van Leeuwen 
safexcel_aead_sm4_blk_encrypt(struct aead_request * req)33181769f704SPascal van Leeuwen static int safexcel_aead_sm4_blk_encrypt(struct aead_request *req)
33191769f704SPascal van Leeuwen {
33201769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
33211769f704SPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
33221769f704SPascal van Leeuwen 		return -EINVAL;
33231769f704SPascal van Leeuwen 
33241769f704SPascal van Leeuwen 	return safexcel_queue_req(&req->base, aead_request_ctx(req),
33251769f704SPascal van Leeuwen 				  SAFEXCEL_ENCRYPT);
33261769f704SPascal van Leeuwen }
33271769f704SPascal van Leeuwen 
safexcel_aead_sm4_blk_decrypt(struct aead_request * req)33281769f704SPascal van Leeuwen static int safexcel_aead_sm4_blk_decrypt(struct aead_request *req)
33291769f704SPascal van Leeuwen {
33301769f704SPascal van Leeuwen 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
33311769f704SPascal van Leeuwen 
33321769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
33331769f704SPascal van Leeuwen 	if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1))
33341769f704SPascal van Leeuwen 		return -EINVAL;
33351769f704SPascal van Leeuwen 
33361769f704SPascal van Leeuwen 	return safexcel_queue_req(&req->base, aead_request_ctx(req),
33371769f704SPascal van Leeuwen 				  SAFEXCEL_DECRYPT);
33381769f704SPascal van Leeuwen }
33391769f704SPascal van Leeuwen 
safexcel_aead_sm4cbc_sha1_cra_init(struct crypto_tfm * tfm)33401769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sha1_cra_init(struct crypto_tfm *tfm)
33411769f704SPascal van Leeuwen {
33421769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33431769f704SPascal van Leeuwen 
33441769f704SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
33451769f704SPascal van Leeuwen 	ctx->alg = SAFEXCEL_SM4;
3346098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
33471769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
33481769f704SPascal van Leeuwen 	ctx->state_sz = SHA1_DIGEST_SIZE;
33491769f704SPascal van Leeuwen 	return 0;
33501769f704SPascal van Leeuwen }
33511769f704SPascal van Leeuwen 
33521769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_sm4 = {
33531769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
33541769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1,
33551769f704SPascal van Leeuwen 	.alg.aead = {
33561769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
33571769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_sm4_blk_encrypt,
33581769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_sm4_blk_decrypt,
33591769f704SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
33601769f704SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
33611769f704SPascal van Leeuwen 		.base = {
33621769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(sm4))",
33631769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-sm4",
33641769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
33651769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3366b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
33671769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
33681769f704SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
33691769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
33701769f704SPascal van Leeuwen 			.cra_alignmask = 0,
33711769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4cbc_sha1_cra_init,
33721769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
33731769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
33741769f704SPascal van Leeuwen 		},
33751769f704SPascal van Leeuwen 	},
33761769f704SPascal van Leeuwen };
33771769f704SPascal van Leeuwen 
safexcel_aead_fallback_setkey(struct crypto_aead * ctfm,const u8 * key,unsigned int len)33781769f704SPascal van Leeuwen static int safexcel_aead_fallback_setkey(struct crypto_aead *ctfm,
33791769f704SPascal van Leeuwen 					 const u8 *key, unsigned int len)
33801769f704SPascal van Leeuwen {
33811769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
33821769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33831769f704SPascal van Leeuwen 
33841769f704SPascal van Leeuwen 	/* Keep fallback cipher synchronized */
33851769f704SPascal van Leeuwen 	return crypto_aead_setkey(ctx->fback, (u8 *)key, len) ?:
33861769f704SPascal van Leeuwen 	       safexcel_aead_setkey(ctfm, key, len);
33871769f704SPascal van Leeuwen }
33881769f704SPascal van Leeuwen 
safexcel_aead_fallback_setauthsize(struct crypto_aead * ctfm,unsigned int authsize)33891769f704SPascal van Leeuwen static int safexcel_aead_fallback_setauthsize(struct crypto_aead *ctfm,
33901769f704SPascal van Leeuwen 					      unsigned int authsize)
33911769f704SPascal van Leeuwen {
33921769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
33931769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33941769f704SPascal van Leeuwen 
33951769f704SPascal van Leeuwen 	/* Keep fallback cipher synchronized */
33961769f704SPascal van Leeuwen 	return crypto_aead_setauthsize(ctx->fback, authsize);
33971769f704SPascal van Leeuwen }
33981769f704SPascal van Leeuwen 
safexcel_aead_fallback_crypt(struct aead_request * req,enum safexcel_cipher_direction dir)33991769f704SPascal van Leeuwen static int safexcel_aead_fallback_crypt(struct aead_request *req,
34001769f704SPascal van Leeuwen 					enum safexcel_cipher_direction dir)
34011769f704SPascal van Leeuwen {
34021769f704SPascal van Leeuwen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
34031769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
34041769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34051769f704SPascal van Leeuwen 	struct aead_request *subreq = aead_request_ctx(req);
34061769f704SPascal van Leeuwen 
34071769f704SPascal van Leeuwen 	aead_request_set_tfm(subreq, ctx->fback);
34081769f704SPascal van Leeuwen 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
34091769f704SPascal van Leeuwen 				  req->base.data);
34101769f704SPascal van Leeuwen 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
34111769f704SPascal van Leeuwen 			       req->iv);
34121769f704SPascal van Leeuwen 	aead_request_set_ad(subreq, req->assoclen);
34131769f704SPascal van Leeuwen 
34141769f704SPascal van Leeuwen 	return (dir ==  SAFEXCEL_ENCRYPT) ?
34151769f704SPascal van Leeuwen 		crypto_aead_encrypt(subreq) :
34161769f704SPascal van Leeuwen 		crypto_aead_decrypt(subreq);
34171769f704SPascal van Leeuwen }
34181769f704SPascal van Leeuwen 
safexcel_aead_sm4cbc_sm3_encrypt(struct aead_request * req)34191769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_encrypt(struct aead_request *req)
34201769f704SPascal van Leeuwen {
34211769f704SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
34221769f704SPascal van Leeuwen 
34231769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
34241769f704SPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
34251769f704SPascal van Leeuwen 		return -EINVAL;
34261769f704SPascal van Leeuwen 	else if (req->cryptlen || req->assoclen) /* If input length > 0 only */
34271769f704SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
34281769f704SPascal van Leeuwen 
34291769f704SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
34301769f704SPascal van Leeuwen 	return safexcel_aead_fallback_crypt(req, SAFEXCEL_ENCRYPT);
34311769f704SPascal van Leeuwen }
34321769f704SPascal van Leeuwen 
safexcel_aead_sm4cbc_sm3_decrypt(struct aead_request * req)34331769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_decrypt(struct aead_request *req)
34341769f704SPascal van Leeuwen {
34351769f704SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
34361769f704SPascal van Leeuwen 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
34371769f704SPascal van Leeuwen 
34381769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
34391769f704SPascal van Leeuwen 	if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1))
34401769f704SPascal van Leeuwen 		return -EINVAL;
34411769f704SPascal van Leeuwen 	else if (req->cryptlen > crypto_aead_authsize(tfm) || req->assoclen)
34421769f704SPascal van Leeuwen 		/* If input length > 0 only */
34431769f704SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
34441769f704SPascal van Leeuwen 
34451769f704SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
34461769f704SPascal van Leeuwen 	return safexcel_aead_fallback_crypt(req, SAFEXCEL_DECRYPT);
34471769f704SPascal van Leeuwen }
34481769f704SPascal van Leeuwen 
safexcel_aead_sm4cbc_sm3_cra_init(struct crypto_tfm * tfm)34491769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_cra_init(struct crypto_tfm *tfm)
34501769f704SPascal van Leeuwen {
34511769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34521769f704SPascal van Leeuwen 
34531769f704SPascal van Leeuwen 	safexcel_aead_fallback_cra_init(tfm);
34541769f704SPascal van Leeuwen 	ctx->alg = SAFEXCEL_SM4;
3455098e51e5SPascal van Leeuwen 	ctx->blocksz = SM4_BLOCK_SIZE;
34561769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
34571769f704SPascal van Leeuwen 	ctx->state_sz = SM3_DIGEST_SIZE;
34581769f704SPascal van Leeuwen 	return 0;
34591769f704SPascal van Leeuwen }
34601769f704SPascal van Leeuwen 
34611769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_cbc_sm4 = {
34621769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
34631769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3,
34641769f704SPascal van Leeuwen 	.alg.aead = {
34651769f704SPascal van Leeuwen 		.setkey = safexcel_aead_fallback_setkey,
34661769f704SPascal van Leeuwen 		.setauthsize = safexcel_aead_fallback_setauthsize,
34671769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_sm4cbc_sm3_encrypt,
34681769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_sm4cbc_sm3_decrypt,
34691769f704SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
34701769f704SPascal van Leeuwen 		.maxauthsize = SM3_DIGEST_SIZE,
34711769f704SPascal van Leeuwen 		.base = {
34721769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sm3),cbc(sm4))",
34731769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sm3-cbc-sm4",
34741769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
34751769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3476b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
34771769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
34781769f704SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
34791769f704SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
34801769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
34811769f704SPascal van Leeuwen 			.cra_alignmask = 0,
34821769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4cbc_sm3_cra_init,
34831769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
34841769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
34851769f704SPascal van Leeuwen 		},
34861769f704SPascal van Leeuwen 	},
34871769f704SPascal van Leeuwen };
34881769f704SPascal van Leeuwen 
safexcel_aead_sm4ctr_sha1_cra_init(struct crypto_tfm * tfm)34891769f704SPascal van Leeuwen static int safexcel_aead_sm4ctr_sha1_cra_init(struct crypto_tfm *tfm)
34901769f704SPascal van Leeuwen {
34911769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34921769f704SPascal van Leeuwen 
34931769f704SPascal van Leeuwen 	safexcel_aead_sm4cbc_sha1_cra_init(tfm);
34941769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
34951769f704SPascal van Leeuwen 	return 0;
34961769f704SPascal van Leeuwen }
34971769f704SPascal van Leeuwen 
34981769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_sm4 = {
34991769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
35001769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1,
35011769f704SPascal van Leeuwen 	.alg.aead = {
35021769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
35031769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
35041769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
35051769f704SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
35061769f704SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
35071769f704SPascal van Leeuwen 		.base = {
35081769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),rfc3686(ctr(sm4)))",
35091769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-sm4",
35101769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
35111769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3512b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
35131769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
35141769f704SPascal van Leeuwen 			.cra_blocksize = 1,
35151769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
35161769f704SPascal van Leeuwen 			.cra_alignmask = 0,
35171769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4ctr_sha1_cra_init,
35181769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
35191769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
35201769f704SPascal van Leeuwen 		},
35211769f704SPascal van Leeuwen 	},
35221769f704SPascal van Leeuwen };
35231769f704SPascal van Leeuwen 
safexcel_aead_sm4ctr_sm3_cra_init(struct crypto_tfm * tfm)35241769f704SPascal van Leeuwen static int safexcel_aead_sm4ctr_sm3_cra_init(struct crypto_tfm *tfm)
35251769f704SPascal van Leeuwen {
35261769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
35271769f704SPascal van Leeuwen 
35281769f704SPascal van Leeuwen 	safexcel_aead_sm4cbc_sm3_cra_init(tfm);
35291769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
35301769f704SPascal van Leeuwen 	return 0;
35311769f704SPascal van Leeuwen }
35321769f704SPascal van Leeuwen 
35331769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_ctr_sm4 = {
35341769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
35351769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3,
35361769f704SPascal van Leeuwen 	.alg.aead = {
35371769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
35381769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
35391769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
35401769f704SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
35411769f704SPascal van Leeuwen 		.maxauthsize = SM3_DIGEST_SIZE,
35421769f704SPascal van Leeuwen 		.base = {
35431769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sm3),rfc3686(ctr(sm4)))",
35441769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sm3-ctr-sm4",
35451769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
35461769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3547b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
35481769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
35491769f704SPascal van Leeuwen 			.cra_blocksize = 1,
35501769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
35511769f704SPascal van Leeuwen 			.cra_alignmask = 0,
35521769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4ctr_sm3_cra_init,
35531769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
35541769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
35551769f704SPascal van Leeuwen 		},
35561769f704SPascal van Leeuwen 	},
35571769f704SPascal van Leeuwen };
3558a19052d4SPascal van Leeuwen 
safexcel_rfc4106_gcm_setkey(struct crypto_aead * ctfm,const u8 * key,unsigned int len)3559a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_setkey(struct crypto_aead *ctfm, const u8 *key,
3560a19052d4SPascal van Leeuwen 				       unsigned int len)
3561a19052d4SPascal van Leeuwen {
3562a19052d4SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
3563a19052d4SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3564a19052d4SPascal van Leeuwen 
3565a19052d4SPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
3566a19052d4SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
3567a19052d4SPascal van Leeuwen 
3568a19052d4SPascal van Leeuwen 	len -= CTR_RFC3686_NONCE_SIZE;
3569a19052d4SPascal van Leeuwen 	return safexcel_aead_gcm_setkey(ctfm, key, len);
3570a19052d4SPascal van Leeuwen }
3571a19052d4SPascal van Leeuwen 
safexcel_rfc4106_gcm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)3572a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_setauthsize(struct crypto_aead *tfm,
3573a19052d4SPascal van Leeuwen 					    unsigned int authsize)
3574a19052d4SPascal van Leeuwen {
3575a19052d4SPascal van Leeuwen 	return crypto_rfc4106_check_authsize(authsize);
3576a19052d4SPascal van Leeuwen }
3577a19052d4SPascal van Leeuwen 
safexcel_rfc4106_encrypt(struct aead_request * req)3578a19052d4SPascal van Leeuwen static int safexcel_rfc4106_encrypt(struct aead_request *req)
3579a19052d4SPascal van Leeuwen {
3580a19052d4SPascal van Leeuwen 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
3581a19052d4SPascal van Leeuwen 	       safexcel_aead_encrypt(req);
3582a19052d4SPascal van Leeuwen }
3583a19052d4SPascal van Leeuwen 
safexcel_rfc4106_decrypt(struct aead_request * req)3584a19052d4SPascal van Leeuwen static int safexcel_rfc4106_decrypt(struct aead_request *req)
3585a19052d4SPascal van Leeuwen {
3586a19052d4SPascal van Leeuwen 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
3587a19052d4SPascal van Leeuwen 	       safexcel_aead_decrypt(req);
3588a19052d4SPascal van Leeuwen }
3589a19052d4SPascal van Leeuwen 
safexcel_rfc4106_gcm_cra_init(struct crypto_tfm * tfm)3590a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_cra_init(struct crypto_tfm *tfm)
3591a19052d4SPascal van Leeuwen {
3592a19052d4SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3593a19052d4SPascal van Leeuwen 	int ret;
3594a19052d4SPascal van Leeuwen 
3595a19052d4SPascal van Leeuwen 	ret = safexcel_aead_gcm_cra_init(tfm);
3596a19052d4SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3597098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3598a19052d4SPascal van Leeuwen 	return ret;
3599a19052d4SPascal van Leeuwen }
3600a19052d4SPascal van Leeuwen 
3601a19052d4SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4106_gcm = {
3602a19052d4SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3603a19052d4SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
3604a19052d4SPascal van Leeuwen 	.alg.aead = {
3605a19052d4SPascal van Leeuwen 		.setkey = safexcel_rfc4106_gcm_setkey,
3606a19052d4SPascal van Leeuwen 		.setauthsize = safexcel_rfc4106_gcm_setauthsize,
3607a19052d4SPascal van Leeuwen 		.encrypt = safexcel_rfc4106_encrypt,
3608a19052d4SPascal van Leeuwen 		.decrypt = safexcel_rfc4106_decrypt,
3609a19052d4SPascal van Leeuwen 		.ivsize = GCM_RFC4106_IV_SIZE,
3610a19052d4SPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
3611a19052d4SPascal van Leeuwen 		.base = {
3612a19052d4SPascal van Leeuwen 			.cra_name = "rfc4106(gcm(aes))",
3613a19052d4SPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4106-gcm-aes",
3614a19052d4SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3615a19052d4SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3616b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3617a19052d4SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3618a19052d4SPascal van Leeuwen 			.cra_blocksize = 1,
3619a19052d4SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3620a19052d4SPascal van Leeuwen 			.cra_alignmask = 0,
3621a19052d4SPascal van Leeuwen 			.cra_init = safexcel_rfc4106_gcm_cra_init,
3622a19052d4SPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
3623a19052d4SPascal van Leeuwen 		},
3624a19052d4SPascal van Leeuwen 	},
3625a19052d4SPascal van Leeuwen };
362692c60cefSPascal van Leeuwen 
safexcel_rfc4543_gcm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)362792c60cefSPascal van Leeuwen static int safexcel_rfc4543_gcm_setauthsize(struct crypto_aead *tfm,
362892c60cefSPascal van Leeuwen 					    unsigned int authsize)
362992c60cefSPascal van Leeuwen {
363092c60cefSPascal van Leeuwen 	if (authsize != GHASH_DIGEST_SIZE)
363192c60cefSPascal van Leeuwen 		return -EINVAL;
363292c60cefSPascal van Leeuwen 
363392c60cefSPascal van Leeuwen 	return 0;
363492c60cefSPascal van Leeuwen }
363592c60cefSPascal van Leeuwen 
safexcel_rfc4543_gcm_cra_init(struct crypto_tfm * tfm)363692c60cefSPascal van Leeuwen static int safexcel_rfc4543_gcm_cra_init(struct crypto_tfm *tfm)
363792c60cefSPascal van Leeuwen {
363892c60cefSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
363992c60cefSPascal van Leeuwen 	int ret;
364092c60cefSPascal van Leeuwen 
364192c60cefSPascal van Leeuwen 	ret = safexcel_aead_gcm_cra_init(tfm);
364292c60cefSPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP_GMAC;
364392c60cefSPascal van Leeuwen 	return ret;
364492c60cefSPascal van Leeuwen }
364592c60cefSPascal van Leeuwen 
364692c60cefSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4543_gcm = {
364792c60cefSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
364892c60cefSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
364992c60cefSPascal van Leeuwen 	.alg.aead = {
365092c60cefSPascal van Leeuwen 		.setkey = safexcel_rfc4106_gcm_setkey,
365192c60cefSPascal van Leeuwen 		.setauthsize = safexcel_rfc4543_gcm_setauthsize,
365292c60cefSPascal van Leeuwen 		.encrypt = safexcel_rfc4106_encrypt,
365392c60cefSPascal van Leeuwen 		.decrypt = safexcel_rfc4106_decrypt,
365492c60cefSPascal van Leeuwen 		.ivsize = GCM_RFC4543_IV_SIZE,
365592c60cefSPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
365692c60cefSPascal van Leeuwen 		.base = {
365792c60cefSPascal van Leeuwen 			.cra_name = "rfc4543(gcm(aes))",
365892c60cefSPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4543-gcm-aes",
365992c60cefSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
366092c60cefSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3661b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
366292c60cefSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
366392c60cefSPascal van Leeuwen 			.cra_blocksize = 1,
366492c60cefSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
366592c60cefSPascal van Leeuwen 			.cra_alignmask = 0,
366692c60cefSPascal van Leeuwen 			.cra_init = safexcel_rfc4543_gcm_cra_init,
366792c60cefSPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
366892c60cefSPascal van Leeuwen 		},
366992c60cefSPascal van Leeuwen 	},
367092c60cefSPascal van Leeuwen };
3671a9a89624SPascal van Leeuwen 
safexcel_rfc4309_ccm_setkey(struct crypto_aead * ctfm,const u8 * key,unsigned int len)3672a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_setkey(struct crypto_aead *ctfm, const u8 *key,
3673a9a89624SPascal van Leeuwen 				       unsigned int len)
3674a9a89624SPascal van Leeuwen {
3675a9a89624SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
3676a9a89624SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3677a9a89624SPascal van Leeuwen 
3678a9a89624SPascal van Leeuwen 	/* First byte of the nonce = L = always 3 for RFC4309 (4 byte ctr) */
3679a9a89624SPascal van Leeuwen 	*(u8 *)&ctx->nonce = EIP197_AEAD_IPSEC_COUNTER_SIZE - 1;
3680a9a89624SPascal van Leeuwen 	/* last 3 bytes of key are the nonce! */
3681a9a89624SPascal van Leeuwen 	memcpy((u8 *)&ctx->nonce + 1, key + len -
3682a9a89624SPascal van Leeuwen 	       EIP197_AEAD_IPSEC_CCM_NONCE_SIZE,
3683a9a89624SPascal van Leeuwen 	       EIP197_AEAD_IPSEC_CCM_NONCE_SIZE);
3684a9a89624SPascal van Leeuwen 
3685a9a89624SPascal van Leeuwen 	len -= EIP197_AEAD_IPSEC_CCM_NONCE_SIZE;
3686a9a89624SPascal van Leeuwen 	return safexcel_aead_ccm_setkey(ctfm, key, len);
3687a9a89624SPascal van Leeuwen }
3688a9a89624SPascal van Leeuwen 
safexcel_rfc4309_ccm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)3689a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_setauthsize(struct crypto_aead *tfm,
3690a9a89624SPascal van Leeuwen 					    unsigned int authsize)
3691a9a89624SPascal van Leeuwen {
3692a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3693a9a89624SPascal van Leeuwen 	switch (authsize) {
3694a9a89624SPascal van Leeuwen 	case 8:
3695a9a89624SPascal van Leeuwen 	case 12:
3696a9a89624SPascal van Leeuwen 	case 16:
3697a9a89624SPascal van Leeuwen 		break;
3698a9a89624SPascal van Leeuwen 	default:
3699a9a89624SPascal van Leeuwen 		return -EINVAL;
3700a9a89624SPascal van Leeuwen 	}
3701a9a89624SPascal van Leeuwen 
3702a9a89624SPascal van Leeuwen 	return 0;
3703a9a89624SPascal van Leeuwen }
3704a9a89624SPascal van Leeuwen 
safexcel_rfc4309_ccm_encrypt(struct aead_request * req)3705a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_encrypt(struct aead_request *req)
3706a9a89624SPascal van Leeuwen {
3707a9a89624SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
3708a9a89624SPascal van Leeuwen 
3709a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3710a9a89624SPascal van Leeuwen 	if (req->assoclen != 16 && req->assoclen != 20)
3711a9a89624SPascal van Leeuwen 		return -EINVAL;
3712a9a89624SPascal van Leeuwen 
3713a9a89624SPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
3714a9a89624SPascal van Leeuwen }
3715a9a89624SPascal van Leeuwen 
safexcel_rfc4309_ccm_decrypt(struct aead_request * req)3716a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_decrypt(struct aead_request *req)
3717a9a89624SPascal van Leeuwen {
3718a9a89624SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
3719a9a89624SPascal van Leeuwen 
3720a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3721a9a89624SPascal van Leeuwen 	if (req->assoclen != 16 && req->assoclen != 20)
3722a9a89624SPascal van Leeuwen 		return -EINVAL;
3723a9a89624SPascal van Leeuwen 
3724a9a89624SPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
3725a9a89624SPascal van Leeuwen }
3726a9a89624SPascal van Leeuwen 
safexcel_rfc4309_ccm_cra_init(struct crypto_tfm * tfm)3727a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_cra_init(struct crypto_tfm *tfm)
3728a9a89624SPascal van Leeuwen {
3729a9a89624SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3730a9a89624SPascal van Leeuwen 	int ret;
3731a9a89624SPascal van Leeuwen 
3732a9a89624SPascal van Leeuwen 	ret = safexcel_aead_ccm_cra_init(tfm);
3733a9a89624SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3734098e51e5SPascal van Leeuwen 	ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE;
3735a9a89624SPascal van Leeuwen 	return ret;
3736a9a89624SPascal van Leeuwen }
3737a9a89624SPascal van Leeuwen 
3738a9a89624SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4309_ccm = {
3739a9a89624SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3740a9a89624SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL,
3741a9a89624SPascal van Leeuwen 	.alg.aead = {
3742a9a89624SPascal van Leeuwen 		.setkey = safexcel_rfc4309_ccm_setkey,
3743a9a89624SPascal van Leeuwen 		.setauthsize = safexcel_rfc4309_ccm_setauthsize,
3744a9a89624SPascal van Leeuwen 		.encrypt = safexcel_rfc4309_ccm_encrypt,
3745a9a89624SPascal van Leeuwen 		.decrypt = safexcel_rfc4309_ccm_decrypt,
3746a9a89624SPascal van Leeuwen 		.ivsize = EIP197_AEAD_IPSEC_IV_SIZE,
3747a9a89624SPascal van Leeuwen 		.maxauthsize = AES_BLOCK_SIZE,
3748a9a89624SPascal van Leeuwen 		.base = {
3749a9a89624SPascal van Leeuwen 			.cra_name = "rfc4309(ccm(aes))",
3750a9a89624SPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4309-ccm-aes",
3751a9a89624SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3752a9a89624SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3753b8aa7dc5SMikulas Patocka 				     CRYPTO_ALG_ALLOCATES_MEMORY |
3754a9a89624SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3755a9a89624SPascal van Leeuwen 			.cra_blocksize = 1,
3756a9a89624SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3757a9a89624SPascal van Leeuwen 			.cra_alignmask = 0,
3758a9a89624SPascal van Leeuwen 			.cra_init = safexcel_rfc4309_ccm_cra_init,
3759a9a89624SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
3760a9a89624SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3761a9a89624SPascal van Leeuwen 		},
3762a9a89624SPascal van Leeuwen 	},
3763a9a89624SPascal van Leeuwen };
3764