1301422e3SAntoine Tenart // SPDX-License-Identifier: GPL-2.0
21b44c5a6SAntoine Ténart /*
31b44c5a6SAntoine Ténart  * Copyright (C) 2017 Marvell
41b44c5a6SAntoine Ténart  *
51b44c5a6SAntoine Ténart  * Antoine Tenart <antoine.tenart@free-electrons.com>
61b44c5a6SAntoine Ténart  */
71b44c5a6SAntoine Ténart 
84a593fb3SPascal van Leeuwen #include <asm/unaligned.h>
91b44c5a6SAntoine Ténart #include <linux/device.h>
101b44c5a6SAntoine Ténart #include <linux/dma-mapping.h>
111b44c5a6SAntoine Ténart #include <linux/dmapool.h>
12f6beaea3SAntoine Tenart #include <crypto/aead.h>
131b44c5a6SAntoine Ténart #include <crypto/aes.h>
14f6beaea3SAntoine Tenart #include <crypto/authenc.h>
154a593fb3SPascal van Leeuwen #include <crypto/chacha.h>
16f26882a3SPascal van Leeuwen #include <crypto/ctr.h>
1704007b0eSArd Biesheuvel #include <crypto/internal/des.h>
183e450886SPascal van Leeuwen #include <crypto/gcm.h>
193e450886SPascal van Leeuwen #include <crypto/ghash.h>
20a6061921SPascal van Leeuwen #include <crypto/poly1305.h>
21f6beaea3SAntoine Tenart #include <crypto/sha.h>
221769f704SPascal van Leeuwen #include <crypto/sm3.h>
23fcca797dSPascal van Leeuwen #include <crypto/sm4.h>
24c7da38a7SPascal van Leeuwen #include <crypto/xts.h>
251b44c5a6SAntoine Ténart #include <crypto/skcipher.h>
26f6beaea3SAntoine Tenart #include <crypto/internal/aead.h>
271eb7b403SOfer Heifetz #include <crypto/internal/skcipher.h>
281b44c5a6SAntoine Ténart 
291b44c5a6SAntoine Ténart #include "safexcel.h"
301b44c5a6SAntoine Ténart 
311b44c5a6SAntoine Ténart enum safexcel_cipher_direction {
321b44c5a6SAntoine Ténart 	SAFEXCEL_ENCRYPT,
331b44c5a6SAntoine Ténart 	SAFEXCEL_DECRYPT,
341b44c5a6SAntoine Ténart };
351b44c5a6SAntoine Ténart 
36a7dea8c0SOfer Heifetz enum safexcel_cipher_alg {
37a7dea8c0SOfer Heifetz 	SAFEXCEL_DES,
3862469879SOfer Heifetz 	SAFEXCEL_3DES,
39a7dea8c0SOfer Heifetz 	SAFEXCEL_AES,
404a593fb3SPascal van Leeuwen 	SAFEXCEL_CHACHA20,
41fcca797dSPascal van Leeuwen 	SAFEXCEL_SM4,
42a7dea8c0SOfer Heifetz };
43a7dea8c0SOfer Heifetz 
441b44c5a6SAntoine Ténart struct safexcel_cipher_ctx {
451b44c5a6SAntoine Ténart 	struct safexcel_context base;
461b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv;
471b44c5a6SAntoine Ténart 
481b44c5a6SAntoine Ténart 	u32 mode;
49a7dea8c0SOfer Heifetz 	enum safexcel_cipher_alg alg;
5092c60cefSPascal van Leeuwen 	char aead; /* !=0=AEAD, 2=IPSec ESP AEAD, 3=IPsec ESP GMAC */
51a6061921SPascal van Leeuwen 	char xcm;  /* 0=authenc, 1=GCM, 2 reserved for CCM */
521b44c5a6SAntoine Ténart 
53c7da38a7SPascal van Leeuwen 	__le32 key[16];
5454f9e8faSPascal van Leeuwen 	u32 nonce;
55c7da38a7SPascal van Leeuwen 	unsigned int key_len, xts;
56f6beaea3SAntoine Tenart 
57f6beaea3SAntoine Tenart 	/* All the below is AEAD specific */
58a7dea8c0SOfer Heifetz 	u32 hash_alg;
59f6beaea3SAntoine Tenart 	u32 state_sz;
6013a1bb93SPascal van Leeuwen 	__be32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)];
6113a1bb93SPascal van Leeuwen 	__be32 opad[SHA512_DIGEST_SIZE / sizeof(u32)];
623e450886SPascal van Leeuwen 
633e450886SPascal van Leeuwen 	struct crypto_cipher *hkaes;
64a6061921SPascal van Leeuwen 	struct crypto_aead *fback;
651b44c5a6SAntoine Ténart };
661b44c5a6SAntoine Ténart 
671eb7b403SOfer Heifetz struct safexcel_cipher_req {
68847ccfc5SOfer Heifetz 	enum safexcel_cipher_direction direction;
6989332590SAntoine Tenart 	/* Number of result descriptors associated to the request */
7089332590SAntoine Tenart 	unsigned int rdescs;
711eb7b403SOfer Heifetz 	bool needs_inv;
7219b347b3SPascal van Leeuwen 	int  nr_src, nr_dst;
731eb7b403SOfer Heifetz };
741eb7b403SOfer Heifetz 
750e17e362SPascal van Leeuwen static void safexcel_cipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
760e17e362SPascal van Leeuwen 				  struct safexcel_command_desc *cdesc)
771b44c5a6SAntoine Ténart {
7854f9e8faSPascal van Leeuwen 	u32 block_sz = 0;
791b44c5a6SAntoine Ténart 
80a19052d4SPascal van Leeuwen 	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD ||
8192c60cefSPascal van Leeuwen 	    ctx->aead & EIP197_AEAD_TYPE_IPSEC_ESP) { /* _ESP and _ESP_GMAC */
82493e289cSPascal van Leeuwen 		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
83493e289cSPascal van Leeuwen 
84493e289cSPascal van Leeuwen 		/* 32 bit nonce */
85493e289cSPascal van Leeuwen 		cdesc->control_data.token[0] = ctx->nonce;
86493e289cSPascal van Leeuwen 		/* 64 bit IV part */
87493e289cSPascal van Leeuwen 		memcpy(&cdesc->control_data.token[1], iv, 8);
88a19052d4SPascal van Leeuwen 
89a9a89624SPascal van Leeuwen 		if (ctx->alg == SAFEXCEL_CHACHA20 ||
90a9a89624SPascal van Leeuwen 		    ctx->xcm == EIP197_XCM_MODE_CCM) {
91a19052d4SPascal van Leeuwen 			/* 32 bit counter, starting at 0 */
92a19052d4SPascal van Leeuwen 			cdesc->control_data.token[3] = 0;
93a19052d4SPascal van Leeuwen 		} else {
94493e289cSPascal van Leeuwen 			/* 32 bit counter, start at 1 (big endian!) */
9513a1bb93SPascal van Leeuwen 			cdesc->control_data.token[3] =
9613a1bb93SPascal van Leeuwen 				(__force u32)cpu_to_be32(1);
97a19052d4SPascal van Leeuwen 		}
98a19052d4SPascal van Leeuwen 
99a19052d4SPascal van Leeuwen 		return;
100a19052d4SPascal van Leeuwen 	} else if (ctx->xcm == EIP197_XCM_MODE_GCM ||
101a19052d4SPascal van Leeuwen 		   (ctx->aead && ctx->alg == SAFEXCEL_CHACHA20)) {
102a19052d4SPascal van Leeuwen 		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
103a19052d4SPascal van Leeuwen 
104a19052d4SPascal van Leeuwen 		/* 96 bit IV part */
105a19052d4SPascal van Leeuwen 		memcpy(&cdesc->control_data.token[0], iv, 12);
106a19052d4SPascal van Leeuwen 
107a19052d4SPascal van Leeuwen 		if (ctx->alg == SAFEXCEL_CHACHA20) {
108a19052d4SPascal van Leeuwen 			/* 32 bit counter, starting at 0 */
109a19052d4SPascal van Leeuwen 			cdesc->control_data.token[3] = 0;
110a19052d4SPascal van Leeuwen 		} else {
111a19052d4SPascal van Leeuwen 			/* 32 bit counter, start at 1 (big endian!) */
11213a1bb93SPascal van Leeuwen 			*(__be32 *)&cdesc->control_data.token[3] =
11313a1bb93SPascal van Leeuwen 				cpu_to_be32(1);
114a19052d4SPascal van Leeuwen 		}
115493e289cSPascal van Leeuwen 
116493e289cSPascal van Leeuwen 		return;
1174a593fb3SPascal van Leeuwen 	} else if (ctx->alg == SAFEXCEL_CHACHA20) {
1184a593fb3SPascal van Leeuwen 		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
1194a593fb3SPascal van Leeuwen 
1204a593fb3SPascal van Leeuwen 		/* 96 bit nonce part */
1214a593fb3SPascal van Leeuwen 		memcpy(&cdesc->control_data.token[0], &iv[4], 12);
1224a593fb3SPascal van Leeuwen 		/* 32 bit counter */
1234a593fb3SPascal van Leeuwen 		cdesc->control_data.token[3] = *(u32 *)iv;
1243e450886SPascal van Leeuwen 
1253e450886SPascal van Leeuwen 		return;
1264eb76fafSPascal van Leeuwen 	} else if (ctx->xcm == EIP197_XCM_MODE_CCM) {
1274eb76fafSPascal van Leeuwen 		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
1284eb76fafSPascal van Leeuwen 
1294eb76fafSPascal van Leeuwen 		/* Variable length IV part */
1304eb76fafSPascal van Leeuwen 		memcpy(&cdesc->control_data.token[0], iv, 15 - iv[0]);
1314eb76fafSPascal van Leeuwen 		/* Start variable length counter at 0 */
1324eb76fafSPascal van Leeuwen 		memset((u8 *)&cdesc->control_data.token[0] + 15 - iv[0],
1334eb76fafSPascal van Leeuwen 		       0, iv[0] + 1);
1344eb76fafSPascal van Leeuwen 
1354eb76fafSPascal van Leeuwen 		return;
136493e289cSPascal van Leeuwen 	}
137493e289cSPascal van Leeuwen 
13854f9e8faSPascal van Leeuwen 	if (ctx->mode != CONTEXT_CONTROL_CRYPTO_MODE_ECB) {
139a7dea8c0SOfer Heifetz 		switch (ctx->alg) {
140a7dea8c0SOfer Heifetz 		case SAFEXCEL_DES:
14157660b11SAntoine Tenart 			block_sz = DES_BLOCK_SIZE;
142a7dea8c0SOfer Heifetz 			cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD;
143a7dea8c0SOfer Heifetz 			break;
14462469879SOfer Heifetz 		case SAFEXCEL_3DES:
14557660b11SAntoine Tenart 			block_sz = DES3_EDE_BLOCK_SIZE;
14662469879SOfer Heifetz 			cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD;
14762469879SOfer Heifetz 			break;
148fcca797dSPascal van Leeuwen 		case SAFEXCEL_SM4:
149fcca797dSPascal van Leeuwen 			block_sz = SM4_BLOCK_SIZE;
150fcca797dSPascal van Leeuwen 			cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
151fcca797dSPascal van Leeuwen 			break;
152a7dea8c0SOfer Heifetz 		case SAFEXCEL_AES:
15357660b11SAntoine Tenart 			block_sz = AES_BLOCK_SIZE;
1541b44c5a6SAntoine Ténart 			cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
155a7dea8c0SOfer Heifetz 			break;
1564a593fb3SPascal van Leeuwen 		default:
1574a593fb3SPascal van Leeuwen 			break;
158a7dea8c0SOfer Heifetz 		}
15957660b11SAntoine Tenart 		memcpy(cdesc->control_data.token, iv, block_sz);
1601b44c5a6SAntoine Ténart 	}
16154f9e8faSPascal van Leeuwen }
1620e17e362SPascal van Leeuwen 
1630e17e362SPascal van Leeuwen static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
1640e17e362SPascal van Leeuwen 				    struct safexcel_command_desc *cdesc,
1650e17e362SPascal van Leeuwen 				    u32 length)
1660e17e362SPascal van Leeuwen {
1670e17e362SPascal van Leeuwen 	struct safexcel_token *token;
1680e17e362SPascal van Leeuwen 
1690e17e362SPascal van Leeuwen 	safexcel_cipher_token(ctx, iv, cdesc);
1701b44c5a6SAntoine Ténart 
17154f9e8faSPascal van Leeuwen 	/* skip over worst case IV of 4 dwords, no need to be exact */
17254f9e8faSPascal van Leeuwen 	token = (struct safexcel_token *)(cdesc->control_data.token + 4);
1731b44c5a6SAntoine Ténart 
1741b44c5a6SAntoine Ténart 	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
1751b44c5a6SAntoine Ténart 	token[0].packet_length = length;
17615f64ee0SAntoine Tenart 	token[0].stat = EIP197_TOKEN_STAT_LAST_PACKET |
17715f64ee0SAntoine Tenart 			EIP197_TOKEN_STAT_LAST_HASH;
1781b44c5a6SAntoine Ténart 	token[0].instructions = EIP197_TOKEN_INS_LAST |
179a74d850fSPascal van Leeuwen 				EIP197_TOKEN_INS_TYPE_CRYPTO |
1801b44c5a6SAntoine Ténart 				EIP197_TOKEN_INS_TYPE_OUTPUT;
1811b44c5a6SAntoine Ténart }
1821b44c5a6SAntoine Ténart 
183f6beaea3SAntoine Tenart static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
184f6beaea3SAntoine Tenart 				struct safexcel_command_desc *cdesc,
185f6beaea3SAntoine Tenart 				enum safexcel_cipher_direction direction,
186f6beaea3SAntoine Tenart 				u32 cryptlen, u32 assoclen, u32 digestsize)
187f6beaea3SAntoine Tenart {
188f6beaea3SAntoine Tenart 	struct safexcel_token *token;
189f6beaea3SAntoine Tenart 
1900e17e362SPascal van Leeuwen 	safexcel_cipher_token(ctx, iv, cdesc);
191f6beaea3SAntoine Tenart 
192f6beaea3SAntoine Tenart 	if (direction == SAFEXCEL_ENCRYPT) {
19354f9e8faSPascal van Leeuwen 		/* align end of instruction sequence to end of token */
19454f9e8faSPascal van Leeuwen 		token = (struct safexcel_token *)(cdesc->control_data.token +
195a9a89624SPascal van Leeuwen 			 EIP197_MAX_TOKENS - 14);
19654f9e8faSPascal van Leeuwen 
197a9a89624SPascal van Leeuwen 		token[13].opcode = EIP197_TOKEN_OPCODE_INSERT;
198a9a89624SPascal van Leeuwen 		token[13].packet_length = digestsize;
199a9a89624SPascal van Leeuwen 		token[13].stat = EIP197_TOKEN_STAT_LAST_HASH |
200f6beaea3SAntoine Tenart 				 EIP197_TOKEN_STAT_LAST_PACKET;
201a9a89624SPascal van Leeuwen 		token[13].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
202f6beaea3SAntoine Tenart 					 EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
203f6beaea3SAntoine Tenart 	} else {
204d2d9e6fdSPascal van Leeuwen 		cryptlen -= digestsize;
205d2d9e6fdSPascal van Leeuwen 
20654f9e8faSPascal van Leeuwen 		/* align end of instruction sequence to end of token */
20754f9e8faSPascal van Leeuwen 		token = (struct safexcel_token *)(cdesc->control_data.token +
208a9a89624SPascal van Leeuwen 			 EIP197_MAX_TOKENS - 15);
20954f9e8faSPascal van Leeuwen 
210a9a89624SPascal van Leeuwen 		token[13].opcode = EIP197_TOKEN_OPCODE_RETRIEVE;
211a9a89624SPascal van Leeuwen 		token[13].packet_length = digestsize;
2124eb76fafSPascal van Leeuwen 		token[13].stat = EIP197_TOKEN_STAT_LAST_HASH |
213f6beaea3SAntoine Tenart 				 EIP197_TOKEN_STAT_LAST_PACKET;
214a9a89624SPascal van Leeuwen 		token[13].instructions = EIP197_TOKEN_INS_INSERT_HASH_DIGEST;
215a9a89624SPascal van Leeuwen 
216a9a89624SPascal van Leeuwen 		token[14].opcode = EIP197_TOKEN_OPCODE_VERIFY;
217a9a89624SPascal van Leeuwen 		token[14].packet_length = digestsize |
218a9a89624SPascal van Leeuwen 					  EIP197_TOKEN_HASH_RESULT_VERIFY;
219a9a89624SPascal van Leeuwen 		token[14].stat = EIP197_TOKEN_STAT_LAST_HASH |
220a9a89624SPascal van Leeuwen 				 EIP197_TOKEN_STAT_LAST_PACKET;
221a9a89624SPascal van Leeuwen 		token[14].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT;
222f6beaea3SAntoine Tenart 	}
22354f9e8faSPascal van Leeuwen 
224a6061921SPascal van Leeuwen 	if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
22592c60cefSPascal van Leeuwen 		/* For ESP mode (and not GMAC), skip over the IV */
226a9a89624SPascal van Leeuwen 		token[8].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
227a9a89624SPascal van Leeuwen 		token[8].packet_length = EIP197_AEAD_IPSEC_IV_SIZE;
228a6061921SPascal van Leeuwen 
229a6061921SPascal van Leeuwen 		assoclen -= EIP197_AEAD_IPSEC_IV_SIZE;
230a6061921SPascal van Leeuwen 	}
231a6061921SPascal van Leeuwen 
2324eb76fafSPascal van Leeuwen 	token[6].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
2334eb76fafSPascal van Leeuwen 	token[6].packet_length = assoclen;
234a6061921SPascal van Leeuwen 	token[6].instructions = EIP197_TOKEN_INS_LAST |
235a6061921SPascal van Leeuwen 				EIP197_TOKEN_INS_TYPE_HASH;
23654f9e8faSPascal van Leeuwen 
237a6061921SPascal van Leeuwen 	if (likely(cryptlen || ctx->alg == SAFEXCEL_CHACHA20)) {
238a9a89624SPascal van Leeuwen 		token[11].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
239a9a89624SPascal van Leeuwen 		token[11].packet_length = cryptlen;
240a9a89624SPascal van Leeuwen 		token[11].stat = EIP197_TOKEN_STAT_LAST_HASH;
24192c60cefSPascal van Leeuwen 		if (unlikely(ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP_GMAC)) {
24292c60cefSPascal van Leeuwen 			token[6].instructions = EIP197_TOKEN_INS_TYPE_HASH;
24392c60cefSPascal van Leeuwen 			/* Do not send to crypt engine in case of GMAC */
244a9a89624SPascal van Leeuwen 			token[11].instructions = EIP197_TOKEN_INS_LAST |
24592c60cefSPascal van Leeuwen 						 EIP197_TOKEN_INS_TYPE_HASH |
24692c60cefSPascal van Leeuwen 						 EIP197_TOKEN_INS_TYPE_OUTPUT;
24792c60cefSPascal van Leeuwen 		} else {
248a9a89624SPascal van Leeuwen 			token[11].instructions = EIP197_TOKEN_INS_LAST |
24954f9e8faSPascal van Leeuwen 						 EIP197_TOKEN_INS_TYPE_CRYPTO |
25054f9e8faSPascal van Leeuwen 						 EIP197_TOKEN_INS_TYPE_HASH |
25154f9e8faSPascal van Leeuwen 						 EIP197_TOKEN_INS_TYPE_OUTPUT;
25292c60cefSPascal van Leeuwen 		}
2534eb76fafSPascal van Leeuwen 	} else if (ctx->xcm != EIP197_XCM_MODE_CCM) {
2544eb76fafSPascal van Leeuwen 		token[6].stat = EIP197_TOKEN_STAT_LAST_HASH;
2550e17e362SPascal van Leeuwen 	}
2563e450886SPascal van Leeuwen 
2574eb76fafSPascal van Leeuwen 	if (!ctx->xcm)
2584eb76fafSPascal van Leeuwen 		return;
2593e450886SPascal van Leeuwen 
260a9a89624SPascal van Leeuwen 	token[9].opcode = EIP197_TOKEN_OPCODE_INSERT_REMRES;
261a9a89624SPascal van Leeuwen 	token[9].packet_length = 0;
262a9a89624SPascal van Leeuwen 	token[9].instructions = AES_BLOCK_SIZE;
2633e450886SPascal van Leeuwen 
264a9a89624SPascal van Leeuwen 	token[10].opcode = EIP197_TOKEN_OPCODE_INSERT;
265a9a89624SPascal van Leeuwen 	token[10].packet_length = AES_BLOCK_SIZE;
266a9a89624SPascal van Leeuwen 	token[10].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT |
2673e450886SPascal van Leeuwen 				 EIP197_TOKEN_INS_TYPE_CRYPTO;
2684eb76fafSPascal van Leeuwen 
269a6061921SPascal van Leeuwen 	if (ctx->xcm != EIP197_XCM_MODE_GCM) {
270a9a89624SPascal van Leeuwen 		u8 *final_iv = (u8 *)cdesc->control_data.token;
2714eb76fafSPascal van Leeuwen 		u8 *cbcmaciv = (u8 *)&token[1];
27213a1bb93SPascal van Leeuwen 		__le32 *aadlen = (__le32 *)&token[5];
2734eb76fafSPascal van Leeuwen 
2744eb76fafSPascal van Leeuwen 		/* Construct IV block B0 for the CBC-MAC */
2754eb76fafSPascal van Leeuwen 		token[0].opcode = EIP197_TOKEN_OPCODE_INSERT;
2764eb76fafSPascal van Leeuwen 		token[0].packet_length = AES_BLOCK_SIZE +
2774eb76fafSPascal van Leeuwen 					 ((assoclen > 0) << 1);
2784eb76fafSPascal van Leeuwen 		token[0].instructions = EIP197_TOKEN_INS_ORIGIN_TOKEN |
2794eb76fafSPascal van Leeuwen 					EIP197_TOKEN_INS_TYPE_HASH;
2804eb76fafSPascal van Leeuwen 		/* Variable length IV part */
281a9a89624SPascal van Leeuwen 		memcpy(cbcmaciv, final_iv, 15 - final_iv[0]);
2824eb76fafSPascal van Leeuwen 		/* fixup flags byte */
2834eb76fafSPascal van Leeuwen 		cbcmaciv[0] |= ((assoclen > 0) << 6) | ((digestsize - 2) << 2);
2844eb76fafSPascal van Leeuwen 		/* Clear upper bytes of variable message length to 0 */
285a9a89624SPascal van Leeuwen 		memset(cbcmaciv + 15 - final_iv[0], 0, final_iv[0] - 1);
2864eb76fafSPascal van Leeuwen 		/* insert lower 2 bytes of message length */
2874eb76fafSPascal van Leeuwen 		cbcmaciv[14] = cryptlen >> 8;
2884eb76fafSPascal van Leeuwen 		cbcmaciv[15] = cryptlen & 255;
2894eb76fafSPascal van Leeuwen 
2904eb76fafSPascal van Leeuwen 		if (assoclen) {
29113a1bb93SPascal van Leeuwen 			*aadlen = cpu_to_le32((assoclen >> 8) |
29213a1bb93SPascal van Leeuwen 					      ((assoclen & 0xff) << 8));
2934eb76fafSPascal van Leeuwen 			assoclen += 2;
2944eb76fafSPascal van Leeuwen 		}
2954eb76fafSPascal van Leeuwen 
2964eb76fafSPascal van Leeuwen 		token[6].instructions = EIP197_TOKEN_INS_TYPE_HASH;
2974eb76fafSPascal van Leeuwen 
2984eb76fafSPascal van Leeuwen 		/* Align AAD data towards hash engine */
2994eb76fafSPascal van Leeuwen 		token[7].opcode = EIP197_TOKEN_OPCODE_INSERT;
3004eb76fafSPascal van Leeuwen 		assoclen &= 15;
3014eb76fafSPascal van Leeuwen 		token[7].packet_length = assoclen ? 16 - assoclen : 0;
3024eb76fafSPascal van Leeuwen 
3034eb76fafSPascal van Leeuwen 		if (likely(cryptlen)) {
3044eb76fafSPascal van Leeuwen 			token[7].instructions = EIP197_TOKEN_INS_TYPE_HASH;
3054eb76fafSPascal van Leeuwen 
3064eb76fafSPascal van Leeuwen 			/* Align crypto data towards hash engine */
307a9a89624SPascal van Leeuwen 			token[11].stat = 0;
3084eb76fafSPascal van Leeuwen 
309a9a89624SPascal van Leeuwen 			token[12].opcode = EIP197_TOKEN_OPCODE_INSERT;
3104eb76fafSPascal van Leeuwen 			cryptlen &= 15;
311a9a89624SPascal van Leeuwen 			token[12].packet_length = cryptlen ? 16 - cryptlen : 0;
312a9a89624SPascal van Leeuwen 			token[12].stat = EIP197_TOKEN_STAT_LAST_HASH;
313a9a89624SPascal van Leeuwen 			token[12].instructions = EIP197_TOKEN_INS_TYPE_HASH;
3144eb76fafSPascal van Leeuwen 		} else {
3154eb76fafSPascal van Leeuwen 			token[7].stat = EIP197_TOKEN_STAT_LAST_HASH;
3164eb76fafSPascal van Leeuwen 			token[7].instructions = EIP197_TOKEN_INS_LAST |
3174eb76fafSPascal van Leeuwen 						EIP197_TOKEN_INS_TYPE_HASH;
3184eb76fafSPascal van Leeuwen 		}
3193e450886SPascal van Leeuwen 	}
320f6beaea3SAntoine Tenart }
321f6beaea3SAntoine Tenart 
3228ac1283eSAntoine Tenart static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm,
3238ac1283eSAntoine Tenart 					const u8 *key, unsigned int len)
3241b44c5a6SAntoine Ténart {
3251b44c5a6SAntoine Ténart 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3261b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
327871df319SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
3281b44c5a6SAntoine Ténart 	struct crypto_aes_ctx aes;
3291b44c5a6SAntoine Ténart 	int ret, i;
3301b44c5a6SAntoine Ténart 
331363a90c2SArd Biesheuvel 	ret = aes_expandkey(&aes, key, len);
3321b44c5a6SAntoine Ténart 	if (ret) {
3331b44c5a6SAntoine Ténart 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
3341b44c5a6SAntoine Ténart 		return ret;
3351b44c5a6SAntoine Ténart 	}
3361b44c5a6SAntoine Ténart 
33753c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
3381b44c5a6SAntoine Ténart 		for (i = 0; i < len / sizeof(u32); i++) {
33913a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
3401b44c5a6SAntoine Ténart 				ctx->base.needs_inv = true;
3411b44c5a6SAntoine Ténart 				break;
3421b44c5a6SAntoine Ténart 			}
3431b44c5a6SAntoine Ténart 		}
344c4daf4ccSOfer Heifetz 	}
3451b44c5a6SAntoine Ténart 
3461b44c5a6SAntoine Ténart 	for (i = 0; i < len / sizeof(u32); i++)
3471b44c5a6SAntoine Ténart 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
3481b44c5a6SAntoine Ténart 
3491b44c5a6SAntoine Ténart 	ctx->key_len = len;
3501b44c5a6SAntoine Ténart 
3511b44c5a6SAntoine Ténart 	memzero_explicit(&aes, sizeof(aes));
3521b44c5a6SAntoine Ténart 	return 0;
3531b44c5a6SAntoine Ténart }
3541b44c5a6SAntoine Ténart 
35577cdd4efSPascal van Leeuwen static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key,
356f6beaea3SAntoine Tenart 				unsigned int len)
357f6beaea3SAntoine Tenart {
358f6beaea3SAntoine Tenart 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
359f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
360f6beaea3SAntoine Tenart 	struct safexcel_ahash_export_state istate, ostate;
361f6beaea3SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
362f6beaea3SAntoine Tenart 	struct crypto_authenc_keys keys;
3630e17e362SPascal van Leeuwen 	struct crypto_aes_ctx aes;
36413a1bb93SPascal van Leeuwen 	int err = -EINVAL, i;
365f6beaea3SAntoine Tenart 
3661769f704SPascal van Leeuwen 	if (unlikely(crypto_authenc_extractkeys(&keys, key, len)))
367f6beaea3SAntoine Tenart 		goto badkey;
368f6beaea3SAntoine Tenart 
3690e17e362SPascal van Leeuwen 	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) {
3701769f704SPascal van Leeuwen 		/* Must have at least space for the nonce here */
3711769f704SPascal van Leeuwen 		if (unlikely(keys.enckeylen < CTR_RFC3686_NONCE_SIZE))
372f6beaea3SAntoine Tenart 			goto badkey;
3730e17e362SPascal van Leeuwen 		/* last 4 bytes of key are the nonce! */
374f26882a3SPascal van Leeuwen 		ctx->nonce = *(u32 *)(keys.enckey + keys.enckeylen -
375f26882a3SPascal van Leeuwen 				      CTR_RFC3686_NONCE_SIZE);
3760e17e362SPascal van Leeuwen 		/* exclude the nonce here */
3771769f704SPascal van Leeuwen 		keys.enckeylen -= CTR_RFC3686_NONCE_SIZE;
3780e17e362SPascal van Leeuwen 	}
379f6beaea3SAntoine Tenart 
380f6beaea3SAntoine Tenart 	/* Encryption key */
3810e17e362SPascal van Leeuwen 	switch (ctx->alg) {
382bb7679b8SPascal van Leeuwen 	case SAFEXCEL_DES:
383bb7679b8SPascal van Leeuwen 		err = verify_aead_des_key(ctfm, keys.enckey, keys.enckeylen);
384bb7679b8SPascal van Leeuwen 		if (unlikely(err))
385bb7679b8SPascal van Leeuwen 			goto badkey_expflags;
386bb7679b8SPascal van Leeuwen 		break;
3870e17e362SPascal van Leeuwen 	case SAFEXCEL_3DES:
38821f5a15eSArd Biesheuvel 		err = verify_aead_des3_key(ctfm, keys.enckey, keys.enckeylen);
38977cdd4efSPascal van Leeuwen 		if (unlikely(err))
3900e17e362SPascal van Leeuwen 			goto badkey_expflags;
3910e17e362SPascal van Leeuwen 		break;
3920e17e362SPascal van Leeuwen 	case SAFEXCEL_AES:
3930e17e362SPascal van Leeuwen 		err = aes_expandkey(&aes, keys.enckey, keys.enckeylen);
3940e17e362SPascal van Leeuwen 		if (unlikely(err))
3950e17e362SPascal van Leeuwen 			goto badkey;
3960e17e362SPascal van Leeuwen 		break;
3971769f704SPascal van Leeuwen 	case SAFEXCEL_SM4:
3981769f704SPascal van Leeuwen 		if (unlikely(keys.enckeylen != SM4_KEY_SIZE))
3991769f704SPascal van Leeuwen 			goto badkey;
4001769f704SPascal van Leeuwen 		break;
4010e17e362SPascal van Leeuwen 	default:
4020e17e362SPascal van Leeuwen 		dev_err(priv->dev, "aead: unsupported cipher algorithm\n");
4030e17e362SPascal van Leeuwen 		goto badkey;
40477cdd4efSPascal van Leeuwen 	}
40577cdd4efSPascal van Leeuwen 
40613a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
40713a1bb93SPascal van Leeuwen 		for (i = 0; i < keys.enckeylen / sizeof(u32); i++) {
408*b8151220SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) !=
409*b8151220SPascal van Leeuwen 			    ((u32 *)keys.enckey)[i]) {
410f6beaea3SAntoine Tenart 				ctx->base.needs_inv = true;
41113a1bb93SPascal van Leeuwen 				break;
41213a1bb93SPascal van Leeuwen 			}
41313a1bb93SPascal van Leeuwen 		}
41413a1bb93SPascal van Leeuwen 	}
415f6beaea3SAntoine Tenart 
416f6beaea3SAntoine Tenart 	/* Auth key */
417a7dea8c0SOfer Heifetz 	switch (ctx->hash_alg) {
41801ba061dSAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA1:
41901ba061dSAntoine Tenart 		if (safexcel_hmac_setkey("safexcel-sha1", keys.authkey,
42001ba061dSAntoine Tenart 					 keys.authkeylen, &istate, &ostate))
42101ba061dSAntoine Tenart 			goto badkey;
42201ba061dSAntoine Tenart 		break;
423678b2878SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA224:
424678b2878SAntoine Tenart 		if (safexcel_hmac_setkey("safexcel-sha224", keys.authkey,
425678b2878SAntoine Tenart 					 keys.authkeylen, &istate, &ostate))
426678b2878SAntoine Tenart 			goto badkey;
427678b2878SAntoine Tenart 		break;
428678b2878SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA256:
429f6beaea3SAntoine Tenart 		if (safexcel_hmac_setkey("safexcel-sha256", keys.authkey,
430f6beaea3SAntoine Tenart 					 keys.authkeylen, &istate, &ostate))
431f6beaea3SAntoine Tenart 			goto badkey;
432678b2878SAntoine Tenart 		break;
433ea23cb53SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA384:
434ea23cb53SAntoine Tenart 		if (safexcel_hmac_setkey("safexcel-sha384", keys.authkey,
435ea23cb53SAntoine Tenart 					 keys.authkeylen, &istate, &ostate))
436ea23cb53SAntoine Tenart 			goto badkey;
437ea23cb53SAntoine Tenart 		break;
43887eee125SAntoine Tenart 	case CONTEXT_CONTROL_CRYPTO_ALG_SHA512:
43987eee125SAntoine Tenart 		if (safexcel_hmac_setkey("safexcel-sha512", keys.authkey,
44087eee125SAntoine Tenart 					 keys.authkeylen, &istate, &ostate))
44187eee125SAntoine Tenart 			goto badkey;
44287eee125SAntoine Tenart 		break;
4431769f704SPascal van Leeuwen 	case CONTEXT_CONTROL_CRYPTO_ALG_SM3:
4441769f704SPascal van Leeuwen 		if (safexcel_hmac_setkey("safexcel-sm3", keys.authkey,
4451769f704SPascal van Leeuwen 					 keys.authkeylen, &istate, &ostate))
4461769f704SPascal van Leeuwen 			goto badkey;
4471769f704SPascal van Leeuwen 		break;
448678b2878SAntoine Tenart 	default:
4491a61af28SColin Ian King 		dev_err(priv->dev, "aead: unsupported hash algorithm\n");
450678b2878SAntoine Tenart 		goto badkey;
451678b2878SAntoine Tenart 	}
452f6beaea3SAntoine Tenart 
453f6beaea3SAntoine Tenart 	crypto_aead_set_flags(ctfm, crypto_aead_get_flags(ctfm) &
454f6beaea3SAntoine Tenart 				    CRYPTO_TFM_RES_MASK);
455f6beaea3SAntoine Tenart 
45653c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma &&
457f6beaea3SAntoine Tenart 	    (memcmp(ctx->ipad, istate.state, ctx->state_sz) ||
458f6beaea3SAntoine Tenart 	     memcmp(ctx->opad, ostate.state, ctx->state_sz)))
459f6beaea3SAntoine Tenart 		ctx->base.needs_inv = true;
460f6beaea3SAntoine Tenart 
461f6beaea3SAntoine Tenart 	/* Now copy the keys into the context */
46213a1bb93SPascal van Leeuwen 	for (i = 0; i < keys.enckeylen / sizeof(u32); i++)
463*b8151220SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(((u32 *)keys.enckey)[i]);
464f6beaea3SAntoine Tenart 	ctx->key_len = keys.enckeylen;
465f6beaea3SAntoine Tenart 
466f6beaea3SAntoine Tenart 	memcpy(ctx->ipad, &istate.state, ctx->state_sz);
467f6beaea3SAntoine Tenart 	memcpy(ctx->opad, &ostate.state, ctx->state_sz);
468f6beaea3SAntoine Tenart 
469f6beaea3SAntoine Tenart 	memzero_explicit(&keys, sizeof(keys));
470f6beaea3SAntoine Tenart 	return 0;
471f6beaea3SAntoine Tenart 
472f6beaea3SAntoine Tenart badkey:
473f6beaea3SAntoine Tenart 	crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
4740e17e362SPascal van Leeuwen badkey_expflags:
475f6beaea3SAntoine Tenart 	memzero_explicit(&keys, sizeof(keys));
4760e17e362SPascal van Leeuwen 	return err;
477f6beaea3SAntoine Tenart }
478f6beaea3SAntoine Tenart 
4791b44c5a6SAntoine Ténart static int safexcel_context_control(struct safexcel_cipher_ctx *ctx,
480847ccfc5SOfer Heifetz 				    struct crypto_async_request *async,
4818ac1283eSAntoine Tenart 				    struct safexcel_cipher_req *sreq,
4821b44c5a6SAntoine Ténart 				    struct safexcel_command_desc *cdesc)
4831b44c5a6SAntoine Ténart {
4841b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
485d2d9e6fdSPascal van Leeuwen 	int ctrl_size = ctx->key_len / sizeof(u32);
486d2d9e6fdSPascal van Leeuwen 
487d2d9e6fdSPascal van Leeuwen 	cdesc->control_data.control1 = ctx->mode;
4881b44c5a6SAntoine Ténart 
489f6beaea3SAntoine Tenart 	if (ctx->aead) {
490d2d9e6fdSPascal van Leeuwen 		/* Take in account the ipad+opad digests */
4913e450886SPascal van Leeuwen 		if (ctx->xcm) {
4923e450886SPascal van Leeuwen 			ctrl_size += ctx->state_sz / sizeof(u32);
4933e450886SPascal van Leeuwen 			cdesc->control_data.control0 =
4943e450886SPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
4953e450886SPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_XCM |
4963e450886SPascal van Leeuwen 				ctx->hash_alg |
4973e450886SPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
498a6061921SPascal van Leeuwen 		} else if (ctx->alg == SAFEXCEL_CHACHA20) {
499a6061921SPascal van Leeuwen 			/* Chacha20-Poly1305 */
500a6061921SPascal van Leeuwen 			cdesc->control_data.control0 =
501a6061921SPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
502a6061921SPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20 |
503a6061921SPascal van Leeuwen 				(sreq->direction == SAFEXCEL_ENCRYPT ?
504a6061921SPascal van Leeuwen 					CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT :
505a6061921SPascal van Leeuwen 					CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN) |
506a6061921SPascal van Leeuwen 				ctx->hash_alg |
507a6061921SPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
508a6061921SPascal van Leeuwen 			return 0;
5093e450886SPascal van Leeuwen 		} else {
510d2d9e6fdSPascal van Leeuwen 			ctrl_size += ctx->state_sz / sizeof(u32) * 2;
5113e450886SPascal van Leeuwen 			cdesc->control_data.control0 =
5123e450886SPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
5133e450886SPascal van Leeuwen 				CONTEXT_CONTROL_DIGEST_HMAC |
5143e450886SPascal van Leeuwen 				ctx->hash_alg |
5153e450886SPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
5163e450886SPascal van Leeuwen 		}
5174eb76fafSPascal van Leeuwen 
51892c60cefSPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_ENCRYPT &&
51992c60cefSPascal van Leeuwen 		    (ctx->xcm == EIP197_XCM_MODE_CCM ||
52092c60cefSPascal van Leeuwen 		     ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP_GMAC))
52192c60cefSPascal van Leeuwen 			cdesc->control_data.control0 |=
52292c60cefSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_ENCRYPT_OUT;
52392c60cefSPascal van Leeuwen 		else if (sreq->direction == SAFEXCEL_ENCRYPT)
52492c60cefSPascal van Leeuwen 			cdesc->control_data.control0 |=
52592c60cefSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT;
52692c60cefSPascal van Leeuwen 		else if (ctx->xcm == EIP197_XCM_MODE_CCM)
52792c60cefSPascal van Leeuwen 			cdesc->control_data.control0 |=
52892c60cefSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_DECRYPT_HASH_IN;
529d2d9e6fdSPascal van Leeuwen 		else
5303e450886SPascal van Leeuwen 			cdesc->control_data.control0 |=
5313e450886SPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN;
532d2d9e6fdSPascal van Leeuwen 	} else {
533d2d9e6fdSPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_ENCRYPT)
534d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 =
535d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_CRYPTO_OUT |
536d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
537d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
538d2d9e6fdSPascal van Leeuwen 		else
539d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 =
540d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_TYPE_CRYPTO_IN |
541d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_KEY_EN |
542d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_SIZE(ctrl_size);
543f6beaea3SAntoine Tenart 	}
5441b44c5a6SAntoine Ténart 
545a7dea8c0SOfer Heifetz 	if (ctx->alg == SAFEXCEL_DES) {
546d2d9e6fdSPascal van Leeuwen 		cdesc->control_data.control0 |=
547d2d9e6fdSPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_DES;
54862469879SOfer Heifetz 	} else if (ctx->alg == SAFEXCEL_3DES) {
549d2d9e6fdSPascal van Leeuwen 		cdesc->control_data.control0 |=
550d2d9e6fdSPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_3DES;
551a7dea8c0SOfer Heifetz 	} else if (ctx->alg == SAFEXCEL_AES) {
552c7da38a7SPascal van Leeuwen 		switch (ctx->key_len >> ctx->xts) {
5531b44c5a6SAntoine Ténart 		case AES_KEYSIZE_128:
554d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 |=
555d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_AES128;
5561b44c5a6SAntoine Ténart 			break;
5571b44c5a6SAntoine Ténart 		case AES_KEYSIZE_192:
558d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 |=
559d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_AES192;
5601b44c5a6SAntoine Ténart 			break;
5611b44c5a6SAntoine Ténart 		case AES_KEYSIZE_256:
562d2d9e6fdSPascal van Leeuwen 			cdesc->control_data.control0 |=
563d2d9e6fdSPascal van Leeuwen 				CONTEXT_CONTROL_CRYPTO_ALG_AES256;
5641b44c5a6SAntoine Ténart 			break;
5651b44c5a6SAntoine Ténart 		default:
5661b44c5a6SAntoine Ténart 			dev_err(priv->dev, "aes keysize not supported: %u\n",
567c7da38a7SPascal van Leeuwen 				ctx->key_len >> ctx->xts);
5681b44c5a6SAntoine Ténart 			return -EINVAL;
5691b44c5a6SAntoine Ténart 		}
5704a593fb3SPascal van Leeuwen 	} else if (ctx->alg == SAFEXCEL_CHACHA20) {
5714a593fb3SPascal van Leeuwen 		cdesc->control_data.control0 |=
5724a593fb3SPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20;
573fcca797dSPascal van Leeuwen 	} else if (ctx->alg == SAFEXCEL_SM4) {
574fcca797dSPascal van Leeuwen 		cdesc->control_data.control0 |=
575fcca797dSPascal van Leeuwen 			CONTEXT_CONTROL_CRYPTO_ALG_SM4;
576a7dea8c0SOfer Heifetz 	}
577fef0cfe5SAntoine Tenart 
5781b44c5a6SAntoine Ténart 	return 0;
5791b44c5a6SAntoine Ténart }
5801b44c5a6SAntoine Ténart 
5811eb7b403SOfer Heifetz static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int ring,
5821b44c5a6SAntoine Ténart 				      struct crypto_async_request *async,
5838ac1283eSAntoine Tenart 				      struct scatterlist *src,
5848ac1283eSAntoine Tenart 				      struct scatterlist *dst,
5858ac1283eSAntoine Tenart 				      unsigned int cryptlen,
5868ac1283eSAntoine Tenart 				      struct safexcel_cipher_req *sreq,
5871b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
5881b44c5a6SAntoine Ténart {
5895bdb6e6aSPascal van Leeuwen 	struct skcipher_request *areq = skcipher_request_cast(async);
5905bdb6e6aSPascal van Leeuwen 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq);
5915bdb6e6aSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(skcipher);
5921b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
5931b44c5a6SAntoine Ténart 	int ndesc = 0;
5941b44c5a6SAntoine Ténart 
5951b44c5a6SAntoine Ténart 	*ret = 0;
5961b44c5a6SAntoine Ténart 
59789332590SAntoine Tenart 	if (unlikely(!sreq->rdescs))
59889332590SAntoine Tenart 		return 0;
59989332590SAntoine Tenart 
60089332590SAntoine Tenart 	while (sreq->rdescs--) {
6011b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
6021b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
6031b44c5a6SAntoine Ténart 			dev_err(priv->dev,
6041b44c5a6SAntoine Ténart 				"cipher: result: could not retrieve the result descriptor\n");
6051b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
6061b44c5a6SAntoine Ténart 			break;
6071b44c5a6SAntoine Ténart 		}
6081b44c5a6SAntoine Ténart 
609bdfd1909SAntoine Tenart 		if (likely(!*ret))
610bdfd1909SAntoine Tenart 			*ret = safexcel_rdesc_check_errors(priv, rdesc);
6111b44c5a6SAntoine Ténart 
6121b44c5a6SAntoine Ténart 		ndesc++;
61389332590SAntoine Tenart 	}
6141b44c5a6SAntoine Ténart 
6151b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
6161b44c5a6SAntoine Ténart 
6178ac1283eSAntoine Tenart 	if (src == dst) {
61819b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL);
6191b44c5a6SAntoine Ténart 	} else {
62019b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE);
62119b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE);
6221b44c5a6SAntoine Ténart 	}
6231b44c5a6SAntoine Ténart 
6245bdb6e6aSPascal van Leeuwen 	/*
6255bdb6e6aSPascal van Leeuwen 	 * Update IV in req from last crypto output word for CBC modes
6265bdb6e6aSPascal van Leeuwen 	 */
6275bdb6e6aSPascal van Leeuwen 	if ((!ctx->aead) && (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) &&
6285bdb6e6aSPascal van Leeuwen 	    (sreq->direction == SAFEXCEL_ENCRYPT)) {
6295bdb6e6aSPascal van Leeuwen 		/* For encrypt take the last output word */
63019b347b3SPascal van Leeuwen 		sg_pcopy_to_buffer(dst, sreq->nr_dst, areq->iv,
6315bdb6e6aSPascal van Leeuwen 				   crypto_skcipher_ivsize(skcipher),
6325bdb6e6aSPascal van Leeuwen 				   (cryptlen -
6335bdb6e6aSPascal van Leeuwen 				    crypto_skcipher_ivsize(skcipher)));
6345bdb6e6aSPascal van Leeuwen 	}
6355bdb6e6aSPascal van Leeuwen 
6361b44c5a6SAntoine Ténart 	*should_complete = true;
6371b44c5a6SAntoine Ténart 
6381b44c5a6SAntoine Ténart 	return ndesc;
6391b44c5a6SAntoine Ténart }
6401b44c5a6SAntoine Ténart 
641a7dea8c0SOfer Heifetz static int safexcel_send_req(struct crypto_async_request *base, int ring,
6428ac1283eSAntoine Tenart 			     struct safexcel_cipher_req *sreq,
6438ac1283eSAntoine Tenart 			     struct scatterlist *src, struct scatterlist *dst,
644f6beaea3SAntoine Tenart 			     unsigned int cryptlen, unsigned int assoclen,
645f6beaea3SAntoine Tenart 			     unsigned int digestsize, u8 *iv, int *commands,
6468ac1283eSAntoine Tenart 			     int *results)
6471b44c5a6SAntoine Ténart {
6485bdb6e6aSPascal van Leeuwen 	struct skcipher_request *areq = skcipher_request_cast(base);
6495bdb6e6aSPascal van Leeuwen 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq);
6508ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
6511b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
6521b44c5a6SAntoine Ténart 	struct safexcel_command_desc *cdesc;
65319b347b3SPascal van Leeuwen 	struct safexcel_command_desc *first_cdesc = NULL;
654e5c8ee1fSAntoine Tenart 	struct safexcel_result_desc *rdesc, *first_rdesc = NULL;
6551b44c5a6SAntoine Ténart 	struct scatterlist *sg;
65619b347b3SPascal van Leeuwen 	unsigned int totlen;
65719b347b3SPascal van Leeuwen 	unsigned int totlen_src = cryptlen + assoclen;
65819b347b3SPascal van Leeuwen 	unsigned int totlen_dst = totlen_src;
65919b347b3SPascal van Leeuwen 	int n_cdesc = 0, n_rdesc = 0;
66019b347b3SPascal van Leeuwen 	int queued, i, ret = 0;
66119b347b3SPascal van Leeuwen 	bool first = true;
6621b44c5a6SAntoine Ténart 
66319b347b3SPascal van Leeuwen 	sreq->nr_src = sg_nents_for_len(src, totlen_src);
66419b347b3SPascal van Leeuwen 
66519b347b3SPascal van Leeuwen 	if (ctx->aead) {
66619b347b3SPascal van Leeuwen 		/*
66719b347b3SPascal van Leeuwen 		 * AEAD has auth tag appended to output for encrypt and
66819b347b3SPascal van Leeuwen 		 * removed from the output for decrypt!
66919b347b3SPascal van Leeuwen 		 */
67019b347b3SPascal van Leeuwen 		if (sreq->direction == SAFEXCEL_DECRYPT)
67119b347b3SPascal van Leeuwen 			totlen_dst -= digestsize;
67219b347b3SPascal van Leeuwen 		else
67319b347b3SPascal van Leeuwen 			totlen_dst += digestsize;
67419b347b3SPascal van Leeuwen 
67519b347b3SPascal van Leeuwen 		memcpy(ctx->base.ctxr->data + ctx->key_len / sizeof(u32),
67619b347b3SPascal van Leeuwen 		       ctx->ipad, ctx->state_sz);
6773e450886SPascal van Leeuwen 		if (!ctx->xcm)
6783e450886SPascal van Leeuwen 			memcpy(ctx->base.ctxr->data + (ctx->key_len +
6793e450886SPascal van Leeuwen 			       ctx->state_sz) / sizeof(u32), ctx->opad,
6803e450886SPascal van Leeuwen 			       ctx->state_sz);
68119b347b3SPascal van Leeuwen 	} else if ((ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) &&
6825bdb6e6aSPascal van Leeuwen 		   (sreq->direction == SAFEXCEL_DECRYPT)) {
6835bdb6e6aSPascal van Leeuwen 		/*
6845bdb6e6aSPascal van Leeuwen 		 * Save IV from last crypto input word for CBC modes in decrypt
6855bdb6e6aSPascal van Leeuwen 		 * direction. Need to do this first in case of inplace operation
6865bdb6e6aSPascal van Leeuwen 		 * as it will be overwritten.
6875bdb6e6aSPascal van Leeuwen 		 */
68819b347b3SPascal van Leeuwen 		sg_pcopy_to_buffer(src, sreq->nr_src, areq->iv,
6895bdb6e6aSPascal van Leeuwen 				   crypto_skcipher_ivsize(skcipher),
69019b347b3SPascal van Leeuwen 				   (totlen_src -
6915bdb6e6aSPascal van Leeuwen 				    crypto_skcipher_ivsize(skcipher)));
6925bdb6e6aSPascal van Leeuwen 	}
6935bdb6e6aSPascal van Leeuwen 
69419b347b3SPascal van Leeuwen 	sreq->nr_dst = sg_nents_for_len(dst, totlen_dst);
6951b44c5a6SAntoine Ténart 
69619b347b3SPascal van Leeuwen 	/*
69719b347b3SPascal van Leeuwen 	 * Remember actual input length, source buffer length may be
69819b347b3SPascal van Leeuwen 	 * updated in case of inline operation below.
69919b347b3SPascal van Leeuwen 	 */
70019b347b3SPascal van Leeuwen 	totlen = totlen_src;
70119b347b3SPascal van Leeuwen 	queued = totlen_src;
70219b347b3SPascal van Leeuwen 
70319b347b3SPascal van Leeuwen 	if (src == dst) {
70419b347b3SPascal van Leeuwen 		sreq->nr_src = max(sreq->nr_src, sreq->nr_dst);
70519b347b3SPascal van Leeuwen 		sreq->nr_dst = sreq->nr_src;
70619b347b3SPascal van Leeuwen 		if (unlikely((totlen_src || totlen_dst) &&
70719b347b3SPascal van Leeuwen 		    (sreq->nr_src <= 0))) {
70819b347b3SPascal van Leeuwen 			dev_err(priv->dev, "In-place buffer not large enough (need %d bytes)!",
70919b347b3SPascal van Leeuwen 				max(totlen_src, totlen_dst));
7101b44c5a6SAntoine Ténart 			return -EINVAL;
7111b44c5a6SAntoine Ténart 		}
71219b347b3SPascal van Leeuwen 		dma_map_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL);
71319b347b3SPascal van Leeuwen 	} else {
71419b347b3SPascal van Leeuwen 		if (unlikely(totlen_src && (sreq->nr_src <= 0))) {
71519b347b3SPascal van Leeuwen 			dev_err(priv->dev, "Source buffer not large enough (need %d bytes)!",
71619b347b3SPascal van Leeuwen 				totlen_src);
71719b347b3SPascal van Leeuwen 			return -EINVAL;
71819b347b3SPascal van Leeuwen 		}
71919b347b3SPascal van Leeuwen 		dma_map_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE);
72019b347b3SPascal van Leeuwen 
72119b347b3SPascal van Leeuwen 		if (unlikely(totlen_dst && (sreq->nr_dst <= 0))) {
72219b347b3SPascal van Leeuwen 			dev_err(priv->dev, "Dest buffer not large enough (need %d bytes)!",
72319b347b3SPascal van Leeuwen 				totlen_dst);
72419b347b3SPascal van Leeuwen 			dma_unmap_sg(priv->dev, src, sreq->nr_src,
72519b347b3SPascal van Leeuwen 				     DMA_TO_DEVICE);
72619b347b3SPascal van Leeuwen 			return -EINVAL;
72719b347b3SPascal van Leeuwen 		}
72819b347b3SPascal van Leeuwen 		dma_map_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE);
7291b44c5a6SAntoine Ténart 	}
7301b44c5a6SAntoine Ténart 
7311b44c5a6SAntoine Ténart 	memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len);
7321b44c5a6SAntoine Ténart 
73319b347b3SPascal van Leeuwen 	/* The EIP cannot deal with zero length input packets! */
73419b347b3SPascal van Leeuwen 	if (totlen == 0)
73519b347b3SPascal van Leeuwen 		totlen = 1;
736f6beaea3SAntoine Tenart 
7371b44c5a6SAntoine Ténart 	/* command descriptors */
73819b347b3SPascal van Leeuwen 	for_each_sg(src, sg, sreq->nr_src, i) {
7391b44c5a6SAntoine Ténart 		int len = sg_dma_len(sg);
7401b44c5a6SAntoine Ténart 
7411b44c5a6SAntoine Ténart 		/* Do not overflow the request */
7421b44c5a6SAntoine Ténart 		if (queued - len < 0)
7431b44c5a6SAntoine Ténart 			len = queued;
7441b44c5a6SAntoine Ténart 
74519b347b3SPascal van Leeuwen 		cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
74619b347b3SPascal van Leeuwen 					   !(queued - len),
747f6beaea3SAntoine Tenart 					   sg_dma_address(sg), len, totlen,
7481b44c5a6SAntoine Ténart 					   ctx->base.ctxr_dma);
7491b44c5a6SAntoine Ténart 		if (IS_ERR(cdesc)) {
7501b44c5a6SAntoine Ténart 			/* No space left in the command descriptor ring */
7511b44c5a6SAntoine Ténart 			ret = PTR_ERR(cdesc);
7521b44c5a6SAntoine Ténart 			goto cdesc_rollback;
7531b44c5a6SAntoine Ténart 		}
7541b44c5a6SAntoine Ténart 		n_cdesc++;
7551b44c5a6SAntoine Ténart 
7561b44c5a6SAntoine Ténart 		if (n_cdesc == 1) {
75719b347b3SPascal van Leeuwen 			first_cdesc = cdesc;
7581b44c5a6SAntoine Ténart 		}
7591b44c5a6SAntoine Ténart 
7601b44c5a6SAntoine Ténart 		queued -= len;
7611b44c5a6SAntoine Ténart 		if (!queued)
7621b44c5a6SAntoine Ténart 			break;
7631b44c5a6SAntoine Ténart 	}
7641b44c5a6SAntoine Ténart 
76519b347b3SPascal van Leeuwen 	if (unlikely(!n_cdesc)) {
76619b347b3SPascal van Leeuwen 		/*
76719b347b3SPascal van Leeuwen 		 * Special case: zero length input buffer.
76819b347b3SPascal van Leeuwen 		 * The engine always needs the 1st command descriptor, however!
76919b347b3SPascal van Leeuwen 		 */
77019b347b3SPascal van Leeuwen 		first_cdesc = safexcel_add_cdesc(priv, ring, 1, 1, 0, 0, totlen,
77119b347b3SPascal van Leeuwen 						 ctx->base.ctxr_dma);
77219b347b3SPascal van Leeuwen 		n_cdesc = 1;
77319b347b3SPascal van Leeuwen 	}
77419b347b3SPascal van Leeuwen 
77519b347b3SPascal van Leeuwen 	/* Add context control words and token to first command descriptor */
77619b347b3SPascal van Leeuwen 	safexcel_context_control(ctx, base, sreq, first_cdesc);
77719b347b3SPascal van Leeuwen 	if (ctx->aead)
77819b347b3SPascal van Leeuwen 		safexcel_aead_token(ctx, iv, first_cdesc,
77919b347b3SPascal van Leeuwen 				    sreq->direction, cryptlen,
78019b347b3SPascal van Leeuwen 				    assoclen, digestsize);
78119b347b3SPascal van Leeuwen 	else
78219b347b3SPascal van Leeuwen 		safexcel_skcipher_token(ctx, iv, first_cdesc,
78319b347b3SPascal van Leeuwen 					cryptlen);
78419b347b3SPascal van Leeuwen 
7851b44c5a6SAntoine Ténart 	/* result descriptors */
78619b347b3SPascal van Leeuwen 	for_each_sg(dst, sg, sreq->nr_dst, i) {
78719b347b3SPascal van Leeuwen 		bool last = (i == sreq->nr_dst - 1);
7881b44c5a6SAntoine Ténart 		u32 len = sg_dma_len(sg);
7891b44c5a6SAntoine Ténart 
79019b347b3SPascal van Leeuwen 		/* only allow the part of the buffer we know we need */
79119b347b3SPascal van Leeuwen 		if (len > totlen_dst)
79219b347b3SPascal van Leeuwen 			len = totlen_dst;
79319b347b3SPascal van Leeuwen 		if (unlikely(!len))
79419b347b3SPascal van Leeuwen 			break;
79519b347b3SPascal van Leeuwen 		totlen_dst -= len;
79619b347b3SPascal van Leeuwen 
79719b347b3SPascal van Leeuwen 		/* skip over AAD space in buffer - not written */
79819b347b3SPascal van Leeuwen 		if (assoclen) {
79919b347b3SPascal van Leeuwen 			if (assoclen >= len) {
80019b347b3SPascal van Leeuwen 				assoclen -= len;
80119b347b3SPascal van Leeuwen 				continue;
80219b347b3SPascal van Leeuwen 			}
8031b44c5a6SAntoine Ténart 			rdesc = safexcel_add_rdesc(priv, ring, first, last,
80419b347b3SPascal van Leeuwen 						   sg_dma_address(sg) +
80519b347b3SPascal van Leeuwen 						   assoclen,
80619b347b3SPascal van Leeuwen 						   len - assoclen);
80719b347b3SPascal van Leeuwen 			assoclen = 0;
80819b347b3SPascal van Leeuwen 		} else {
80919b347b3SPascal van Leeuwen 			rdesc = safexcel_add_rdesc(priv, ring, first, last,
81019b347b3SPascal van Leeuwen 						   sg_dma_address(sg),
81119b347b3SPascal van Leeuwen 						   len);
81219b347b3SPascal van Leeuwen 		}
8131b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
8141b44c5a6SAntoine Ténart 			/* No space left in the result descriptor ring */
8151b44c5a6SAntoine Ténart 			ret = PTR_ERR(rdesc);
8161b44c5a6SAntoine Ténart 			goto rdesc_rollback;
8171b44c5a6SAntoine Ténart 		}
81819b347b3SPascal van Leeuwen 		if (first) {
8199744fec9SOfer Heifetz 			first_rdesc = rdesc;
82019b347b3SPascal van Leeuwen 			first = false;
82119b347b3SPascal van Leeuwen 		}
8221b44c5a6SAntoine Ténart 		n_rdesc++;
8231b44c5a6SAntoine Ténart 	}
8241b44c5a6SAntoine Ténart 
82519b347b3SPascal van Leeuwen 	if (unlikely(first)) {
82619b347b3SPascal van Leeuwen 		/*
82719b347b3SPascal van Leeuwen 		 * Special case: AEAD decrypt with only AAD data.
82819b347b3SPascal van Leeuwen 		 * In this case there is NO output data from the engine,
82919b347b3SPascal van Leeuwen 		 * but the engine still needs a result descriptor!
83019b347b3SPascal van Leeuwen 		 * Create a dummy one just for catching the result token.
83119b347b3SPascal van Leeuwen 		 */
83219b347b3SPascal van Leeuwen 		rdesc = safexcel_add_rdesc(priv, ring, true, true, 0, 0);
83319b347b3SPascal van Leeuwen 		if (IS_ERR(rdesc)) {
83419b347b3SPascal van Leeuwen 			/* No space left in the result descriptor ring */
83519b347b3SPascal van Leeuwen 			ret = PTR_ERR(rdesc);
83619b347b3SPascal van Leeuwen 			goto rdesc_rollback;
83719b347b3SPascal van Leeuwen 		}
83819b347b3SPascal van Leeuwen 		first_rdesc = rdesc;
83919b347b3SPascal van Leeuwen 		n_rdesc = 1;
84019b347b3SPascal van Leeuwen 	}
84119b347b3SPascal van Leeuwen 
8429744fec9SOfer Heifetz 	safexcel_rdr_req_set(priv, ring, first_rdesc, base);
84397858434SAntoine Ténart 
8441b44c5a6SAntoine Ténart 	*commands = n_cdesc;
845152bdf4cSOfer Heifetz 	*results = n_rdesc;
8461b44c5a6SAntoine Ténart 	return 0;
8471b44c5a6SAntoine Ténart 
8481b44c5a6SAntoine Ténart rdesc_rollback:
8491b44c5a6SAntoine Ténart 	for (i = 0; i < n_rdesc; i++)
8501b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].rdr);
8511b44c5a6SAntoine Ténart cdesc_rollback:
8521b44c5a6SAntoine Ténart 	for (i = 0; i < n_cdesc; i++)
8531b44c5a6SAntoine Ténart 		safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);
8541b44c5a6SAntoine Ténart 
8558ac1283eSAntoine Tenart 	if (src == dst) {
85619b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL);
8571b44c5a6SAntoine Ténart 	} else {
85819b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE);
85919b347b3SPascal van Leeuwen 		dma_unmap_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE);
8601b44c5a6SAntoine Ténart 	}
8611b44c5a6SAntoine Ténart 
8621b44c5a6SAntoine Ténart 	return ret;
8631b44c5a6SAntoine Ténart }
8641b44c5a6SAntoine Ténart 
8651b44c5a6SAntoine Ténart static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv,
8661b44c5a6SAntoine Ténart 				      int ring,
8678ac1283eSAntoine Tenart 				      struct crypto_async_request *base,
86889332590SAntoine Tenart 				      struct safexcel_cipher_req *sreq,
8691b44c5a6SAntoine Ténart 				      bool *should_complete, int *ret)
8701b44c5a6SAntoine Ténart {
8718ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
8721b44c5a6SAntoine Ténart 	struct safexcel_result_desc *rdesc;
8731b44c5a6SAntoine Ténart 	int ndesc = 0, enq_ret;
8741b44c5a6SAntoine Ténart 
8751b44c5a6SAntoine Ténart 	*ret = 0;
8761b44c5a6SAntoine Ténart 
87789332590SAntoine Tenart 	if (unlikely(!sreq->rdescs))
87889332590SAntoine Tenart 		return 0;
87989332590SAntoine Tenart 
88089332590SAntoine Tenart 	while (sreq->rdescs--) {
8811b44c5a6SAntoine Ténart 		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
8821b44c5a6SAntoine Ténart 		if (IS_ERR(rdesc)) {
8831b44c5a6SAntoine Ténart 			dev_err(priv->dev,
8841b44c5a6SAntoine Ténart 				"cipher: invalidate: could not retrieve the result descriptor\n");
8851b44c5a6SAntoine Ténart 			*ret = PTR_ERR(rdesc);
8861b44c5a6SAntoine Ténart 			break;
8871b44c5a6SAntoine Ténart 		}
8881b44c5a6SAntoine Ténart 
889cda3e73aSAntoine Tenart 		if (likely(!*ret))
890cda3e73aSAntoine Tenart 			*ret = safexcel_rdesc_check_errors(priv, rdesc);
8911b44c5a6SAntoine Ténart 
8921b44c5a6SAntoine Ténart 		ndesc++;
89389332590SAntoine Tenart 	}
8941b44c5a6SAntoine Ténart 
8951b44c5a6SAntoine Ténart 	safexcel_complete(priv, ring);
8961b44c5a6SAntoine Ténart 
8971b44c5a6SAntoine Ténart 	if (ctx->base.exit_inv) {
8981b44c5a6SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
8991b44c5a6SAntoine Ténart 			      ctx->base.ctxr_dma);
9001b44c5a6SAntoine Ténart 
9011b44c5a6SAntoine Ténart 		*should_complete = true;
9021b44c5a6SAntoine Ténart 
9031b44c5a6SAntoine Ténart 		return ndesc;
9041b44c5a6SAntoine Ténart 	}
9051b44c5a6SAntoine Ténart 
90686671abbSAntoine Ténart 	ring = safexcel_select_ring(priv);
90786671abbSAntoine Ténart 	ctx->base.ring = ring;
9081b44c5a6SAntoine Ténart 
90986671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
9108ac1283eSAntoine Tenart 	enq_ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
91186671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
9121b44c5a6SAntoine Ténart 
9131b44c5a6SAntoine Ténart 	if (enq_ret != -EINPROGRESS)
9141b44c5a6SAntoine Ténart 		*ret = enq_ret;
9151b44c5a6SAntoine Ténart 
9168472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
9178472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
91886671abbSAntoine Ténart 
9191b44c5a6SAntoine Ténart 	*should_complete = false;
9201b44c5a6SAntoine Ténart 
9211b44c5a6SAntoine Ténart 	return ndesc;
9221b44c5a6SAntoine Ténart }
9231b44c5a6SAntoine Ténart 
9248ac1283eSAntoine Tenart static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv,
9258ac1283eSAntoine Tenart 					   int ring,
9261eb7b403SOfer Heifetz 					   struct crypto_async_request *async,
9271eb7b403SOfer Heifetz 					   bool *should_complete, int *ret)
9281eb7b403SOfer Heifetz {
9291eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
9301eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
9311eb7b403SOfer Heifetz 	int err;
9321eb7b403SOfer Heifetz 
9331eb7b403SOfer Heifetz 	if (sreq->needs_inv) {
9341eb7b403SOfer Heifetz 		sreq->needs_inv = false;
93589332590SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async, sreq,
9361eb7b403SOfer Heifetz 						 should_complete, ret);
9371eb7b403SOfer Heifetz 	} else {
9388ac1283eSAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
9398ac1283eSAntoine Tenart 						 req->dst, req->cryptlen, sreq,
9401eb7b403SOfer Heifetz 						 should_complete, ret);
9411eb7b403SOfer Heifetz 	}
9421eb7b403SOfer Heifetz 
9431eb7b403SOfer Heifetz 	return err;
9441eb7b403SOfer Heifetz }
9451eb7b403SOfer Heifetz 
946f6beaea3SAntoine Tenart static int safexcel_aead_handle_result(struct safexcel_crypto_priv *priv,
947f6beaea3SAntoine Tenart 				       int ring,
948f6beaea3SAntoine Tenart 				       struct crypto_async_request *async,
949f6beaea3SAntoine Tenart 				       bool *should_complete, int *ret)
950f6beaea3SAntoine Tenart {
951f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
952f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
953f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
954f6beaea3SAntoine Tenart 	int err;
955f6beaea3SAntoine Tenart 
956f6beaea3SAntoine Tenart 	if (sreq->needs_inv) {
957f6beaea3SAntoine Tenart 		sreq->needs_inv = false;
95889332590SAntoine Tenart 		err = safexcel_handle_inv_result(priv, ring, async, sreq,
959f6beaea3SAntoine Tenart 						 should_complete, ret);
960f6beaea3SAntoine Tenart 	} else {
961f6beaea3SAntoine Tenart 		err = safexcel_handle_req_result(priv, ring, async, req->src,
962f6beaea3SAntoine Tenart 						 req->dst,
963f6beaea3SAntoine Tenart 						 req->cryptlen + crypto_aead_authsize(tfm),
964f6beaea3SAntoine Tenart 						 sreq, should_complete, ret);
965f6beaea3SAntoine Tenart 	}
966f6beaea3SAntoine Tenart 
967f6beaea3SAntoine Tenart 	return err;
968f6beaea3SAntoine Tenart }
969f6beaea3SAntoine Tenart 
9708ac1283eSAntoine Tenart static int safexcel_cipher_send_inv(struct crypto_async_request *base,
9719744fec9SOfer Heifetz 				    int ring, int *commands, int *results)
9721b44c5a6SAntoine Ténart {
9738ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
9741b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
9751b44c5a6SAntoine Ténart 	int ret;
9761b44c5a6SAntoine Ténart 
9779744fec9SOfer Heifetz 	ret = safexcel_invalidate_cache(base, priv, ctx->base.ctxr_dma, ring);
9781b44c5a6SAntoine Ténart 	if (unlikely(ret))
9791b44c5a6SAntoine Ténart 		return ret;
9801b44c5a6SAntoine Ténart 
9811b44c5a6SAntoine Ténart 	*commands = 1;
9821b44c5a6SAntoine Ténart 	*results = 1;
9831b44c5a6SAntoine Ténart 
9841b44c5a6SAntoine Ténart 	return 0;
9851b44c5a6SAntoine Ténart }
9861b44c5a6SAntoine Ténart 
9878ac1283eSAntoine Tenart static int safexcel_skcipher_send(struct crypto_async_request *async, int ring,
9881eb7b403SOfer Heifetz 				  int *commands, int *results)
9891eb7b403SOfer Heifetz {
9901eb7b403SOfer Heifetz 	struct skcipher_request *req = skcipher_request_cast(async);
991871df319SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
9921eb7b403SOfer Heifetz 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
993871df319SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
9941eb7b403SOfer Heifetz 	int ret;
9951eb7b403SOfer Heifetz 
99653c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv);
997871df319SAntoine Ténart 
9985bdb6e6aSPascal van Leeuwen 	if (sreq->needs_inv) {
9999744fec9SOfer Heifetz 		ret = safexcel_cipher_send_inv(async, ring, commands, results);
10005bdb6e6aSPascal van Leeuwen 	} else {
10015bdb6e6aSPascal van Leeuwen 		struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
10025bdb6e6aSPascal van Leeuwen 		u8 input_iv[AES_BLOCK_SIZE];
10035bdb6e6aSPascal van Leeuwen 
10045bdb6e6aSPascal van Leeuwen 		/*
10055bdb6e6aSPascal van Leeuwen 		 * Save input IV in case of CBC decrypt mode
10065bdb6e6aSPascal van Leeuwen 		 * Will be overwritten with output IV prior to use!
10075bdb6e6aSPascal van Leeuwen 		 */
10085bdb6e6aSPascal van Leeuwen 		memcpy(input_iv, req->iv, crypto_skcipher_ivsize(skcipher));
10095bdb6e6aSPascal van Leeuwen 
10109744fec9SOfer Heifetz 		ret = safexcel_send_req(async, ring, sreq, req->src,
10115bdb6e6aSPascal van Leeuwen 					req->dst, req->cryptlen, 0, 0, input_iv,
1012f6beaea3SAntoine Tenart 					commands, results);
10135bdb6e6aSPascal van Leeuwen 	}
101489332590SAntoine Tenart 
101589332590SAntoine Tenart 	sreq->rdescs = *results;
1016f6beaea3SAntoine Tenart 	return ret;
1017f6beaea3SAntoine Tenart }
1018f6beaea3SAntoine Tenart 
1019f6beaea3SAntoine Tenart static int safexcel_aead_send(struct crypto_async_request *async, int ring,
10209744fec9SOfer Heifetz 			      int *commands, int *results)
1021f6beaea3SAntoine Tenart {
1022f6beaea3SAntoine Tenart 	struct aead_request *req = aead_request_cast(async);
1023f6beaea3SAntoine Tenart 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1024f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
1025f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
1026f6beaea3SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
1027f6beaea3SAntoine Tenart 	int ret;
1028f6beaea3SAntoine Tenart 
102953c83e91SAntoine Tenart 	BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv);
1030f6beaea3SAntoine Tenart 
1031f6beaea3SAntoine Tenart 	if (sreq->needs_inv)
10329744fec9SOfer Heifetz 		ret = safexcel_cipher_send_inv(async, ring, commands, results);
1033f6beaea3SAntoine Tenart 	else
10349744fec9SOfer Heifetz 		ret = safexcel_send_req(async, ring, sreq, req->src, req->dst,
10359744fec9SOfer Heifetz 					req->cryptlen, req->assoclen,
1036f6beaea3SAntoine Tenart 					crypto_aead_authsize(tfm), req->iv,
10371eb7b403SOfer Heifetz 					commands, results);
103889332590SAntoine Tenart 	sreq->rdescs = *results;
10391eb7b403SOfer Heifetz 	return ret;
10401eb7b403SOfer Heifetz }
10411eb7b403SOfer Heifetz 
10428ac1283eSAntoine Tenart static int safexcel_cipher_exit_inv(struct crypto_tfm *tfm,
10438ac1283eSAntoine Tenart 				    struct crypto_async_request *base,
10448ac1283eSAntoine Tenart 				    struct safexcel_cipher_req *sreq,
10458ac1283eSAntoine Tenart 				    struct safexcel_inv_result *result)
10461b44c5a6SAntoine Ténart {
10471b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
10481b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
104986671abbSAntoine Ténart 	int ring = ctx->base.ring;
10501b44c5a6SAntoine Ténart 
10518ac1283eSAntoine Tenart 	init_completion(&result->completion);
10521b44c5a6SAntoine Ténart 
10538ac1283eSAntoine Tenart 	ctx = crypto_tfm_ctx(base->tfm);
10541b44c5a6SAntoine Ténart 	ctx->base.exit_inv = true;
10551eb7b403SOfer Heifetz 	sreq->needs_inv = true;
10561b44c5a6SAntoine Ténart 
105786671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
10588ac1283eSAntoine Tenart 	crypto_enqueue_request(&priv->ring[ring].queue, base);
105986671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
10601b44c5a6SAntoine Ténart 
10618472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
10628472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
10631b44c5a6SAntoine Ténart 
10648ac1283eSAntoine Tenart 	wait_for_completion(&result->completion);
10651b44c5a6SAntoine Ténart 
10668ac1283eSAntoine Tenart 	if (result->error) {
10671b44c5a6SAntoine Ténart 		dev_warn(priv->dev,
10681b44c5a6SAntoine Ténart 			"cipher: sync: invalidate: completion error %d\n",
10698ac1283eSAntoine Tenart 			 result->error);
10708ac1283eSAntoine Tenart 		return result->error;
10711b44c5a6SAntoine Ténart 	}
10721b44c5a6SAntoine Ténart 
10731b44c5a6SAntoine Ténart 	return 0;
10741b44c5a6SAntoine Ténart }
10751b44c5a6SAntoine Ténart 
10768ac1283eSAntoine Tenart static int safexcel_skcipher_exit_inv(struct crypto_tfm *tfm)
10778ac1283eSAntoine Tenart {
10788ac1283eSAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, skcipher, EIP197_SKCIPHER_REQ_SIZE);
10798ac1283eSAntoine Tenart 	struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
10808ac1283eSAntoine Tenart 	struct safexcel_inv_result result = {};
10818ac1283eSAntoine Tenart 
10828ac1283eSAntoine Tenart 	memset(req, 0, sizeof(struct skcipher_request));
10838ac1283eSAntoine Tenart 
10848ac1283eSAntoine Tenart 	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
10858ac1283eSAntoine Tenart 				      safexcel_inv_complete, &result);
10868ac1283eSAntoine Tenart 	skcipher_request_set_tfm(req, __crypto_skcipher_cast(tfm));
10878ac1283eSAntoine Tenart 
10888ac1283eSAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
10898ac1283eSAntoine Tenart }
10908ac1283eSAntoine Tenart 
1091f6beaea3SAntoine Tenart static int safexcel_aead_exit_inv(struct crypto_tfm *tfm)
1092f6beaea3SAntoine Tenart {
1093f6beaea3SAntoine Tenart 	EIP197_REQUEST_ON_STACK(req, aead, EIP197_AEAD_REQ_SIZE);
1094f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *sreq = aead_request_ctx(req);
1095f6beaea3SAntoine Tenart 	struct safexcel_inv_result result = {};
1096f6beaea3SAntoine Tenart 
1097f6beaea3SAntoine Tenart 	memset(req, 0, sizeof(struct aead_request));
1098f6beaea3SAntoine Tenart 
1099f6beaea3SAntoine Tenart 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1100f6beaea3SAntoine Tenart 				  safexcel_inv_complete, &result);
1101f6beaea3SAntoine Tenart 	aead_request_set_tfm(req, __crypto_aead_cast(tfm));
1102f6beaea3SAntoine Tenart 
1103f6beaea3SAntoine Tenart 	return safexcel_cipher_exit_inv(tfm, &req->base, sreq, &result);
1104f6beaea3SAntoine Tenart }
1105f6beaea3SAntoine Tenart 
1106a7dea8c0SOfer Heifetz static int safexcel_queue_req(struct crypto_async_request *base,
11078ac1283eSAntoine Tenart 			struct safexcel_cipher_req *sreq,
110893369b5dSPascal van Leeuwen 			enum safexcel_cipher_direction dir)
11091b44c5a6SAntoine Ténart {
11108ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm);
11111b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
111286671abbSAntoine Ténart 	int ret, ring;
11131b44c5a6SAntoine Ténart 
11141eb7b403SOfer Heifetz 	sreq->needs_inv = false;
1115847ccfc5SOfer Heifetz 	sreq->direction = dir;
11161b44c5a6SAntoine Ténart 
11171b44c5a6SAntoine Ténart 	if (ctx->base.ctxr) {
111853c83e91SAntoine Tenart 		if (priv->flags & EIP197_TRC_CACHE && ctx->base.needs_inv) {
11191eb7b403SOfer Heifetz 			sreq->needs_inv = true;
11201eb7b403SOfer Heifetz 			ctx->base.needs_inv = false;
11211eb7b403SOfer Heifetz 		}
11221b44c5a6SAntoine Ténart 	} else {
11231b44c5a6SAntoine Ténart 		ctx->base.ring = safexcel_select_ring(priv);
11241b44c5a6SAntoine Ténart 		ctx->base.ctxr = dma_pool_zalloc(priv->context_pool,
11258ac1283eSAntoine Tenart 						 EIP197_GFP_FLAGS(*base),
11261b44c5a6SAntoine Ténart 						 &ctx->base.ctxr_dma);
11271b44c5a6SAntoine Ténart 		if (!ctx->base.ctxr)
11281b44c5a6SAntoine Ténart 			return -ENOMEM;
11291b44c5a6SAntoine Ténart 	}
11301b44c5a6SAntoine Ténart 
113186671abbSAntoine Ténart 	ring = ctx->base.ring;
11321b44c5a6SAntoine Ténart 
113386671abbSAntoine Ténart 	spin_lock_bh(&priv->ring[ring].queue_lock);
11348ac1283eSAntoine Tenart 	ret = crypto_enqueue_request(&priv->ring[ring].queue, base);
113586671abbSAntoine Ténart 	spin_unlock_bh(&priv->ring[ring].queue_lock);
113686671abbSAntoine Ténart 
11378472e778SAntoine Ténart 	queue_work(priv->ring[ring].workqueue,
11388472e778SAntoine Ténart 		   &priv->ring[ring].work_data.work);
11391b44c5a6SAntoine Ténart 
11401b44c5a6SAntoine Ténart 	return ret;
11411b44c5a6SAntoine Ténart }
11421b44c5a6SAntoine Ténart 
114393369b5dSPascal van Leeuwen static int safexcel_encrypt(struct skcipher_request *req)
11441b44c5a6SAntoine Ténart {
1145a7dea8c0SOfer Heifetz 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
114693369b5dSPascal van Leeuwen 			SAFEXCEL_ENCRYPT);
11471b44c5a6SAntoine Ténart }
11481b44c5a6SAntoine Ténart 
114993369b5dSPascal van Leeuwen static int safexcel_decrypt(struct skcipher_request *req)
11501b44c5a6SAntoine Ténart {
1151a7dea8c0SOfer Heifetz 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
115293369b5dSPascal van Leeuwen 			SAFEXCEL_DECRYPT);
11531b44c5a6SAntoine Ténart }
11541b44c5a6SAntoine Ténart 
11551b44c5a6SAntoine Ténart static int safexcel_skcipher_cra_init(struct crypto_tfm *tfm)
11561b44c5a6SAntoine Ténart {
11571b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
11581b44c5a6SAntoine Ténart 	struct safexcel_alg_template *tmpl =
11591b44c5a6SAntoine Ténart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
11601b44c5a6SAntoine Ténart 			     alg.skcipher.base);
11611b44c5a6SAntoine Ténart 
11621eb7b403SOfer Heifetz 	crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm),
11631eb7b403SOfer Heifetz 				    sizeof(struct safexcel_cipher_req));
11641b44c5a6SAntoine Ténart 
11658ac1283eSAntoine Tenart 	ctx->priv = tmpl->priv;
11668ac1283eSAntoine Tenart 
11678ac1283eSAntoine Tenart 	ctx->base.send = safexcel_skcipher_send;
11688ac1283eSAntoine Tenart 	ctx->base.handle_result = safexcel_skcipher_handle_result;
11698ac1283eSAntoine Tenart 	return 0;
11708ac1283eSAntoine Tenart }
11718ac1283eSAntoine Tenart 
11728ac1283eSAntoine Tenart static int safexcel_cipher_cra_exit(struct crypto_tfm *tfm)
11738ac1283eSAntoine Tenart {
11748ac1283eSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
11758ac1283eSAntoine Tenart 
1176ce679559SAntoine Tenart 	memzero_explicit(ctx->key, sizeof(ctx->key));
11778ac1283eSAntoine Tenart 
11788ac1283eSAntoine Tenart 	/* context not allocated, skip invalidation */
11798ac1283eSAntoine Tenart 	if (!ctx->base.ctxr)
11808ac1283eSAntoine Tenart 		return -ENOMEM;
11818ac1283eSAntoine Tenart 
1182ce679559SAntoine Tenart 	memzero_explicit(ctx->base.ctxr->data, sizeof(ctx->base.ctxr->data));
11831b44c5a6SAntoine Ténart 	return 0;
11841b44c5a6SAntoine Ténart }
11851b44c5a6SAntoine Ténart 
11861b44c5a6SAntoine Ténart static void safexcel_skcipher_cra_exit(struct crypto_tfm *tfm)
11871b44c5a6SAntoine Ténart {
11881b44c5a6SAntoine Ténart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
11891b44c5a6SAntoine Ténart 	struct safexcel_crypto_priv *priv = ctx->priv;
11901b44c5a6SAntoine Ténart 	int ret;
11911b44c5a6SAntoine Ténart 
11928ac1283eSAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
11931b44c5a6SAntoine Ténart 		return;
11941b44c5a6SAntoine Ténart 
119553c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
11968ac1283eSAntoine Tenart 		ret = safexcel_skcipher_exit_inv(tfm);
11971b44c5a6SAntoine Ténart 		if (ret)
11988ac1283eSAntoine Tenart 			dev_warn(priv->dev, "skcipher: invalidation error %d\n",
11998ac1283eSAntoine Tenart 				 ret);
1200871df319SAntoine Ténart 	} else {
1201871df319SAntoine Ténart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
1202871df319SAntoine Ténart 			      ctx->base.ctxr_dma);
1203871df319SAntoine Ténart 	}
12041b44c5a6SAntoine Ténart }
12051b44c5a6SAntoine Ténart 
1206f6beaea3SAntoine Tenart static void safexcel_aead_cra_exit(struct crypto_tfm *tfm)
1207f6beaea3SAntoine Tenart {
1208f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1209f6beaea3SAntoine Tenart 	struct safexcel_crypto_priv *priv = ctx->priv;
1210f6beaea3SAntoine Tenart 	int ret;
1211f6beaea3SAntoine Tenart 
1212f6beaea3SAntoine Tenart 	if (safexcel_cipher_cra_exit(tfm))
1213f6beaea3SAntoine Tenart 		return;
1214f6beaea3SAntoine Tenart 
121553c83e91SAntoine Tenart 	if (priv->flags & EIP197_TRC_CACHE) {
1216f6beaea3SAntoine Tenart 		ret = safexcel_aead_exit_inv(tfm);
1217f6beaea3SAntoine Tenart 		if (ret)
1218f6beaea3SAntoine Tenart 			dev_warn(priv->dev, "aead: invalidation error %d\n",
1219f6beaea3SAntoine Tenart 				 ret);
1220f6beaea3SAntoine Tenart 	} else {
1221f6beaea3SAntoine Tenart 		dma_pool_free(priv->context_pool, ctx->base.ctxr,
1222f6beaea3SAntoine Tenart 			      ctx->base.ctxr_dma);
1223f6beaea3SAntoine Tenart 	}
1224f6beaea3SAntoine Tenart }
1225f6beaea3SAntoine Tenart 
122693369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_ecb_cra_init(struct crypto_tfm *tfm)
122793369b5dSPascal van Leeuwen {
122893369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
122993369b5dSPascal van Leeuwen 
123093369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
123193369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
123293369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
123393369b5dSPascal van Leeuwen 	return 0;
123493369b5dSPascal van Leeuwen }
123593369b5dSPascal van Leeuwen 
12361b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_ecb_aes = {
12371b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1238062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
12391b44c5a6SAntoine Ténart 	.alg.skcipher = {
12408ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
124193369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
124293369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
12431b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
12441b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
12451b44c5a6SAntoine Ténart 		.base = {
12461b44c5a6SAntoine Ténart 			.cra_name = "ecb(aes)",
12471b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-ecb-aes",
1248aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
12492c95e6d9SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
12501b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
12511b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
12521b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
12531b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
125493369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ecb_cra_init,
12551b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
12561b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
12571b44c5a6SAntoine Ténart 		},
12581b44c5a6SAntoine Ténart 	},
12591b44c5a6SAntoine Ténart };
12601b44c5a6SAntoine Ténart 
126193369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_cbc_cra_init(struct crypto_tfm *tfm)
12621b44c5a6SAntoine Ténart {
126393369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
12641b44c5a6SAntoine Ténart 
126593369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
126693369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
126793369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
126893369b5dSPascal van Leeuwen 	return 0;
12691b44c5a6SAntoine Ténart }
12701b44c5a6SAntoine Ténart 
12711b44c5a6SAntoine Ténart struct safexcel_alg_template safexcel_alg_cbc_aes = {
12721b44c5a6SAntoine Ténart 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1273062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
12741b44c5a6SAntoine Ténart 	.alg.skcipher = {
12758ac1283eSAntoine Tenart 		.setkey = safexcel_skcipher_aes_setkey,
127693369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
127793369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
12781b44c5a6SAntoine Ténart 		.min_keysize = AES_MIN_KEY_SIZE,
12791b44c5a6SAntoine Ténart 		.max_keysize = AES_MAX_KEY_SIZE,
12801b44c5a6SAntoine Ténart 		.ivsize = AES_BLOCK_SIZE,
12811b44c5a6SAntoine Ténart 		.base = {
12821b44c5a6SAntoine Ténart 			.cra_name = "cbc(aes)",
12831b44c5a6SAntoine Ténart 			.cra_driver_name = "safexcel-cbc-aes",
1284aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
12852c95e6d9SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
12861b44c5a6SAntoine Ténart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
12871b44c5a6SAntoine Ténart 			.cra_blocksize = AES_BLOCK_SIZE,
12881b44c5a6SAntoine Ténart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
12891b44c5a6SAntoine Ténart 			.cra_alignmask = 0,
129093369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_cbc_cra_init,
12911b44c5a6SAntoine Ténart 			.cra_exit = safexcel_skcipher_cra_exit,
12921b44c5a6SAntoine Ténart 			.cra_module = THIS_MODULE,
12931b44c5a6SAntoine Ténart 		},
12941b44c5a6SAntoine Ténart 	},
12951b44c5a6SAntoine Ténart };
1296f6beaea3SAntoine Tenart 
129748e97afaSPascal van Leeuwen static int safexcel_skcipher_aes_cfb_cra_init(struct crypto_tfm *tfm)
129848e97afaSPascal van Leeuwen {
129948e97afaSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
130048e97afaSPascal van Leeuwen 
130148e97afaSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
130248e97afaSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
130348e97afaSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB;
130448e97afaSPascal van Leeuwen 	return 0;
130548e97afaSPascal van Leeuwen }
130648e97afaSPascal van Leeuwen 
130748e97afaSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cfb_aes = {
130848e97afaSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
130948e97afaSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XFB,
131048e97afaSPascal van Leeuwen 	.alg.skcipher = {
131148e97afaSPascal van Leeuwen 		.setkey = safexcel_skcipher_aes_setkey,
131248e97afaSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
131348e97afaSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
131448e97afaSPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE,
131548e97afaSPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE,
131648e97afaSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
131748e97afaSPascal van Leeuwen 		.base = {
131848e97afaSPascal van Leeuwen 			.cra_name = "cfb(aes)",
131948e97afaSPascal van Leeuwen 			.cra_driver_name = "safexcel-cfb-aes",
132048e97afaSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
132148e97afaSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
132248e97afaSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
132348e97afaSPascal van Leeuwen 			.cra_blocksize = 1,
132448e97afaSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
132548e97afaSPascal van Leeuwen 			.cra_alignmask = 0,
132648e97afaSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_cfb_cra_init,
132748e97afaSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
132848e97afaSPascal van Leeuwen 			.cra_module = THIS_MODULE,
132948e97afaSPascal van Leeuwen 		},
133048e97afaSPascal van Leeuwen 	},
133148e97afaSPascal van Leeuwen };
133248e97afaSPascal van Leeuwen 
133350485dfbSPascal van Leeuwen static int safexcel_skcipher_aes_ofb_cra_init(struct crypto_tfm *tfm)
133450485dfbSPascal van Leeuwen {
133550485dfbSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
133650485dfbSPascal van Leeuwen 
133750485dfbSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
133850485dfbSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
133950485dfbSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB;
134050485dfbSPascal van Leeuwen 	return 0;
134150485dfbSPascal van Leeuwen }
134250485dfbSPascal van Leeuwen 
134350485dfbSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ofb_aes = {
134450485dfbSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
134550485dfbSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XFB,
134650485dfbSPascal van Leeuwen 	.alg.skcipher = {
134750485dfbSPascal van Leeuwen 		.setkey = safexcel_skcipher_aes_setkey,
134850485dfbSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
134950485dfbSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
135050485dfbSPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE,
135150485dfbSPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE,
135250485dfbSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
135350485dfbSPascal van Leeuwen 		.base = {
135450485dfbSPascal van Leeuwen 			.cra_name = "ofb(aes)",
135550485dfbSPascal van Leeuwen 			.cra_driver_name = "safexcel-ofb-aes",
135650485dfbSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
135750485dfbSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
135850485dfbSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
135950485dfbSPascal van Leeuwen 			.cra_blocksize = 1,
136050485dfbSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
136150485dfbSPascal van Leeuwen 			.cra_alignmask = 0,
136250485dfbSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ofb_cra_init,
136350485dfbSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
136450485dfbSPascal van Leeuwen 			.cra_module = THIS_MODULE,
136550485dfbSPascal van Leeuwen 		},
136650485dfbSPascal van Leeuwen 	},
136750485dfbSPascal van Leeuwen };
136850485dfbSPascal van Leeuwen 
136954f9e8faSPascal van Leeuwen static int safexcel_skcipher_aesctr_setkey(struct crypto_skcipher *ctfm,
137054f9e8faSPascal van Leeuwen 					   const u8 *key, unsigned int len)
137154f9e8faSPascal van Leeuwen {
137254f9e8faSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
137354f9e8faSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
137454f9e8faSPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
137554f9e8faSPascal van Leeuwen 	struct crypto_aes_ctx aes;
137654f9e8faSPascal van Leeuwen 	int ret, i;
137754f9e8faSPascal van Leeuwen 	unsigned int keylen;
137854f9e8faSPascal van Leeuwen 
137954f9e8faSPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
1380f26882a3SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
138154f9e8faSPascal van Leeuwen 	/* exclude the nonce here */
1382f26882a3SPascal van Leeuwen 	keylen = len - CTR_RFC3686_NONCE_SIZE;
138354f9e8faSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, keylen);
138454f9e8faSPascal van Leeuwen 	if (ret) {
138554f9e8faSPascal van Leeuwen 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
138654f9e8faSPascal van Leeuwen 		return ret;
138754f9e8faSPascal van Leeuwen 	}
138854f9e8faSPascal van Leeuwen 
138954f9e8faSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
139054f9e8faSPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
139113a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
139254f9e8faSPascal van Leeuwen 				ctx->base.needs_inv = true;
139354f9e8faSPascal van Leeuwen 				break;
139454f9e8faSPascal van Leeuwen 			}
139554f9e8faSPascal van Leeuwen 		}
139654f9e8faSPascal van Leeuwen 	}
139754f9e8faSPascal van Leeuwen 
139854f9e8faSPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
139954f9e8faSPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
140054f9e8faSPascal van Leeuwen 
140154f9e8faSPascal van Leeuwen 	ctx->key_len = keylen;
140254f9e8faSPascal van Leeuwen 
140354f9e8faSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
140454f9e8faSPascal van Leeuwen 	return 0;
140554f9e8faSPascal van Leeuwen }
140654f9e8faSPascal van Leeuwen 
140793369b5dSPascal van Leeuwen static int safexcel_skcipher_aes_ctr_cra_init(struct crypto_tfm *tfm)
140893369b5dSPascal van Leeuwen {
140993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
141093369b5dSPascal van Leeuwen 
141193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
141293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
141393369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
141493369b5dSPascal van Leeuwen 	return 0;
141593369b5dSPascal van Leeuwen }
141693369b5dSPascal van Leeuwen 
141754f9e8faSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ctr_aes = {
141854f9e8faSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1419062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES,
142054f9e8faSPascal van Leeuwen 	.alg.skcipher = {
142154f9e8faSPascal van Leeuwen 		.setkey = safexcel_skcipher_aesctr_setkey,
142293369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
142393369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1424f26882a3SPascal van Leeuwen 		/* Add nonce size */
1425f26882a3SPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
1426f26882a3SPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
1427f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
142854f9e8faSPascal van Leeuwen 		.base = {
142954f9e8faSPascal van Leeuwen 			.cra_name = "rfc3686(ctr(aes))",
143054f9e8faSPascal van Leeuwen 			.cra_driver_name = "safexcel-ctr-aes",
1431aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
143254f9e8faSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
143354f9e8faSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
143454f9e8faSPascal van Leeuwen 			.cra_blocksize = 1,
143554f9e8faSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
143654f9e8faSPascal van Leeuwen 			.cra_alignmask = 0,
143793369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_ctr_cra_init,
143854f9e8faSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
143954f9e8faSPascal van Leeuwen 			.cra_module = THIS_MODULE,
144054f9e8faSPascal van Leeuwen 		},
144154f9e8faSPascal van Leeuwen 	},
144254f9e8faSPascal van Leeuwen };
144354f9e8faSPascal van Leeuwen 
1444a7dea8c0SOfer Heifetz static int safexcel_des_setkey(struct crypto_skcipher *ctfm, const u8 *key,
1445a7dea8c0SOfer Heifetz 			       unsigned int len)
1446a7dea8c0SOfer Heifetz {
144721f5a15eSArd Biesheuvel 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
1448a7dea8c0SOfer Heifetz 	int ret;
1449a7dea8c0SOfer Heifetz 
145021f5a15eSArd Biesheuvel 	ret = verify_skcipher_des_key(ctfm, key);
145121f5a15eSArd Biesheuvel 	if (ret)
145221f5a15eSArd Biesheuvel 		return ret;
1453a7dea8c0SOfer Heifetz 
1454a7dea8c0SOfer Heifetz 	/* if context exits and key changed, need to invalidate it */
1455a7dea8c0SOfer Heifetz 	if (ctx->base.ctxr_dma)
1456a7dea8c0SOfer Heifetz 		if (memcmp(ctx->key, key, len))
1457a7dea8c0SOfer Heifetz 			ctx->base.needs_inv = true;
1458a7dea8c0SOfer Heifetz 
1459a7dea8c0SOfer Heifetz 	memcpy(ctx->key, key, len);
1460a7dea8c0SOfer Heifetz 	ctx->key_len = len;
1461a7dea8c0SOfer Heifetz 
1462a7dea8c0SOfer Heifetz 	return 0;
1463a7dea8c0SOfer Heifetz }
1464a7dea8c0SOfer Heifetz 
146593369b5dSPascal van Leeuwen static int safexcel_skcipher_des_cbc_cra_init(struct crypto_tfm *tfm)
146693369b5dSPascal van Leeuwen {
146793369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
146893369b5dSPascal van Leeuwen 
146993369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
147093369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_DES;
147193369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
147293369b5dSPascal van Leeuwen 	return 0;
147393369b5dSPascal van Leeuwen }
147493369b5dSPascal van Leeuwen 
1475a7dea8c0SOfer Heifetz struct safexcel_alg_template safexcel_alg_cbc_des = {
1476a7dea8c0SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1477062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
1478a7dea8c0SOfer Heifetz 	.alg.skcipher = {
1479a7dea8c0SOfer Heifetz 		.setkey = safexcel_des_setkey,
148093369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
148193369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1482a7dea8c0SOfer Heifetz 		.min_keysize = DES_KEY_SIZE,
1483a7dea8c0SOfer Heifetz 		.max_keysize = DES_KEY_SIZE,
1484a7dea8c0SOfer Heifetz 		.ivsize = DES_BLOCK_SIZE,
1485a7dea8c0SOfer Heifetz 		.base = {
1486a7dea8c0SOfer Heifetz 			.cra_name = "cbc(des)",
1487a7dea8c0SOfer Heifetz 			.cra_driver_name = "safexcel-cbc-des",
1488aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
14892b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1490a7dea8c0SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1491a7dea8c0SOfer Heifetz 			.cra_blocksize = DES_BLOCK_SIZE,
1492a7dea8c0SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1493a7dea8c0SOfer Heifetz 			.cra_alignmask = 0,
149493369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des_cbc_cra_init,
1495a7dea8c0SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
1496a7dea8c0SOfer Heifetz 			.cra_module = THIS_MODULE,
1497a7dea8c0SOfer Heifetz 		},
1498a7dea8c0SOfer Heifetz 	},
1499a7dea8c0SOfer Heifetz };
1500a7dea8c0SOfer Heifetz 
150193369b5dSPascal van Leeuwen static int safexcel_skcipher_des_ecb_cra_init(struct crypto_tfm *tfm)
1502a7dea8c0SOfer Heifetz {
150393369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1504a7dea8c0SOfer Heifetz 
150593369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
150693369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_DES;
150793369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
150893369b5dSPascal van Leeuwen 	return 0;
1509a7dea8c0SOfer Heifetz }
1510a7dea8c0SOfer Heifetz 
1511a7dea8c0SOfer Heifetz struct safexcel_alg_template safexcel_alg_ecb_des = {
1512a7dea8c0SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1513062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
1514a7dea8c0SOfer Heifetz 	.alg.skcipher = {
1515a7dea8c0SOfer Heifetz 		.setkey = safexcel_des_setkey,
151693369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
151793369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
1518a7dea8c0SOfer Heifetz 		.min_keysize = DES_KEY_SIZE,
1519a7dea8c0SOfer Heifetz 		.max_keysize = DES_KEY_SIZE,
1520a7dea8c0SOfer Heifetz 		.base = {
1521a7dea8c0SOfer Heifetz 			.cra_name = "ecb(des)",
1522a7dea8c0SOfer Heifetz 			.cra_driver_name = "safexcel-ecb-des",
1523aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
15242b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1525a7dea8c0SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1526a7dea8c0SOfer Heifetz 			.cra_blocksize = DES_BLOCK_SIZE,
1527a7dea8c0SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1528a7dea8c0SOfer Heifetz 			.cra_alignmask = 0,
152993369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des_ecb_cra_init,
1530a7dea8c0SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
1531a7dea8c0SOfer Heifetz 			.cra_module = THIS_MODULE,
1532a7dea8c0SOfer Heifetz 		},
1533a7dea8c0SOfer Heifetz 	},
1534a7dea8c0SOfer Heifetz };
153562469879SOfer Heifetz 
153662469879SOfer Heifetz static int safexcel_des3_ede_setkey(struct crypto_skcipher *ctfm,
153762469879SOfer Heifetz 				   const u8 *key, unsigned int len)
153862469879SOfer Heifetz {
153967ac62bfSHerbert Xu 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
154067ac62bfSHerbert Xu 	int err;
154162469879SOfer Heifetz 
154221f5a15eSArd Biesheuvel 	err = verify_skcipher_des3_key(ctfm, key);
154321f5a15eSArd Biesheuvel 	if (err)
154467ac62bfSHerbert Xu 		return err;
154562469879SOfer Heifetz 
154662469879SOfer Heifetz 	/* if context exits and key changed, need to invalidate it */
154713a1bb93SPascal van Leeuwen 	if (ctx->base.ctxr_dma)
154862469879SOfer Heifetz 		if (memcmp(ctx->key, key, len))
154962469879SOfer Heifetz 			ctx->base.needs_inv = true;
155062469879SOfer Heifetz 
155162469879SOfer Heifetz 	memcpy(ctx->key, key, len);
155262469879SOfer Heifetz 	ctx->key_len = len;
155362469879SOfer Heifetz 
155462469879SOfer Heifetz 	return 0;
155562469879SOfer Heifetz }
155662469879SOfer Heifetz 
155793369b5dSPascal van Leeuwen static int safexcel_skcipher_des3_cbc_cra_init(struct crypto_tfm *tfm)
155893369b5dSPascal van Leeuwen {
155993369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
156093369b5dSPascal van Leeuwen 
156193369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
156293369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_3DES;
156393369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
156493369b5dSPascal van Leeuwen 	return 0;
156593369b5dSPascal van Leeuwen }
156693369b5dSPascal van Leeuwen 
156762469879SOfer Heifetz struct safexcel_alg_template safexcel_alg_cbc_des3_ede = {
156862469879SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1569062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
157062469879SOfer Heifetz 	.alg.skcipher = {
157162469879SOfer Heifetz 		.setkey = safexcel_des3_ede_setkey,
157293369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
157393369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
157462469879SOfer Heifetz 		.min_keysize = DES3_EDE_KEY_SIZE,
157562469879SOfer Heifetz 		.max_keysize = DES3_EDE_KEY_SIZE,
157662469879SOfer Heifetz 		.ivsize = DES3_EDE_BLOCK_SIZE,
157762469879SOfer Heifetz 		.base = {
157862469879SOfer Heifetz 			.cra_name = "cbc(des3_ede)",
157962469879SOfer Heifetz 			.cra_driver_name = "safexcel-cbc-des3_ede",
1580aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
15812b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
158262469879SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
158362469879SOfer Heifetz 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
158462469879SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
158562469879SOfer Heifetz 			.cra_alignmask = 0,
158693369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des3_cbc_cra_init,
158762469879SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
158862469879SOfer Heifetz 			.cra_module = THIS_MODULE,
158962469879SOfer Heifetz 		},
159062469879SOfer Heifetz 	},
159162469879SOfer Heifetz };
159262469879SOfer Heifetz 
159393369b5dSPascal van Leeuwen static int safexcel_skcipher_des3_ecb_cra_init(struct crypto_tfm *tfm)
159462469879SOfer Heifetz {
159593369b5dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
159662469879SOfer Heifetz 
159793369b5dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
159893369b5dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_3DES;
159993369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
160093369b5dSPascal van Leeuwen 	return 0;
160162469879SOfer Heifetz }
160262469879SOfer Heifetz 
160362469879SOfer Heifetz struct safexcel_alg_template safexcel_alg_ecb_des3_ede = {
160462469879SOfer Heifetz 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
1605062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES,
160662469879SOfer Heifetz 	.alg.skcipher = {
160762469879SOfer Heifetz 		.setkey = safexcel_des3_ede_setkey,
160893369b5dSPascal van Leeuwen 		.encrypt = safexcel_encrypt,
160993369b5dSPascal van Leeuwen 		.decrypt = safexcel_decrypt,
161062469879SOfer Heifetz 		.min_keysize = DES3_EDE_KEY_SIZE,
161162469879SOfer Heifetz 		.max_keysize = DES3_EDE_KEY_SIZE,
161262469879SOfer Heifetz 		.base = {
161362469879SOfer Heifetz 			.cra_name = "ecb(des3_ede)",
161462469879SOfer Heifetz 			.cra_driver_name = "safexcel-ecb-des3_ede",
1615aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
16162b78aeb3SEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
161762469879SOfer Heifetz 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
161862469879SOfer Heifetz 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
161962469879SOfer Heifetz 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
162062469879SOfer Heifetz 			.cra_alignmask = 0,
162193369b5dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_des3_ecb_cra_init,
162262469879SOfer Heifetz 			.cra_exit = safexcel_skcipher_cra_exit,
162362469879SOfer Heifetz 			.cra_module = THIS_MODULE,
162462469879SOfer Heifetz 		},
162562469879SOfer Heifetz 	},
162662469879SOfer Heifetz };
162762469879SOfer Heifetz 
162893369b5dSPascal van Leeuwen static int safexcel_aead_encrypt(struct aead_request *req)
1629f6beaea3SAntoine Tenart {
1630f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
1631f6beaea3SAntoine Tenart 
163293369b5dSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
1633f6beaea3SAntoine Tenart }
1634f6beaea3SAntoine Tenart 
163593369b5dSPascal van Leeuwen static int safexcel_aead_decrypt(struct aead_request *req)
1636f6beaea3SAntoine Tenart {
1637f6beaea3SAntoine Tenart 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
1638f6beaea3SAntoine Tenart 
163993369b5dSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
1640f6beaea3SAntoine Tenart }
1641f6beaea3SAntoine Tenart 
1642f6beaea3SAntoine Tenart static int safexcel_aead_cra_init(struct crypto_tfm *tfm)
1643f6beaea3SAntoine Tenart {
1644f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1645f6beaea3SAntoine Tenart 	struct safexcel_alg_template *tmpl =
1646f6beaea3SAntoine Tenart 		container_of(tfm->__crt_alg, struct safexcel_alg_template,
1647f6beaea3SAntoine Tenart 			     alg.aead.base);
1648f6beaea3SAntoine Tenart 
1649f6beaea3SAntoine Tenart 	crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
1650f6beaea3SAntoine Tenart 				sizeof(struct safexcel_cipher_req));
1651f6beaea3SAntoine Tenart 
1652f6beaea3SAntoine Tenart 	ctx->priv = tmpl->priv;
1653f6beaea3SAntoine Tenart 
16540e17e362SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES; /* default */
165593369b5dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; /* default */
1656f6beaea3SAntoine Tenart 	ctx->aead = true;
1657f6beaea3SAntoine Tenart 	ctx->base.send = safexcel_aead_send;
1658f6beaea3SAntoine Tenart 	ctx->base.handle_result = safexcel_aead_handle_result;
1659f6beaea3SAntoine Tenart 	return 0;
1660f6beaea3SAntoine Tenart }
1661f6beaea3SAntoine Tenart 
166201ba061dSAntoine Tenart static int safexcel_aead_sha1_cra_init(struct crypto_tfm *tfm)
166301ba061dSAntoine Tenart {
166401ba061dSAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
166501ba061dSAntoine Tenart 
166601ba061dSAntoine Tenart 	safexcel_aead_cra_init(tfm);
1667a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
166801ba061dSAntoine Tenart 	ctx->state_sz = SHA1_DIGEST_SIZE;
166901ba061dSAntoine Tenart 	return 0;
167001ba061dSAntoine Tenart }
167101ba061dSAntoine Tenart 
167201ba061dSAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_aes = {
167301ba061dSAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1674062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA1,
167501ba061dSAntoine Tenart 	.alg.aead = {
167677cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
167793369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
167893369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
167901ba061dSAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
168001ba061dSAntoine Tenart 		.maxauthsize = SHA1_DIGEST_SIZE,
168101ba061dSAntoine Tenart 		.base = {
168201ba061dSAntoine Tenart 			.cra_name = "authenc(hmac(sha1),cbc(aes))",
168301ba061dSAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-aes",
1684aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
16853f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
168601ba061dSAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
168701ba061dSAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
168801ba061dSAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
168901ba061dSAntoine Tenart 			.cra_alignmask = 0,
169001ba061dSAntoine Tenart 			.cra_init = safexcel_aead_sha1_cra_init,
169101ba061dSAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
169201ba061dSAntoine Tenart 			.cra_module = THIS_MODULE,
169301ba061dSAntoine Tenart 		},
169401ba061dSAntoine Tenart 	},
169501ba061dSAntoine Tenart };
169601ba061dSAntoine Tenart 
1697f6beaea3SAntoine Tenart static int safexcel_aead_sha256_cra_init(struct crypto_tfm *tfm)
1698f6beaea3SAntoine Tenart {
1699f6beaea3SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1700f6beaea3SAntoine Tenart 
1701f6beaea3SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1702a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256;
1703f6beaea3SAntoine Tenart 	ctx->state_sz = SHA256_DIGEST_SIZE;
1704f6beaea3SAntoine Tenart 	return 0;
1705f6beaea3SAntoine Tenart }
1706f6beaea3SAntoine Tenart 
1707f6beaea3SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_aes = {
1708f6beaea3SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1709062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
1710f6beaea3SAntoine Tenart 	.alg.aead = {
171177cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
171293369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
171393369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1714f6beaea3SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1715f6beaea3SAntoine Tenart 		.maxauthsize = SHA256_DIGEST_SIZE,
1716f6beaea3SAntoine Tenart 		.base = {
1717f6beaea3SAntoine Tenart 			.cra_name = "authenc(hmac(sha256),cbc(aes))",
1718f6beaea3SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-aes",
1719aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
17203f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1721f6beaea3SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1722f6beaea3SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1723f6beaea3SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1724f6beaea3SAntoine Tenart 			.cra_alignmask = 0,
1725f6beaea3SAntoine Tenart 			.cra_init = safexcel_aead_sha256_cra_init,
1726f6beaea3SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1727f6beaea3SAntoine Tenart 			.cra_module = THIS_MODULE,
1728f6beaea3SAntoine Tenart 		},
1729f6beaea3SAntoine Tenart 	},
1730f6beaea3SAntoine Tenart };
1731678b2878SAntoine Tenart 
1732678b2878SAntoine Tenart static int safexcel_aead_sha224_cra_init(struct crypto_tfm *tfm)
1733678b2878SAntoine Tenart {
1734678b2878SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1735678b2878SAntoine Tenart 
1736678b2878SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1737a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224;
1738678b2878SAntoine Tenart 	ctx->state_sz = SHA256_DIGEST_SIZE;
1739678b2878SAntoine Tenart 	return 0;
1740678b2878SAntoine Tenart }
1741678b2878SAntoine Tenart 
1742678b2878SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_aes = {
1743678b2878SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1744062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
1745678b2878SAntoine Tenart 	.alg.aead = {
174677cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
174793369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
174893369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1749678b2878SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1750678b2878SAntoine Tenart 		.maxauthsize = SHA224_DIGEST_SIZE,
1751678b2878SAntoine Tenart 		.base = {
1752678b2878SAntoine Tenart 			.cra_name = "authenc(hmac(sha224),cbc(aes))",
1753678b2878SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-aes",
1754aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
17553f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1756678b2878SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1757678b2878SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1758678b2878SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1759678b2878SAntoine Tenart 			.cra_alignmask = 0,
1760678b2878SAntoine Tenart 			.cra_init = safexcel_aead_sha224_cra_init,
1761678b2878SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1762678b2878SAntoine Tenart 			.cra_module = THIS_MODULE,
1763678b2878SAntoine Tenart 		},
1764678b2878SAntoine Tenart 	},
1765678b2878SAntoine Tenart };
176687eee125SAntoine Tenart 
176787eee125SAntoine Tenart static int safexcel_aead_sha512_cra_init(struct crypto_tfm *tfm)
176887eee125SAntoine Tenart {
176987eee125SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
177087eee125SAntoine Tenart 
177187eee125SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1772a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512;
177387eee125SAntoine Tenart 	ctx->state_sz = SHA512_DIGEST_SIZE;
177487eee125SAntoine Tenart 	return 0;
177587eee125SAntoine Tenart }
177687eee125SAntoine Tenart 
177787eee125SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_aes = {
177887eee125SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1779062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
178087eee125SAntoine Tenart 	.alg.aead = {
178177cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
178293369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
178393369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
178487eee125SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
178587eee125SAntoine Tenart 		.maxauthsize = SHA512_DIGEST_SIZE,
178687eee125SAntoine Tenart 		.base = {
178787eee125SAntoine Tenart 			.cra_name = "authenc(hmac(sha512),cbc(aes))",
178887eee125SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-aes",
1789aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
17903f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
179187eee125SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
179287eee125SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
179387eee125SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
179487eee125SAntoine Tenart 			.cra_alignmask = 0,
179587eee125SAntoine Tenart 			.cra_init = safexcel_aead_sha512_cra_init,
179687eee125SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
179787eee125SAntoine Tenart 			.cra_module = THIS_MODULE,
179887eee125SAntoine Tenart 		},
179987eee125SAntoine Tenart 	},
180087eee125SAntoine Tenart };
1801ea23cb53SAntoine Tenart 
1802ea23cb53SAntoine Tenart static int safexcel_aead_sha384_cra_init(struct crypto_tfm *tfm)
1803ea23cb53SAntoine Tenart {
1804ea23cb53SAntoine Tenart 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1805ea23cb53SAntoine Tenart 
1806ea23cb53SAntoine Tenart 	safexcel_aead_cra_init(tfm);
1807a7dea8c0SOfer Heifetz 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384;
1808ea23cb53SAntoine Tenart 	ctx->state_sz = SHA512_DIGEST_SIZE;
1809ea23cb53SAntoine Tenart 	return 0;
1810ea23cb53SAntoine Tenart }
1811ea23cb53SAntoine Tenart 
1812ea23cb53SAntoine Tenart struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_aes = {
1813ea23cb53SAntoine Tenart 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1814062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
1815ea23cb53SAntoine Tenart 	.alg.aead = {
181677cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
181793369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
181893369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1819ea23cb53SAntoine Tenart 		.ivsize = AES_BLOCK_SIZE,
1820ea23cb53SAntoine Tenart 		.maxauthsize = SHA384_DIGEST_SIZE,
1821ea23cb53SAntoine Tenart 		.base = {
1822ea23cb53SAntoine Tenart 			.cra_name = "authenc(hmac(sha384),cbc(aes))",
1823ea23cb53SAntoine Tenart 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-aes",
1824aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
18253f4a537aSEric Biggers 			.cra_flags = CRYPTO_ALG_ASYNC |
1826ea23cb53SAntoine Tenart 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1827ea23cb53SAntoine Tenart 			.cra_blocksize = AES_BLOCK_SIZE,
1828ea23cb53SAntoine Tenart 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1829ea23cb53SAntoine Tenart 			.cra_alignmask = 0,
1830ea23cb53SAntoine Tenart 			.cra_init = safexcel_aead_sha384_cra_init,
1831ea23cb53SAntoine Tenart 			.cra_exit = safexcel_aead_cra_exit,
1832ea23cb53SAntoine Tenart 			.cra_module = THIS_MODULE,
1833ea23cb53SAntoine Tenart 		},
1834ea23cb53SAntoine Tenart 	},
1835ea23cb53SAntoine Tenart };
183677cdd4efSPascal van Leeuwen 
18370e17e362SPascal van Leeuwen static int safexcel_aead_sha1_des3_cra_init(struct crypto_tfm *tfm)
18380e17e362SPascal van Leeuwen {
18390e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
18400e17e362SPascal van Leeuwen 
18410e17e362SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
18420e17e362SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
18430e17e362SPascal van Leeuwen 	return 0;
18440e17e362SPascal van Leeuwen }
18450e17e362SPascal van Leeuwen 
184677cdd4efSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des3_ede = {
184777cdd4efSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1848062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1,
184977cdd4efSPascal van Leeuwen 	.alg.aead = {
185077cdd4efSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
185193369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
185293369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
185377cdd4efSPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
185477cdd4efSPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
185577cdd4efSPascal van Leeuwen 		.base = {
185677cdd4efSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
185777cdd4efSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des3_ede",
1858aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
185977cdd4efSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
186077cdd4efSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
186177cdd4efSPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
186277cdd4efSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
186377cdd4efSPascal van Leeuwen 			.cra_alignmask = 0,
18640e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_des3_cra_init,
18650e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
18660e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
18670e17e362SPascal van Leeuwen 		},
18680e17e362SPascal van Leeuwen 	},
18690e17e362SPascal van Leeuwen };
18700e17e362SPascal van Leeuwen 
1871f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha256_des3_cra_init(struct crypto_tfm *tfm)
1872f0a8bdf0SPascal van Leeuwen {
1873f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1874f0a8bdf0SPascal van Leeuwen 
1875f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
1876f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1877f0a8bdf0SPascal van Leeuwen 	return 0;
1878f0a8bdf0SPascal van Leeuwen }
1879f0a8bdf0SPascal van Leeuwen 
1880f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des3_ede = {
1881f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1882f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
1883f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
1884f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
1885f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
1886f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1887f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
1888f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
1889f0a8bdf0SPascal van Leeuwen 		.base = {
1890f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
1891f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des3_ede",
1892f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
1893f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1894f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1895f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1896f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1897f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
1898f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_des3_cra_init,
1899f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
1900f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
1901f0a8bdf0SPascal van Leeuwen 		},
1902f0a8bdf0SPascal van Leeuwen 	},
1903f0a8bdf0SPascal van Leeuwen };
1904f0a8bdf0SPascal van Leeuwen 
1905f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha224_des3_cra_init(struct crypto_tfm *tfm)
1906f0a8bdf0SPascal van Leeuwen {
1907f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1908f0a8bdf0SPascal van Leeuwen 
1909f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
1910f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1911f0a8bdf0SPascal van Leeuwen 	return 0;
1912f0a8bdf0SPascal van Leeuwen }
1913f0a8bdf0SPascal van Leeuwen 
1914f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des3_ede = {
1915f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1916f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
1917f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
1918f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
1919f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
1920f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1921f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
1922f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
1923f0a8bdf0SPascal van Leeuwen 		.base = {
1924f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),cbc(des3_ede))",
1925f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des3_ede",
1926f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
1927f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1928f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1929f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1930f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1931f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
1932f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_des3_cra_init,
1933f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
1934f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
1935f0a8bdf0SPascal van Leeuwen 		},
1936f0a8bdf0SPascal van Leeuwen 	},
1937f0a8bdf0SPascal van Leeuwen };
1938f0a8bdf0SPascal van Leeuwen 
1939f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha512_des3_cra_init(struct crypto_tfm *tfm)
1940f0a8bdf0SPascal van Leeuwen {
1941f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1942f0a8bdf0SPascal van Leeuwen 
1943f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
1944f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1945f0a8bdf0SPascal van Leeuwen 	return 0;
1946f0a8bdf0SPascal van Leeuwen }
1947f0a8bdf0SPascal van Leeuwen 
1948f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des3_ede = {
1949f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1950f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
1951f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
1952f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
1953f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
1954f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1955f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
1956f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
1957f0a8bdf0SPascal van Leeuwen 		.base = {
1958f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),cbc(des3_ede))",
1959f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des3_ede",
1960f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
1961f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1962f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1963f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1964f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1965f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
1966f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_des3_cra_init,
1967f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
1968f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
1969f0a8bdf0SPascal van Leeuwen 		},
1970f0a8bdf0SPascal van Leeuwen 	},
1971f0a8bdf0SPascal van Leeuwen };
1972f0a8bdf0SPascal van Leeuwen 
1973f0a8bdf0SPascal van Leeuwen static int safexcel_aead_sha384_des3_cra_init(struct crypto_tfm *tfm)
1974f0a8bdf0SPascal van Leeuwen {
1975f0a8bdf0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
1976f0a8bdf0SPascal van Leeuwen 
1977f0a8bdf0SPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
1978f0a8bdf0SPascal van Leeuwen 	ctx->alg = SAFEXCEL_3DES; /* override default */
1979f0a8bdf0SPascal van Leeuwen 	return 0;
1980f0a8bdf0SPascal van Leeuwen }
1981f0a8bdf0SPascal van Leeuwen 
1982f0a8bdf0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des3_ede = {
1983f0a8bdf0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
1984f0a8bdf0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
1985f0a8bdf0SPascal van Leeuwen 	.alg.aead = {
1986f0a8bdf0SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
1987f0a8bdf0SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
1988f0a8bdf0SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
1989f0a8bdf0SPascal van Leeuwen 		.ivsize = DES3_EDE_BLOCK_SIZE,
1990f0a8bdf0SPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
1991f0a8bdf0SPascal van Leeuwen 		.base = {
1992f0a8bdf0SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),cbc(des3_ede))",
1993f0a8bdf0SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des3_ede",
1994f0a8bdf0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
1995f0a8bdf0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
1996f0a8bdf0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
1997f0a8bdf0SPascal van Leeuwen 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1998f0a8bdf0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
1999f0a8bdf0SPascal van Leeuwen 			.cra_alignmask = 0,
2000f0a8bdf0SPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_des3_cra_init,
2001f0a8bdf0SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2002f0a8bdf0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2003f0a8bdf0SPascal van Leeuwen 		},
2004f0a8bdf0SPascal van Leeuwen 	},
2005f0a8bdf0SPascal van Leeuwen };
2006f0a8bdf0SPascal van Leeuwen 
2007bb7679b8SPascal van Leeuwen static int safexcel_aead_sha1_des_cra_init(struct crypto_tfm *tfm)
2008bb7679b8SPascal van Leeuwen {
2009bb7679b8SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2010bb7679b8SPascal van Leeuwen 
2011bb7679b8SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
2012bb7679b8SPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2013bb7679b8SPascal van Leeuwen 	return 0;
2014bb7679b8SPascal van Leeuwen }
2015bb7679b8SPascal van Leeuwen 
2016bb7679b8SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des = {
2017bb7679b8SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2018bb7679b8SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1,
2019bb7679b8SPascal van Leeuwen 	.alg.aead = {
2020bb7679b8SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2021bb7679b8SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2022bb7679b8SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2023bb7679b8SPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2024bb7679b8SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
2025bb7679b8SPascal van Leeuwen 		.base = {
2026bb7679b8SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(des))",
2027bb7679b8SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des",
2028bb7679b8SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2029bb7679b8SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2030bb7679b8SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2031bb7679b8SPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2032bb7679b8SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2033bb7679b8SPascal van Leeuwen 			.cra_alignmask = 0,
2034bb7679b8SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_des_cra_init,
2035bb7679b8SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2036bb7679b8SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2037bb7679b8SPascal van Leeuwen 		},
2038bb7679b8SPascal van Leeuwen 	},
2039bb7679b8SPascal van Leeuwen };
2040bb7679b8SPascal van Leeuwen 
2041457a6fdfSPascal van Leeuwen static int safexcel_aead_sha256_des_cra_init(struct crypto_tfm *tfm)
2042457a6fdfSPascal van Leeuwen {
2043457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2044457a6fdfSPascal van Leeuwen 
2045457a6fdfSPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
2046457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2047457a6fdfSPascal van Leeuwen 	return 0;
2048457a6fdfSPascal van Leeuwen }
2049457a6fdfSPascal van Leeuwen 
2050457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des = {
2051457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2052457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2053457a6fdfSPascal van Leeuwen 	.alg.aead = {
2054457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2055457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2056457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2057457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2058457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
2059457a6fdfSPascal van Leeuwen 		.base = {
2060457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),cbc(des))",
2061457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des",
2062457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2063457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2064457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2065457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2066457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2067457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2068457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_des_cra_init,
2069457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2070457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2071457a6fdfSPascal van Leeuwen 		},
2072457a6fdfSPascal van Leeuwen 	},
2073457a6fdfSPascal van Leeuwen };
2074457a6fdfSPascal van Leeuwen 
2075457a6fdfSPascal van Leeuwen static int safexcel_aead_sha224_des_cra_init(struct crypto_tfm *tfm)
2076457a6fdfSPascal van Leeuwen {
2077457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2078457a6fdfSPascal van Leeuwen 
2079457a6fdfSPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
2080457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2081457a6fdfSPascal van Leeuwen 	return 0;
2082457a6fdfSPascal van Leeuwen }
2083457a6fdfSPascal van Leeuwen 
2084457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des = {
2085457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2086457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256,
2087457a6fdfSPascal van Leeuwen 	.alg.aead = {
2088457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2089457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2090457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2091457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2092457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
2093457a6fdfSPascal van Leeuwen 		.base = {
2094457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),cbc(des))",
2095457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des",
2096457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2097457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2098457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2099457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2100457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2101457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2102457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_des_cra_init,
2103457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2104457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2105457a6fdfSPascal van Leeuwen 		},
2106457a6fdfSPascal van Leeuwen 	},
2107457a6fdfSPascal van Leeuwen };
2108457a6fdfSPascal van Leeuwen 
2109457a6fdfSPascal van Leeuwen static int safexcel_aead_sha512_des_cra_init(struct crypto_tfm *tfm)
2110457a6fdfSPascal van Leeuwen {
2111457a6fdfSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2112457a6fdfSPascal van Leeuwen 
2113457a6fdfSPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
2114457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2115457a6fdfSPascal van Leeuwen 	return 0;
2116457a6fdfSPascal van Leeuwen }
2117457a6fdfSPascal van Leeuwen 
2118457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des = {
2119457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2120457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2121457a6fdfSPascal van Leeuwen 	.alg.aead = {
2122457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2123457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2124457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2125457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2126457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
2127457a6fdfSPascal van Leeuwen 		.base = {
2128457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),cbc(des))",
2129457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des",
2130457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2131457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2132457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2133457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2134457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2135457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2136457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_des_cra_init,
2137457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2138457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2139457a6fdfSPascal van Leeuwen 		},
2140457a6fdfSPascal van Leeuwen 	},
2141457a6fdfSPascal van Leeuwen };
2142457a6fdfSPascal van Leeuwen 
2143457a6fdfSPascal van Leeuwen static int safexcel_aead_sha384_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_sha384_cra_init(tfm);
2148457a6fdfSPascal van Leeuwen 	ctx->alg = SAFEXCEL_DES; /* override default */
2149457a6fdfSPascal van Leeuwen 	return 0;
2150457a6fdfSPascal van Leeuwen }
2151457a6fdfSPascal van Leeuwen 
2152457a6fdfSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des = {
2153457a6fdfSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2154457a6fdfSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512,
2155457a6fdfSPascal van Leeuwen 	.alg.aead = {
2156457a6fdfSPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
2157457a6fdfSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
2158457a6fdfSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2159457a6fdfSPascal van Leeuwen 		.ivsize = DES_BLOCK_SIZE,
2160457a6fdfSPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
2161457a6fdfSPascal van Leeuwen 		.base = {
2162457a6fdfSPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),cbc(des))",
2163457a6fdfSPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des",
2164457a6fdfSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2165457a6fdfSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2166457a6fdfSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2167457a6fdfSPascal van Leeuwen 			.cra_blocksize = DES_BLOCK_SIZE,
2168457a6fdfSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2169457a6fdfSPascal van Leeuwen 			.cra_alignmask = 0,
2170457a6fdfSPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_des_cra_init,
2171457a6fdfSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
2172457a6fdfSPascal van Leeuwen 			.cra_module = THIS_MODULE,
2173457a6fdfSPascal van Leeuwen 		},
2174457a6fdfSPascal van Leeuwen 	},
2175457a6fdfSPascal van Leeuwen };
2176457a6fdfSPascal van Leeuwen 
21770e17e362SPascal van Leeuwen static int safexcel_aead_sha1_ctr_cra_init(struct crypto_tfm *tfm)
21780e17e362SPascal van Leeuwen {
21790e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
21800e17e362SPascal van Leeuwen 
21810e17e362SPascal van Leeuwen 	safexcel_aead_sha1_cra_init(tfm);
21820e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
21830e17e362SPascal van Leeuwen 	return 0;
21840e17e362SPascal van Leeuwen }
21850e17e362SPascal van Leeuwen 
21860e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_aes = {
21870e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2188062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA1,
21890e17e362SPascal van Leeuwen 	.alg.aead = {
21900e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
219193369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
219293369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2193f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
21940e17e362SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
21950e17e362SPascal van Leeuwen 		.base = {
21960e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
21970e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-aes",
2198aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
21990e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
22000e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
22010e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
22020e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
22030e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
22040e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha1_ctr_cra_init,
22050e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
22060e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
22070e17e362SPascal van Leeuwen 		},
22080e17e362SPascal van Leeuwen 	},
22090e17e362SPascal van Leeuwen };
22100e17e362SPascal van Leeuwen 
22110e17e362SPascal van Leeuwen static int safexcel_aead_sha256_ctr_cra_init(struct crypto_tfm *tfm)
22120e17e362SPascal van Leeuwen {
22130e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
22140e17e362SPascal van Leeuwen 
22150e17e362SPascal van Leeuwen 	safexcel_aead_sha256_cra_init(tfm);
22160e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
22170e17e362SPascal van Leeuwen 	return 0;
22180e17e362SPascal van Leeuwen }
22190e17e362SPascal van Leeuwen 
22200e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_ctr_aes = {
22210e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2222062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
22230e17e362SPascal van Leeuwen 	.alg.aead = {
22240e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
222593369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
222693369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2227f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
22280e17e362SPascal van Leeuwen 		.maxauthsize = SHA256_DIGEST_SIZE,
22290e17e362SPascal van Leeuwen 		.base = {
22300e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
22310e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha256-ctr-aes",
2232aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
22330e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
22340e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
22350e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
22360e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
22370e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
22380e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha256_ctr_cra_init,
22390e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
22400e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
22410e17e362SPascal van Leeuwen 		},
22420e17e362SPascal van Leeuwen 	},
22430e17e362SPascal van Leeuwen };
22440e17e362SPascal van Leeuwen 
22450e17e362SPascal van Leeuwen static int safexcel_aead_sha224_ctr_cra_init(struct crypto_tfm *tfm)
22460e17e362SPascal van Leeuwen {
22470e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
22480e17e362SPascal van Leeuwen 
22490e17e362SPascal van Leeuwen 	safexcel_aead_sha224_cra_init(tfm);
22500e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
22510e17e362SPascal van Leeuwen 	return 0;
22520e17e362SPascal van Leeuwen }
22530e17e362SPascal van Leeuwen 
22540e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_ctr_aes = {
22550e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2256062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_256,
22570e17e362SPascal van Leeuwen 	.alg.aead = {
22580e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
225993369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
226093369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2261f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
22620e17e362SPascal van Leeuwen 		.maxauthsize = SHA224_DIGEST_SIZE,
22630e17e362SPascal van Leeuwen 		.base = {
22640e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))",
22650e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha224-ctr-aes",
2266aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
22670e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
22680e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
22690e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
22700e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
22710e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
22720e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha224_ctr_cra_init,
22730e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
22740e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
22750e17e362SPascal van Leeuwen 		},
22760e17e362SPascal van Leeuwen 	},
22770e17e362SPascal van Leeuwen };
22780e17e362SPascal van Leeuwen 
22790e17e362SPascal van Leeuwen static int safexcel_aead_sha512_ctr_cra_init(struct crypto_tfm *tfm)
22800e17e362SPascal van Leeuwen {
22810e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
22820e17e362SPascal van Leeuwen 
22830e17e362SPascal van Leeuwen 	safexcel_aead_sha512_cra_init(tfm);
22840e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
22850e17e362SPascal van Leeuwen 	return 0;
22860e17e362SPascal van Leeuwen }
22870e17e362SPascal van Leeuwen 
22880e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_ctr_aes = {
22890e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2290062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
22910e17e362SPascal van Leeuwen 	.alg.aead = {
22920e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
229393369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
229493369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2295f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
22960e17e362SPascal van Leeuwen 		.maxauthsize = SHA512_DIGEST_SIZE,
22970e17e362SPascal van Leeuwen 		.base = {
22980e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
22990e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha512-ctr-aes",
2300aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23010e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
23020e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23030e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23040e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23050e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23060e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha512_ctr_cra_init,
23070e17e362SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
23080e17e362SPascal van Leeuwen 			.cra_module = THIS_MODULE,
23090e17e362SPascal van Leeuwen 		},
23100e17e362SPascal van Leeuwen 	},
23110e17e362SPascal van Leeuwen };
23120e17e362SPascal van Leeuwen 
23130e17e362SPascal van Leeuwen static int safexcel_aead_sha384_ctr_cra_init(struct crypto_tfm *tfm)
23140e17e362SPascal van Leeuwen {
23150e17e362SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
23160e17e362SPascal van Leeuwen 
23170e17e362SPascal van Leeuwen 	safexcel_aead_sha384_cra_init(tfm);
23180e17e362SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */
23190e17e362SPascal van Leeuwen 	return 0;
23200e17e362SPascal van Leeuwen }
23210e17e362SPascal van Leeuwen 
23220e17e362SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_ctr_aes = {
23230e17e362SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2324062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_SHA2_512,
23250e17e362SPascal van Leeuwen 	.alg.aead = {
23260e17e362SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
232793369b5dSPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
232893369b5dSPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
2329f26882a3SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
23300e17e362SPascal van Leeuwen 		.maxauthsize = SHA384_DIGEST_SIZE,
23310e17e362SPascal van Leeuwen 		.base = {
23320e17e362SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
23330e17e362SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha384-ctr-aes",
2334aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
23350e17e362SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
23360e17e362SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
23370e17e362SPascal van Leeuwen 			.cra_blocksize = 1,
23380e17e362SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
23390e17e362SPascal van Leeuwen 			.cra_alignmask = 0,
23400e17e362SPascal van Leeuwen 			.cra_init = safexcel_aead_sha384_ctr_cra_init,
234177cdd4efSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
234277cdd4efSPascal van Leeuwen 			.cra_module = THIS_MODULE,
234377cdd4efSPascal van Leeuwen 		},
234477cdd4efSPascal van Leeuwen 	},
234577cdd4efSPascal van Leeuwen };
2346c7da38a7SPascal van Leeuwen 
2347c7da38a7SPascal van Leeuwen static int safexcel_skcipher_aesxts_setkey(struct crypto_skcipher *ctfm,
2348c7da38a7SPascal van Leeuwen 					   const u8 *key, unsigned int len)
2349c7da38a7SPascal van Leeuwen {
2350c7da38a7SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
2351c7da38a7SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2352c7da38a7SPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
2353c7da38a7SPascal van Leeuwen 	struct crypto_aes_ctx aes;
2354c7da38a7SPascal van Leeuwen 	int ret, i;
2355c7da38a7SPascal van Leeuwen 	unsigned int keylen;
2356c7da38a7SPascal van Leeuwen 
2357c7da38a7SPascal van Leeuwen 	/* Check for illegal XTS keys */
2358c7da38a7SPascal van Leeuwen 	ret = xts_verify_key(ctfm, key, len);
2359c7da38a7SPascal van Leeuwen 	if (ret)
2360c7da38a7SPascal van Leeuwen 		return ret;
2361c7da38a7SPascal van Leeuwen 
2362c7da38a7SPascal van Leeuwen 	/* Only half of the key data is cipher key */
2363c7da38a7SPascal van Leeuwen 	keylen = (len >> 1);
2364c7da38a7SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, keylen);
2365c7da38a7SPascal van Leeuwen 	if (ret) {
2366c7da38a7SPascal van Leeuwen 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2367c7da38a7SPascal van Leeuwen 		return ret;
2368c7da38a7SPascal van Leeuwen 	}
2369c7da38a7SPascal van Leeuwen 
2370c7da38a7SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
2371c7da38a7SPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
237213a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
2373c7da38a7SPascal van Leeuwen 				ctx->base.needs_inv = true;
2374c7da38a7SPascal van Leeuwen 				break;
2375c7da38a7SPascal van Leeuwen 			}
2376c7da38a7SPascal van Leeuwen 		}
2377c7da38a7SPascal van Leeuwen 	}
2378c7da38a7SPascal van Leeuwen 
2379c7da38a7SPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
2380c7da38a7SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
2381c7da38a7SPascal van Leeuwen 
2382c7da38a7SPascal van Leeuwen 	/* The other half is the tweak key */
2383c7da38a7SPascal van Leeuwen 	ret = aes_expandkey(&aes, (u8 *)(key + keylen), keylen);
2384c7da38a7SPascal van Leeuwen 	if (ret) {
2385c7da38a7SPascal van Leeuwen 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2386c7da38a7SPascal van Leeuwen 		return ret;
2387c7da38a7SPascal van Leeuwen 	}
2388c7da38a7SPascal van Leeuwen 
2389c7da38a7SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
2390c7da38a7SPascal van Leeuwen 		for (i = 0; i < keylen / sizeof(u32); i++) {
239113a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i + keylen / sizeof(u32)]) !=
239213a1bb93SPascal van Leeuwen 			    aes.key_enc[i]) {
2393c7da38a7SPascal van Leeuwen 				ctx->base.needs_inv = true;
2394c7da38a7SPascal van Leeuwen 				break;
2395c7da38a7SPascal van Leeuwen 			}
2396c7da38a7SPascal van Leeuwen 		}
2397c7da38a7SPascal van Leeuwen 	}
2398c7da38a7SPascal van Leeuwen 
2399c7da38a7SPascal van Leeuwen 	for (i = 0; i < keylen / sizeof(u32); i++)
2400c7da38a7SPascal van Leeuwen 		ctx->key[i + keylen / sizeof(u32)] =
2401c7da38a7SPascal van Leeuwen 			cpu_to_le32(aes.key_enc[i]);
2402c7da38a7SPascal van Leeuwen 
2403c7da38a7SPascal van Leeuwen 	ctx->key_len = keylen << 1;
2404c7da38a7SPascal van Leeuwen 
2405c7da38a7SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
2406c7da38a7SPascal van Leeuwen 	return 0;
2407c7da38a7SPascal van Leeuwen }
2408c7da38a7SPascal van Leeuwen 
2409c7da38a7SPascal van Leeuwen static int safexcel_skcipher_aes_xts_cra_init(struct crypto_tfm *tfm)
2410c7da38a7SPascal van Leeuwen {
2411c7da38a7SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2412c7da38a7SPascal van Leeuwen 
2413c7da38a7SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
2414c7da38a7SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_AES;
2415c7da38a7SPascal van Leeuwen 	ctx->xts  = 1;
2416c7da38a7SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XTS;
2417c7da38a7SPascal van Leeuwen 	return 0;
2418c7da38a7SPascal van Leeuwen }
2419c7da38a7SPascal van Leeuwen 
2420c7da38a7SPascal van Leeuwen static int safexcel_encrypt_xts(struct skcipher_request *req)
2421c7da38a7SPascal van Leeuwen {
2422c7da38a7SPascal van Leeuwen 	if (req->cryptlen < XTS_BLOCK_SIZE)
2423c7da38a7SPascal van Leeuwen 		return -EINVAL;
2424c7da38a7SPascal van Leeuwen 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2425c7da38a7SPascal van Leeuwen 				  SAFEXCEL_ENCRYPT);
2426c7da38a7SPascal van Leeuwen }
2427c7da38a7SPascal van Leeuwen 
2428c7da38a7SPascal van Leeuwen static int safexcel_decrypt_xts(struct skcipher_request *req)
2429c7da38a7SPascal van Leeuwen {
2430c7da38a7SPascal van Leeuwen 	if (req->cryptlen < XTS_BLOCK_SIZE)
2431c7da38a7SPascal van Leeuwen 		return -EINVAL;
2432c7da38a7SPascal van Leeuwen 	return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2433c7da38a7SPascal van Leeuwen 				  SAFEXCEL_DECRYPT);
2434c7da38a7SPascal van Leeuwen }
2435c7da38a7SPascal van Leeuwen 
2436c7da38a7SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_xts_aes = {
2437c7da38a7SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
2438062b64caSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_AES_XTS,
2439c7da38a7SPascal van Leeuwen 	.alg.skcipher = {
2440c7da38a7SPascal van Leeuwen 		.setkey = safexcel_skcipher_aesxts_setkey,
2441c7da38a7SPascal van Leeuwen 		.encrypt = safexcel_encrypt_xts,
2442c7da38a7SPascal van Leeuwen 		.decrypt = safexcel_decrypt_xts,
2443c7da38a7SPascal van Leeuwen 		/* XTS actually uses 2 AES keys glued together */
2444c7da38a7SPascal van Leeuwen 		.min_keysize = AES_MIN_KEY_SIZE * 2,
2445c7da38a7SPascal van Leeuwen 		.max_keysize = AES_MAX_KEY_SIZE * 2,
2446c7da38a7SPascal van Leeuwen 		.ivsize = XTS_BLOCK_SIZE,
2447c7da38a7SPascal van Leeuwen 		.base = {
2448c7da38a7SPascal van Leeuwen 			.cra_name = "xts(aes)",
2449c7da38a7SPascal van Leeuwen 			.cra_driver_name = "safexcel-xts-aes",
2450aa88f331SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
2451c7da38a7SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2452c7da38a7SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
2453c7da38a7SPascal van Leeuwen 			.cra_blocksize = XTS_BLOCK_SIZE,
2454c7da38a7SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2455c7da38a7SPascal van Leeuwen 			.cra_alignmask = 0,
2456c7da38a7SPascal van Leeuwen 			.cra_init = safexcel_skcipher_aes_xts_cra_init,
2457c7da38a7SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
2458c7da38a7SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2459c7da38a7SPascal van Leeuwen 		},
2460c7da38a7SPascal van Leeuwen 	},
2461c7da38a7SPascal van Leeuwen };
24623e450886SPascal van Leeuwen 
24633e450886SPascal van Leeuwen static int safexcel_aead_gcm_setkey(struct crypto_aead *ctfm, const u8 *key,
24643e450886SPascal van Leeuwen 				    unsigned int len)
24653e450886SPascal van Leeuwen {
24663e450886SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
24673e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
24683e450886SPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
24693e450886SPascal van Leeuwen 	struct crypto_aes_ctx aes;
24703e450886SPascal van Leeuwen 	u32 hashkey[AES_BLOCK_SIZE >> 2];
24713e450886SPascal van Leeuwen 	int ret, i;
24723e450886SPascal van Leeuwen 
24733e450886SPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
24743e450886SPascal van Leeuwen 	if (ret) {
24753e450886SPascal van Leeuwen 		crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
24763e450886SPascal van Leeuwen 		memzero_explicit(&aes, sizeof(aes));
24773e450886SPascal van Leeuwen 		return ret;
24783e450886SPascal van Leeuwen 	}
24793e450886SPascal van Leeuwen 
24803e450886SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
24813e450886SPascal van Leeuwen 		for (i = 0; i < len / sizeof(u32); i++) {
248213a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
24833e450886SPascal van Leeuwen 				ctx->base.needs_inv = true;
24843e450886SPascal van Leeuwen 				break;
24853e450886SPascal van Leeuwen 			}
24863e450886SPascal van Leeuwen 		}
24873e450886SPascal van Leeuwen 	}
24883e450886SPascal van Leeuwen 
24893e450886SPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++)
24903e450886SPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
24913e450886SPascal van Leeuwen 
24923e450886SPascal van Leeuwen 	ctx->key_len = len;
24933e450886SPascal van Leeuwen 
24943e450886SPascal van Leeuwen 	/* Compute hash key by encrypting zeroes with cipher key */
24953e450886SPascal van Leeuwen 	crypto_cipher_clear_flags(ctx->hkaes, CRYPTO_TFM_REQ_MASK);
24963e450886SPascal van Leeuwen 	crypto_cipher_set_flags(ctx->hkaes, crypto_aead_get_flags(ctfm) &
24973e450886SPascal van Leeuwen 				CRYPTO_TFM_REQ_MASK);
24983e450886SPascal van Leeuwen 	ret = crypto_cipher_setkey(ctx->hkaes, key, len);
24993e450886SPascal van Leeuwen 	crypto_aead_set_flags(ctfm, crypto_cipher_get_flags(ctx->hkaes) &
25003e450886SPascal van Leeuwen 			      CRYPTO_TFM_RES_MASK);
25013e450886SPascal van Leeuwen 	if (ret)
25023e450886SPascal van Leeuwen 		return ret;
25033e450886SPascal van Leeuwen 
25043e450886SPascal van Leeuwen 	memset(hashkey, 0, AES_BLOCK_SIZE);
25053e450886SPascal van Leeuwen 	crypto_cipher_encrypt_one(ctx->hkaes, (u8 *)hashkey, (u8 *)hashkey);
25063e450886SPascal van Leeuwen 
25073e450886SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
25083e450886SPascal van Leeuwen 		for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) {
250913a1bb93SPascal van Leeuwen 			if (be32_to_cpu(ctx->ipad[i]) != hashkey[i]) {
25103e450886SPascal van Leeuwen 				ctx->base.needs_inv = true;
25113e450886SPascal van Leeuwen 				break;
25123e450886SPascal van Leeuwen 			}
25133e450886SPascal van Leeuwen 		}
25143e450886SPascal van Leeuwen 	}
25153e450886SPascal van Leeuwen 
25163e450886SPascal van Leeuwen 	for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++)
25173e450886SPascal van Leeuwen 		ctx->ipad[i] = cpu_to_be32(hashkey[i]);
25183e450886SPascal van Leeuwen 
25193e450886SPascal van Leeuwen 	memzero_explicit(hashkey, AES_BLOCK_SIZE);
25203e450886SPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
25213e450886SPascal van Leeuwen 	return 0;
25223e450886SPascal van Leeuwen }
25233e450886SPascal van Leeuwen 
25243e450886SPascal van Leeuwen static int safexcel_aead_gcm_cra_init(struct crypto_tfm *tfm)
25253e450886SPascal van Leeuwen {
25263e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
25273e450886SPascal van Leeuwen 
25283e450886SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
25293e450886SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_GHASH;
25303e450886SPascal van Leeuwen 	ctx->state_sz = GHASH_BLOCK_SIZE;
25314eb76fafSPascal van Leeuwen 	ctx->xcm = EIP197_XCM_MODE_GCM;
25323e450886SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */
25333e450886SPascal van Leeuwen 
25343e450886SPascal van Leeuwen 	ctx->hkaes = crypto_alloc_cipher("aes", 0, 0);
25353e450886SPascal van Leeuwen 	if (IS_ERR(ctx->hkaes))
25363e450886SPascal van Leeuwen 		return PTR_ERR(ctx->hkaes);
25373e450886SPascal van Leeuwen 
25383e450886SPascal van Leeuwen 	return 0;
25393e450886SPascal van Leeuwen }
25403e450886SPascal van Leeuwen 
25413e450886SPascal van Leeuwen static void safexcel_aead_gcm_cra_exit(struct crypto_tfm *tfm)
25423e450886SPascal van Leeuwen {
25433e450886SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
25443e450886SPascal van Leeuwen 
25453e450886SPascal van Leeuwen 	crypto_free_cipher(ctx->hkaes);
25463e450886SPascal van Leeuwen 	safexcel_aead_cra_exit(tfm);
25473e450886SPascal van Leeuwen }
25483e450886SPascal van Leeuwen 
25493e450886SPascal van Leeuwen static int safexcel_aead_gcm_setauthsize(struct crypto_aead *tfm,
25503e450886SPascal van Leeuwen 					 unsigned int authsize)
25513e450886SPascal van Leeuwen {
25523e450886SPascal van Leeuwen 	return crypto_gcm_check_authsize(authsize);
25533e450886SPascal van Leeuwen }
25543e450886SPascal van Leeuwen 
25553e450886SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_gcm = {
25563e450886SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
25573e450886SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
25583e450886SPascal van Leeuwen 	.alg.aead = {
25593e450886SPascal van Leeuwen 		.setkey = safexcel_aead_gcm_setkey,
25603e450886SPascal van Leeuwen 		.setauthsize = safexcel_aead_gcm_setauthsize,
25613e450886SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
25623e450886SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
25633e450886SPascal van Leeuwen 		.ivsize = GCM_AES_IV_SIZE,
25643e450886SPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
25653e450886SPascal van Leeuwen 		.base = {
25663e450886SPascal van Leeuwen 			.cra_name = "gcm(aes)",
25673e450886SPascal van Leeuwen 			.cra_driver_name = "safexcel-gcm-aes",
25683e450886SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
25693e450886SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
25703e450886SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
25713e450886SPascal van Leeuwen 			.cra_blocksize = 1,
25723e450886SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
25733e450886SPascal van Leeuwen 			.cra_alignmask = 0,
25743e450886SPascal van Leeuwen 			.cra_init = safexcel_aead_gcm_cra_init,
25753e450886SPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
25763e450886SPascal van Leeuwen 			.cra_module = THIS_MODULE,
25773e450886SPascal van Leeuwen 		},
25783e450886SPascal van Leeuwen 	},
25793e450886SPascal van Leeuwen };
25804eb76fafSPascal van Leeuwen 
25814eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_setkey(struct crypto_aead *ctfm, const u8 *key,
25824eb76fafSPascal van Leeuwen 				    unsigned int len)
25834eb76fafSPascal van Leeuwen {
25844eb76fafSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
25854eb76fafSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
25864eb76fafSPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
25874eb76fafSPascal van Leeuwen 	struct crypto_aes_ctx aes;
25884eb76fafSPascal van Leeuwen 	int ret, i;
25894eb76fafSPascal van Leeuwen 
25904eb76fafSPascal van Leeuwen 	ret = aes_expandkey(&aes, key, len);
25914eb76fafSPascal van Leeuwen 	if (ret) {
25924eb76fafSPascal van Leeuwen 		crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
25934eb76fafSPascal van Leeuwen 		memzero_explicit(&aes, sizeof(aes));
25944eb76fafSPascal van Leeuwen 		return ret;
25954eb76fafSPascal van Leeuwen 	}
25964eb76fafSPascal van Leeuwen 
25974eb76fafSPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) {
25984eb76fafSPascal van Leeuwen 		for (i = 0; i < len / sizeof(u32); i++) {
259913a1bb93SPascal van Leeuwen 			if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) {
26004eb76fafSPascal van Leeuwen 				ctx->base.needs_inv = true;
26014eb76fafSPascal van Leeuwen 				break;
26024eb76fafSPascal van Leeuwen 			}
26034eb76fafSPascal van Leeuwen 		}
26044eb76fafSPascal van Leeuwen 	}
26054eb76fafSPascal van Leeuwen 
26064eb76fafSPascal van Leeuwen 	for (i = 0; i < len / sizeof(u32); i++) {
26074eb76fafSPascal van Leeuwen 		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
26084eb76fafSPascal van Leeuwen 		ctx->ipad[i + 2 * AES_BLOCK_SIZE / sizeof(u32)] =
26094eb76fafSPascal van Leeuwen 			cpu_to_be32(aes.key_enc[i]);
26104eb76fafSPascal van Leeuwen 	}
26114eb76fafSPascal van Leeuwen 
26124eb76fafSPascal van Leeuwen 	ctx->key_len = len;
26134eb76fafSPascal van Leeuwen 	ctx->state_sz = 2 * AES_BLOCK_SIZE + len;
26144eb76fafSPascal van Leeuwen 
26154eb76fafSPascal van Leeuwen 	if (len == AES_KEYSIZE_192)
26164eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192;
26174eb76fafSPascal van Leeuwen 	else if (len == AES_KEYSIZE_256)
26184eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256;
26194eb76fafSPascal van Leeuwen 	else
26204eb76fafSPascal van Leeuwen 		ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
26214eb76fafSPascal van Leeuwen 
26224eb76fafSPascal van Leeuwen 	memzero_explicit(&aes, sizeof(aes));
26234eb76fafSPascal van Leeuwen 	return 0;
26244eb76fafSPascal van Leeuwen }
26254eb76fafSPascal van Leeuwen 
26264eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_cra_init(struct crypto_tfm *tfm)
26274eb76fafSPascal van Leeuwen {
26284eb76fafSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
26294eb76fafSPascal van Leeuwen 
26304eb76fafSPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
26314eb76fafSPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128;
26324eb76fafSPascal van Leeuwen 	ctx->state_sz = 3 * AES_BLOCK_SIZE;
26334eb76fafSPascal van Leeuwen 	ctx->xcm = EIP197_XCM_MODE_CCM;
26344eb76fafSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */
26354eb76fafSPascal van Leeuwen 	return 0;
26364eb76fafSPascal van Leeuwen }
26374eb76fafSPascal van Leeuwen 
26384eb76fafSPascal van Leeuwen static int safexcel_aead_ccm_setauthsize(struct crypto_aead *tfm,
26394eb76fafSPascal van Leeuwen 					 unsigned int authsize)
26404eb76fafSPascal van Leeuwen {
26414eb76fafSPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
26424eb76fafSPascal van Leeuwen 	switch (authsize) {
26434eb76fafSPascal van Leeuwen 	case 4:
26444eb76fafSPascal van Leeuwen 	case 6:
26454eb76fafSPascal van Leeuwen 	case 8:
26464eb76fafSPascal van Leeuwen 	case 10:
26474eb76fafSPascal van Leeuwen 	case 12:
26484eb76fafSPascal van Leeuwen 	case 14:
26494eb76fafSPascal van Leeuwen 	case 16:
26504eb76fafSPascal van Leeuwen 		break;
26514eb76fafSPascal van Leeuwen 	default:
26524eb76fafSPascal van Leeuwen 		return -EINVAL;
26534eb76fafSPascal van Leeuwen 	}
26544eb76fafSPascal van Leeuwen 
26554eb76fafSPascal van Leeuwen 	return 0;
26564eb76fafSPascal van Leeuwen }
26574eb76fafSPascal van Leeuwen 
26584eb76fafSPascal van Leeuwen static int safexcel_ccm_encrypt(struct aead_request *req)
26594eb76fafSPascal van Leeuwen {
26604eb76fafSPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
26614eb76fafSPascal van Leeuwen 
26624eb76fafSPascal van Leeuwen 	if (req->iv[0] < 1 || req->iv[0] > 7)
26634eb76fafSPascal van Leeuwen 		return -EINVAL;
26644eb76fafSPascal van Leeuwen 
26654eb76fafSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
26664eb76fafSPascal van Leeuwen }
26674eb76fafSPascal van Leeuwen 
26684eb76fafSPascal van Leeuwen static int safexcel_ccm_decrypt(struct aead_request *req)
26694eb76fafSPascal van Leeuwen {
26704eb76fafSPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
26714eb76fafSPascal van Leeuwen 
26724eb76fafSPascal van Leeuwen 	if (req->iv[0] < 1 || req->iv[0] > 7)
26734eb76fafSPascal van Leeuwen 		return -EINVAL;
26744eb76fafSPascal van Leeuwen 
26754eb76fafSPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
26764eb76fafSPascal van Leeuwen }
26774eb76fafSPascal van Leeuwen 
26784eb76fafSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ccm = {
26794eb76fafSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
26804eb76fafSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL,
26814eb76fafSPascal van Leeuwen 	.alg.aead = {
26824eb76fafSPascal van Leeuwen 		.setkey = safexcel_aead_ccm_setkey,
26834eb76fafSPascal van Leeuwen 		.setauthsize = safexcel_aead_ccm_setauthsize,
26844eb76fafSPascal van Leeuwen 		.encrypt = safexcel_ccm_encrypt,
26854eb76fafSPascal van Leeuwen 		.decrypt = safexcel_ccm_decrypt,
26864eb76fafSPascal van Leeuwen 		.ivsize = AES_BLOCK_SIZE,
26874eb76fafSPascal van Leeuwen 		.maxauthsize = AES_BLOCK_SIZE,
26884eb76fafSPascal van Leeuwen 		.base = {
26894eb76fafSPascal van Leeuwen 			.cra_name = "ccm(aes)",
26904eb76fafSPascal van Leeuwen 			.cra_driver_name = "safexcel-ccm-aes",
26914eb76fafSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
26924eb76fafSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
26934eb76fafSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
26944eb76fafSPascal van Leeuwen 			.cra_blocksize = 1,
26954eb76fafSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
26964eb76fafSPascal van Leeuwen 			.cra_alignmask = 0,
26974eb76fafSPascal van Leeuwen 			.cra_init = safexcel_aead_ccm_cra_init,
26984eb76fafSPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
26994eb76fafSPascal van Leeuwen 			.cra_module = THIS_MODULE,
27004eb76fafSPascal van Leeuwen 		},
27014eb76fafSPascal van Leeuwen 	},
27024eb76fafSPascal van Leeuwen };
27034a593fb3SPascal van Leeuwen 
2704a6061921SPascal van Leeuwen static void safexcel_chacha20_setkey(struct safexcel_cipher_ctx *ctx,
2705a6061921SPascal van Leeuwen 				     const u8 *key)
27064a593fb3SPascal van Leeuwen {
27074a593fb3SPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
27084a593fb3SPascal van Leeuwen 
270913a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
271013a1bb93SPascal van Leeuwen 		if (memcmp(ctx->key, key, CHACHA_KEY_SIZE))
27114a593fb3SPascal van Leeuwen 			ctx->base.needs_inv = true;
27124a593fb3SPascal van Leeuwen 
271313a1bb93SPascal van Leeuwen 	memcpy(ctx->key, key, CHACHA_KEY_SIZE);
27144a593fb3SPascal van Leeuwen 	ctx->key_len = CHACHA_KEY_SIZE;
2715a6061921SPascal van Leeuwen }
2716a6061921SPascal van Leeuwen 
2717a6061921SPascal van Leeuwen static int safexcel_skcipher_chacha20_setkey(struct crypto_skcipher *ctfm,
2718a6061921SPascal van Leeuwen 					     const u8 *key, unsigned int len)
2719a6061921SPascal van Leeuwen {
2720a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm);
2721a6061921SPascal van Leeuwen 
2722a6061921SPascal van Leeuwen 	if (len != CHACHA_KEY_SIZE) {
2723a6061921SPascal van Leeuwen 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2724a6061921SPascal van Leeuwen 		return -EINVAL;
2725a6061921SPascal van Leeuwen 	}
2726a6061921SPascal van Leeuwen 	safexcel_chacha20_setkey(ctx, key);
27274a593fb3SPascal van Leeuwen 
27284a593fb3SPascal van Leeuwen 	return 0;
27294a593fb3SPascal van Leeuwen }
27304a593fb3SPascal van Leeuwen 
27314a593fb3SPascal van Leeuwen static int safexcel_skcipher_chacha20_cra_init(struct crypto_tfm *tfm)
27324a593fb3SPascal van Leeuwen {
27334a593fb3SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
27344a593fb3SPascal van Leeuwen 
27354a593fb3SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
27364a593fb3SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_CHACHA20;
27374a593fb3SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32;
27384a593fb3SPascal van Leeuwen 	return 0;
27394a593fb3SPascal van Leeuwen }
27404a593fb3SPascal van Leeuwen 
27414a593fb3SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chacha20 = {
27424a593fb3SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
27434a593fb3SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20,
27444a593fb3SPascal van Leeuwen 	.alg.skcipher = {
27454a593fb3SPascal van Leeuwen 		.setkey = safexcel_skcipher_chacha20_setkey,
27464a593fb3SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
27474a593fb3SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
27484a593fb3SPascal van Leeuwen 		.min_keysize = CHACHA_KEY_SIZE,
27494a593fb3SPascal van Leeuwen 		.max_keysize = CHACHA_KEY_SIZE,
27504a593fb3SPascal van Leeuwen 		.ivsize = CHACHA_IV_SIZE,
27514a593fb3SPascal van Leeuwen 		.base = {
27524a593fb3SPascal van Leeuwen 			.cra_name = "chacha20",
27534a593fb3SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20",
27544a593fb3SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
27554a593fb3SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
27564a593fb3SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
27574a593fb3SPascal van Leeuwen 			.cra_blocksize = 1,
27584a593fb3SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
27594a593fb3SPascal van Leeuwen 			.cra_alignmask = 0,
27604a593fb3SPascal van Leeuwen 			.cra_init = safexcel_skcipher_chacha20_cra_init,
27614a593fb3SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
27624a593fb3SPascal van Leeuwen 			.cra_module = THIS_MODULE,
27634a593fb3SPascal van Leeuwen 		},
27644a593fb3SPascal van Leeuwen 	},
27654a593fb3SPascal van Leeuwen };
2766a6061921SPascal van Leeuwen 
2767a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_setkey(struct crypto_aead *ctfm,
2768a6061921SPascal van Leeuwen 				    const u8 *key, unsigned int len)
2769a6061921SPascal van Leeuwen {
2770a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_aead_ctx(ctfm);
2771a6061921SPascal van Leeuwen 
2772a6061921SPascal van Leeuwen 	if (ctx->aead  == EIP197_AEAD_TYPE_IPSEC_ESP &&
2773a6061921SPascal van Leeuwen 	    len > EIP197_AEAD_IPSEC_NONCE_SIZE) {
2774a6061921SPascal van Leeuwen 		/* ESP variant has nonce appended to key */
2775a6061921SPascal van Leeuwen 		len -= EIP197_AEAD_IPSEC_NONCE_SIZE;
2776a6061921SPascal van Leeuwen 		ctx->nonce = *(u32 *)(key + len);
2777a6061921SPascal van Leeuwen 	}
2778a6061921SPascal van Leeuwen 	if (len != CHACHA_KEY_SIZE) {
2779a6061921SPascal van Leeuwen 		crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2780a6061921SPascal van Leeuwen 		return -EINVAL;
2781a6061921SPascal van Leeuwen 	}
2782a6061921SPascal van Leeuwen 	safexcel_chacha20_setkey(ctx, key);
2783a6061921SPascal van Leeuwen 
2784a6061921SPascal van Leeuwen 	return 0;
2785a6061921SPascal van Leeuwen }
2786a6061921SPascal van Leeuwen 
2787a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_setauthsize(struct crypto_aead *tfm,
2788a6061921SPascal van Leeuwen 					 unsigned int authsize)
2789a6061921SPascal van Leeuwen {
2790a6061921SPascal van Leeuwen 	if (authsize != POLY1305_DIGEST_SIZE)
2791a6061921SPascal van Leeuwen 		return -EINVAL;
2792a6061921SPascal van Leeuwen 	return 0;
2793a6061921SPascal van Leeuwen }
2794a6061921SPascal van Leeuwen 
2795a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_crypt(struct aead_request *req,
2796a6061921SPascal van Leeuwen 					  enum safexcel_cipher_direction dir)
2797a6061921SPascal van Leeuwen {
2798a6061921SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
2799a6061921SPascal van Leeuwen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2800a6061921SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
2801a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2802a6061921SPascal van Leeuwen 	struct aead_request *subreq = aead_request_ctx(req);
2803a6061921SPascal van Leeuwen 	u32 key[CHACHA_KEY_SIZE / sizeof(u32) + 1];
280413a1bb93SPascal van Leeuwen 	int ret = 0;
2805a6061921SPascal van Leeuwen 
2806a6061921SPascal van Leeuwen 	/*
2807a6061921SPascal van Leeuwen 	 * Instead of wasting time detecting umpteen silly corner cases,
2808a6061921SPascal van Leeuwen 	 * just dump all "small" requests to the fallback implementation.
2809a6061921SPascal van Leeuwen 	 * HW would not be faster on such small requests anyway.
2810a6061921SPascal van Leeuwen 	 */
2811a6061921SPascal van Leeuwen 	if (likely((ctx->aead != EIP197_AEAD_TYPE_IPSEC_ESP ||
2812a6061921SPascal van Leeuwen 		    req->assoclen >= EIP197_AEAD_IPSEC_IV_SIZE) &&
2813a6061921SPascal van Leeuwen 		   req->cryptlen > POLY1305_DIGEST_SIZE)) {
2814a6061921SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, dir);
2815a6061921SPascal van Leeuwen 	}
2816a6061921SPascal van Leeuwen 
2817a6061921SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
281813a1bb93SPascal van Leeuwen 	memcpy(key, ctx->key, CHACHA_KEY_SIZE);
2819a6061921SPascal van Leeuwen 	if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) {
2820a6061921SPascal van Leeuwen 		/* ESP variant has nonce appended to the key */
2821a6061921SPascal van Leeuwen 		key[CHACHA_KEY_SIZE / sizeof(u32)] = ctx->nonce;
2822a6061921SPascal van Leeuwen 		ret = crypto_aead_setkey(ctx->fback, (u8 *)key,
2823a6061921SPascal van Leeuwen 					 CHACHA_KEY_SIZE +
2824a6061921SPascal van Leeuwen 					 EIP197_AEAD_IPSEC_NONCE_SIZE);
2825a6061921SPascal van Leeuwen 	} else {
2826a6061921SPascal van Leeuwen 		ret = crypto_aead_setkey(ctx->fback, (u8 *)key,
2827a6061921SPascal van Leeuwen 					 CHACHA_KEY_SIZE);
2828a6061921SPascal van Leeuwen 	}
2829a6061921SPascal van Leeuwen 	if (ret) {
2830a6061921SPascal van Leeuwen 		crypto_aead_clear_flags(aead, CRYPTO_TFM_REQ_MASK);
2831a6061921SPascal van Leeuwen 		crypto_aead_set_flags(aead, crypto_aead_get_flags(ctx->fback) &
2832a6061921SPascal van Leeuwen 					    CRYPTO_TFM_REQ_MASK);
2833a6061921SPascal van Leeuwen 		return ret;
2834a6061921SPascal van Leeuwen 	}
2835a6061921SPascal van Leeuwen 
2836a6061921SPascal van Leeuwen 	aead_request_set_tfm(subreq, ctx->fback);
2837a6061921SPascal van Leeuwen 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
2838a6061921SPascal van Leeuwen 				  req->base.data);
2839a6061921SPascal van Leeuwen 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
2840a6061921SPascal van Leeuwen 			       req->iv);
2841a6061921SPascal van Leeuwen 	aead_request_set_ad(subreq, req->assoclen);
2842a6061921SPascal van Leeuwen 
2843a6061921SPascal van Leeuwen 	return (dir ==  SAFEXCEL_ENCRYPT) ?
2844a6061921SPascal van Leeuwen 		crypto_aead_encrypt(subreq) :
2845a6061921SPascal van Leeuwen 		crypto_aead_decrypt(subreq);
2846a6061921SPascal van Leeuwen }
2847a6061921SPascal van Leeuwen 
2848a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_encrypt(struct aead_request *req)
2849a6061921SPascal van Leeuwen {
2850a6061921SPascal van Leeuwen 	return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_ENCRYPT);
2851a6061921SPascal van Leeuwen }
2852a6061921SPascal van Leeuwen 
2853a6061921SPascal van Leeuwen static int safexcel_aead_chachapoly_decrypt(struct aead_request *req)
2854a6061921SPascal van Leeuwen {
2855a6061921SPascal van Leeuwen 	return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_DECRYPT);
2856a6061921SPascal van Leeuwen }
2857a6061921SPascal van Leeuwen 
28581769f704SPascal van Leeuwen static int safexcel_aead_fallback_cra_init(struct crypto_tfm *tfm)
2859a6061921SPascal van Leeuwen {
2860a6061921SPascal van Leeuwen 	struct crypto_aead *aead = __crypto_aead_cast(tfm);
2861a6061921SPascal van Leeuwen 	struct aead_alg *alg = crypto_aead_alg(aead);
2862a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2863a6061921SPascal van Leeuwen 
2864a6061921SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
2865a6061921SPascal van Leeuwen 
2866a6061921SPascal van Leeuwen 	/* Allocate fallback implementation */
2867a6061921SPascal van Leeuwen 	ctx->fback = crypto_alloc_aead(alg->base.cra_name, 0,
2868a6061921SPascal van Leeuwen 				       CRYPTO_ALG_ASYNC |
2869a6061921SPascal van Leeuwen 				       CRYPTO_ALG_NEED_FALLBACK);
2870a6061921SPascal van Leeuwen 	if (IS_ERR(ctx->fback))
2871a6061921SPascal van Leeuwen 		return PTR_ERR(ctx->fback);
2872a6061921SPascal van Leeuwen 
2873a6061921SPascal van Leeuwen 	crypto_aead_set_reqsize(aead, max(sizeof(struct safexcel_cipher_req),
2874a6061921SPascal van Leeuwen 					  sizeof(struct aead_request) +
2875a6061921SPascal van Leeuwen 					  crypto_aead_reqsize(ctx->fback)));
2876a6061921SPascal van Leeuwen 
2877a6061921SPascal van Leeuwen 	return 0;
2878a6061921SPascal van Leeuwen }
2879a6061921SPascal van Leeuwen 
28801769f704SPascal van Leeuwen static int safexcel_aead_chachapoly_cra_init(struct crypto_tfm *tfm)
28811769f704SPascal van Leeuwen {
28821769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
28831769f704SPascal van Leeuwen 
28841769f704SPascal van Leeuwen 	safexcel_aead_fallback_cra_init(tfm);
28851769f704SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_CHACHA20;
28861769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32 |
28871769f704SPascal van Leeuwen 		    CONTEXT_CONTROL_CHACHA20_MODE_CALC_OTK;
28881769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_POLY1305;
28891769f704SPascal van Leeuwen 	ctx->state_sz = 0; /* Precomputed by HW */
28901769f704SPascal van Leeuwen 	return 0;
28911769f704SPascal van Leeuwen }
28921769f704SPascal van Leeuwen 
28931769f704SPascal van Leeuwen static void safexcel_aead_fallback_cra_exit(struct crypto_tfm *tfm)
2894a6061921SPascal van Leeuwen {
2895a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2896a6061921SPascal van Leeuwen 
2897a6061921SPascal van Leeuwen 	crypto_free_aead(ctx->fback);
2898a6061921SPascal van Leeuwen 	safexcel_aead_cra_exit(tfm);
2899a6061921SPascal van Leeuwen }
2900a6061921SPascal van Leeuwen 
2901a6061921SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chachapoly = {
2902a6061921SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2903a6061921SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305,
2904a6061921SPascal van Leeuwen 	.alg.aead = {
2905a6061921SPascal van Leeuwen 		.setkey = safexcel_aead_chachapoly_setkey,
2906a6061921SPascal van Leeuwen 		.setauthsize = safexcel_aead_chachapoly_setauthsize,
2907a6061921SPascal van Leeuwen 		.encrypt = safexcel_aead_chachapoly_encrypt,
2908a6061921SPascal van Leeuwen 		.decrypt = safexcel_aead_chachapoly_decrypt,
2909a6061921SPascal van Leeuwen 		.ivsize = CHACHAPOLY_IV_SIZE,
2910a6061921SPascal van Leeuwen 		.maxauthsize = POLY1305_DIGEST_SIZE,
2911a6061921SPascal van Leeuwen 		.base = {
2912a6061921SPascal van Leeuwen 			.cra_name = "rfc7539(chacha20,poly1305)",
2913a6061921SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20-poly1305",
2914a6061921SPascal van Leeuwen 			/* +1 to put it above HW chacha + SW poly */
2915a6061921SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY + 1,
2916a6061921SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2917a6061921SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
2918a6061921SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
2919a6061921SPascal van Leeuwen 			.cra_blocksize = 1,
2920a6061921SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2921a6061921SPascal van Leeuwen 			.cra_alignmask = 0,
2922a6061921SPascal van Leeuwen 			.cra_init = safexcel_aead_chachapoly_cra_init,
29231769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
2924a6061921SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2925a6061921SPascal van Leeuwen 		},
2926a6061921SPascal van Leeuwen 	},
2927a6061921SPascal van Leeuwen };
2928a6061921SPascal van Leeuwen 
2929a6061921SPascal van Leeuwen static int safexcel_aead_chachapolyesp_cra_init(struct crypto_tfm *tfm)
2930a6061921SPascal van Leeuwen {
2931a6061921SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2932a6061921SPascal van Leeuwen 	int ret;
2933a6061921SPascal van Leeuwen 
2934a6061921SPascal van Leeuwen 	ret = safexcel_aead_chachapoly_cra_init(tfm);
2935a6061921SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
2936a6061921SPascal van Leeuwen 	return ret;
2937a6061921SPascal van Leeuwen }
2938a6061921SPascal van Leeuwen 
2939a6061921SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_chachapoly_esp = {
2940a6061921SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
2941a6061921SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305,
2942a6061921SPascal van Leeuwen 	.alg.aead = {
2943a6061921SPascal van Leeuwen 		.setkey = safexcel_aead_chachapoly_setkey,
2944a6061921SPascal van Leeuwen 		.setauthsize = safexcel_aead_chachapoly_setauthsize,
2945a6061921SPascal van Leeuwen 		.encrypt = safexcel_aead_chachapoly_encrypt,
2946a6061921SPascal van Leeuwen 		.decrypt = safexcel_aead_chachapoly_decrypt,
2947a6061921SPascal van Leeuwen 		.ivsize = CHACHAPOLY_IV_SIZE - EIP197_AEAD_IPSEC_NONCE_SIZE,
2948a6061921SPascal van Leeuwen 		.maxauthsize = POLY1305_DIGEST_SIZE,
2949a6061921SPascal van Leeuwen 		.base = {
2950a6061921SPascal van Leeuwen 			.cra_name = "rfc7539esp(chacha20,poly1305)",
2951a6061921SPascal van Leeuwen 			.cra_driver_name = "safexcel-chacha20-poly1305-esp",
2952a6061921SPascal van Leeuwen 			/* +1 to put it above HW chacha + SW poly */
2953a6061921SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY + 1,
2954a6061921SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
2955a6061921SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
2956a6061921SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
2957a6061921SPascal van Leeuwen 			.cra_blocksize = 1,
2958a6061921SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
2959a6061921SPascal van Leeuwen 			.cra_alignmask = 0,
2960a6061921SPascal van Leeuwen 			.cra_init = safexcel_aead_chachapolyesp_cra_init,
29611769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
2962a6061921SPascal van Leeuwen 			.cra_module = THIS_MODULE,
2963a6061921SPascal van Leeuwen 		},
2964a6061921SPascal van Leeuwen 	},
2965a6061921SPascal van Leeuwen };
2966fcca797dSPascal van Leeuwen 
2967fcca797dSPascal van Leeuwen static int safexcel_skcipher_sm4_setkey(struct crypto_skcipher *ctfm,
2968fcca797dSPascal van Leeuwen 					const u8 *key, unsigned int len)
2969fcca797dSPascal van Leeuwen {
2970fcca797dSPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
2971fcca797dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
2972fcca797dSPascal van Leeuwen 	struct safexcel_crypto_priv *priv = ctx->priv;
2973fcca797dSPascal van Leeuwen 
2974fcca797dSPascal van Leeuwen 	if (len != SM4_KEY_SIZE) {
2975fcca797dSPascal van Leeuwen 		crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2976fcca797dSPascal van Leeuwen 		return -EINVAL;
2977fcca797dSPascal van Leeuwen 	}
2978fcca797dSPascal van Leeuwen 
297913a1bb93SPascal van Leeuwen 	if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma)
298013a1bb93SPascal van Leeuwen 		if (memcmp(ctx->key, key, SM4_KEY_SIZE))
2981fcca797dSPascal van Leeuwen 			ctx->base.needs_inv = true;
2982fcca797dSPascal van Leeuwen 
298313a1bb93SPascal van Leeuwen 	memcpy(ctx->key, key, SM4_KEY_SIZE);
2984fcca797dSPascal van Leeuwen 	ctx->key_len = SM4_KEY_SIZE;
2985fcca797dSPascal van Leeuwen 
2986fcca797dSPascal van Leeuwen 	return 0;
2987fcca797dSPascal van Leeuwen }
2988fcca797dSPascal van Leeuwen 
2989fcca797dSPascal van Leeuwen static int safexcel_sm4_blk_encrypt(struct skcipher_request *req)
2990fcca797dSPascal van Leeuwen {
2991fcca797dSPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
2992fcca797dSPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
2993fcca797dSPascal van Leeuwen 		return -EINVAL;
2994fcca797dSPascal van Leeuwen 	else
2995fcca797dSPascal van Leeuwen 		return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
2996fcca797dSPascal van Leeuwen 					  SAFEXCEL_ENCRYPT);
2997fcca797dSPascal van Leeuwen }
2998fcca797dSPascal van Leeuwen 
2999fcca797dSPascal van Leeuwen static int safexcel_sm4_blk_decrypt(struct skcipher_request *req)
3000fcca797dSPascal van Leeuwen {
3001fcca797dSPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
3002fcca797dSPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
3003fcca797dSPascal van Leeuwen 		return -EINVAL;
3004fcca797dSPascal van Leeuwen 	else
3005fcca797dSPascal van Leeuwen 		return safexcel_queue_req(&req->base, skcipher_request_ctx(req),
3006fcca797dSPascal van Leeuwen 					  SAFEXCEL_DECRYPT);
3007fcca797dSPascal van Leeuwen }
3008fcca797dSPascal van Leeuwen 
3009fcca797dSPascal van Leeuwen static int safexcel_skcipher_sm4_ecb_cra_init(struct crypto_tfm *tfm)
3010fcca797dSPascal van Leeuwen {
3011fcca797dSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3012fcca797dSPascal van Leeuwen 
3013fcca797dSPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
3014fcca797dSPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3015fcca797dSPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB;
3016fcca797dSPascal van Leeuwen 	return 0;
3017fcca797dSPascal van Leeuwen }
3018fcca797dSPascal van Leeuwen 
3019fcca797dSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ecb_sm4 = {
3020fcca797dSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
3021fcca797dSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
3022fcca797dSPascal van Leeuwen 	.alg.skcipher = {
3023fcca797dSPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
3024fcca797dSPascal van Leeuwen 		.encrypt = safexcel_sm4_blk_encrypt,
3025fcca797dSPascal van Leeuwen 		.decrypt = safexcel_sm4_blk_decrypt,
3026fcca797dSPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
3027fcca797dSPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
3028fcca797dSPascal van Leeuwen 		.base = {
3029fcca797dSPascal van Leeuwen 			.cra_name = "ecb(sm4)",
3030fcca797dSPascal van Leeuwen 			.cra_driver_name = "safexcel-ecb-sm4",
3031fcca797dSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3032fcca797dSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3033fcca797dSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3034fcca797dSPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
3035fcca797dSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3036fcca797dSPascal van Leeuwen 			.cra_alignmask = 0,
3037fcca797dSPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ecb_cra_init,
3038fcca797dSPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
3039fcca797dSPascal van Leeuwen 			.cra_module = THIS_MODULE,
3040fcca797dSPascal van Leeuwen 		},
3041fcca797dSPascal van Leeuwen 	},
3042fcca797dSPascal van Leeuwen };
30436f2d1428SPascal van Leeuwen 
30446f2d1428SPascal van Leeuwen static int safexcel_skcipher_sm4_cbc_cra_init(struct crypto_tfm *tfm)
30456f2d1428SPascal van Leeuwen {
30466f2d1428SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
30476f2d1428SPascal van Leeuwen 
30486f2d1428SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
30496f2d1428SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
30506f2d1428SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC;
30516f2d1428SPascal van Leeuwen 	return 0;
30526f2d1428SPascal van Leeuwen }
30536f2d1428SPascal van Leeuwen 
30546f2d1428SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cbc_sm4 = {
30556f2d1428SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
30566f2d1428SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
30576f2d1428SPascal van Leeuwen 	.alg.skcipher = {
30586f2d1428SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
30596f2d1428SPascal van Leeuwen 		.encrypt = safexcel_sm4_blk_encrypt,
30606f2d1428SPascal van Leeuwen 		.decrypt = safexcel_sm4_blk_decrypt,
30616f2d1428SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
30626f2d1428SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
30636f2d1428SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
30646f2d1428SPascal van Leeuwen 		.base = {
30656f2d1428SPascal van Leeuwen 			.cra_name = "cbc(sm4)",
30666f2d1428SPascal van Leeuwen 			.cra_driver_name = "safexcel-cbc-sm4",
30676f2d1428SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
30686f2d1428SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
30696f2d1428SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
30706f2d1428SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
30716f2d1428SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
30726f2d1428SPascal van Leeuwen 			.cra_alignmask = 0,
30736f2d1428SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_cbc_cra_init,
30746f2d1428SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
30756f2d1428SPascal van Leeuwen 			.cra_module = THIS_MODULE,
30766f2d1428SPascal van Leeuwen 		},
30776f2d1428SPascal van Leeuwen 	},
30786f2d1428SPascal van Leeuwen };
307903a6cfb9SPascal van Leeuwen 
308003a6cfb9SPascal van Leeuwen static int safexcel_skcipher_sm4_ofb_cra_init(struct crypto_tfm *tfm)
308103a6cfb9SPascal van Leeuwen {
308203a6cfb9SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
308303a6cfb9SPascal van Leeuwen 
308403a6cfb9SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
308503a6cfb9SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
308603a6cfb9SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB;
308703a6cfb9SPascal van Leeuwen 	return 0;
308803a6cfb9SPascal van Leeuwen }
308903a6cfb9SPascal van Leeuwen 
309003a6cfb9SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ofb_sm4 = {
309103a6cfb9SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
309203a6cfb9SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB,
309303a6cfb9SPascal van Leeuwen 	.alg.skcipher = {
309403a6cfb9SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
309503a6cfb9SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
309603a6cfb9SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
309703a6cfb9SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
309803a6cfb9SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
309903a6cfb9SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
310003a6cfb9SPascal van Leeuwen 		.base = {
310103a6cfb9SPascal van Leeuwen 			.cra_name = "ofb(sm4)",
310203a6cfb9SPascal van Leeuwen 			.cra_driver_name = "safexcel-ofb-sm4",
310303a6cfb9SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
310403a6cfb9SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
310503a6cfb9SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
310603a6cfb9SPascal van Leeuwen 			.cra_blocksize = 1,
310703a6cfb9SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
310803a6cfb9SPascal van Leeuwen 			.cra_alignmask = 0,
310903a6cfb9SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ofb_cra_init,
311003a6cfb9SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
311103a6cfb9SPascal van Leeuwen 			.cra_module = THIS_MODULE,
311203a6cfb9SPascal van Leeuwen 		},
311303a6cfb9SPascal van Leeuwen 	},
311403a6cfb9SPascal van Leeuwen };
31157468ab22SPascal van Leeuwen 
31167468ab22SPascal van Leeuwen static int safexcel_skcipher_sm4_cfb_cra_init(struct crypto_tfm *tfm)
31177468ab22SPascal van Leeuwen {
31187468ab22SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
31197468ab22SPascal van Leeuwen 
31207468ab22SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
31217468ab22SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
31227468ab22SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB;
31237468ab22SPascal van Leeuwen 	return 0;
31247468ab22SPascal van Leeuwen }
31257468ab22SPascal van Leeuwen 
31267468ab22SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_cfb_sm4 = {
31277468ab22SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
31287468ab22SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB,
31297468ab22SPascal van Leeuwen 	.alg.skcipher = {
31307468ab22SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4_setkey,
31317468ab22SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
31327468ab22SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
31337468ab22SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE,
31347468ab22SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE,
31357468ab22SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
31367468ab22SPascal van Leeuwen 		.base = {
31377468ab22SPascal van Leeuwen 			.cra_name = "cfb(sm4)",
31387468ab22SPascal van Leeuwen 			.cra_driver_name = "safexcel-cfb-sm4",
31397468ab22SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
31407468ab22SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
31417468ab22SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
31427468ab22SPascal van Leeuwen 			.cra_blocksize = 1,
31437468ab22SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
31447468ab22SPascal van Leeuwen 			.cra_alignmask = 0,
31457468ab22SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_cfb_cra_init,
31467468ab22SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
31477468ab22SPascal van Leeuwen 			.cra_module = THIS_MODULE,
31487468ab22SPascal van Leeuwen 		},
31497468ab22SPascal van Leeuwen 	},
31507468ab22SPascal van Leeuwen };
3151f77e5dc0SPascal van Leeuwen 
3152f77e5dc0SPascal van Leeuwen static int safexcel_skcipher_sm4ctr_setkey(struct crypto_skcipher *ctfm,
3153f77e5dc0SPascal van Leeuwen 					   const u8 *key, unsigned int len)
3154f77e5dc0SPascal van Leeuwen {
3155f77e5dc0SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
3156f77e5dc0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3157f77e5dc0SPascal van Leeuwen 
3158f77e5dc0SPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
3159f77e5dc0SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
3160f77e5dc0SPascal van Leeuwen 	/* exclude the nonce here */
3161f77e5dc0SPascal van Leeuwen 	len -= CTR_RFC3686_NONCE_SIZE;
3162f77e5dc0SPascal van Leeuwen 
3163f77e5dc0SPascal van Leeuwen 	return safexcel_skcipher_sm4_setkey(ctfm, key, len);
3164f77e5dc0SPascal van Leeuwen }
3165f77e5dc0SPascal van Leeuwen 
3166f77e5dc0SPascal van Leeuwen static int safexcel_skcipher_sm4_ctr_cra_init(struct crypto_tfm *tfm)
3167f77e5dc0SPascal van Leeuwen {
3168f77e5dc0SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3169f77e5dc0SPascal van Leeuwen 
3170f77e5dc0SPascal van Leeuwen 	safexcel_skcipher_cra_init(tfm);
3171f77e5dc0SPascal van Leeuwen 	ctx->alg  = SAFEXCEL_SM4;
3172f77e5dc0SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
3173f77e5dc0SPascal van Leeuwen 	return 0;
3174f77e5dc0SPascal van Leeuwen }
3175f77e5dc0SPascal van Leeuwen 
3176f77e5dc0SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_ctr_sm4 = {
3177f77e5dc0SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_SKCIPHER,
3178f77e5dc0SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4,
3179f77e5dc0SPascal van Leeuwen 	.alg.skcipher = {
3180f77e5dc0SPascal van Leeuwen 		.setkey = safexcel_skcipher_sm4ctr_setkey,
3181f77e5dc0SPascal van Leeuwen 		.encrypt = safexcel_encrypt,
3182f77e5dc0SPascal van Leeuwen 		.decrypt = safexcel_decrypt,
3183f77e5dc0SPascal van Leeuwen 		/* Add nonce size */
3184f77e5dc0SPascal van Leeuwen 		.min_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
3185f77e5dc0SPascal van Leeuwen 		.max_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
3186f77e5dc0SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
3187f77e5dc0SPascal van Leeuwen 		.base = {
3188f77e5dc0SPascal van Leeuwen 			.cra_name = "rfc3686(ctr(sm4))",
3189f77e5dc0SPascal van Leeuwen 			.cra_driver_name = "safexcel-ctr-sm4",
3190f77e5dc0SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3191f77e5dc0SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3192f77e5dc0SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3193f77e5dc0SPascal van Leeuwen 			.cra_blocksize = 1,
3194f77e5dc0SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3195f77e5dc0SPascal van Leeuwen 			.cra_alignmask = 0,
3196f77e5dc0SPascal van Leeuwen 			.cra_init = safexcel_skcipher_sm4_ctr_cra_init,
3197f77e5dc0SPascal van Leeuwen 			.cra_exit = safexcel_skcipher_cra_exit,
3198f77e5dc0SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3199f77e5dc0SPascal van Leeuwen 		},
3200f77e5dc0SPascal van Leeuwen 	},
3201f77e5dc0SPascal van Leeuwen };
32021769f704SPascal van Leeuwen 
32031769f704SPascal van Leeuwen static int safexcel_aead_sm4_blk_encrypt(struct aead_request *req)
32041769f704SPascal van Leeuwen {
32051769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
32061769f704SPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
32071769f704SPascal van Leeuwen 		return -EINVAL;
32081769f704SPascal van Leeuwen 
32091769f704SPascal van Leeuwen 	return safexcel_queue_req(&req->base, aead_request_ctx(req),
32101769f704SPascal van Leeuwen 				  SAFEXCEL_ENCRYPT);
32111769f704SPascal van Leeuwen }
32121769f704SPascal van Leeuwen 
32131769f704SPascal van Leeuwen static int safexcel_aead_sm4_blk_decrypt(struct aead_request *req)
32141769f704SPascal van Leeuwen {
32151769f704SPascal van Leeuwen 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
32161769f704SPascal van Leeuwen 
32171769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
32181769f704SPascal van Leeuwen 	if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1))
32191769f704SPascal van Leeuwen 		return -EINVAL;
32201769f704SPascal van Leeuwen 
32211769f704SPascal van Leeuwen 	return safexcel_queue_req(&req->base, aead_request_ctx(req),
32221769f704SPascal van Leeuwen 				  SAFEXCEL_DECRYPT);
32231769f704SPascal van Leeuwen }
32241769f704SPascal van Leeuwen 
32251769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sha1_cra_init(struct crypto_tfm *tfm)
32261769f704SPascal van Leeuwen {
32271769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
32281769f704SPascal van Leeuwen 
32291769f704SPascal van Leeuwen 	safexcel_aead_cra_init(tfm);
32301769f704SPascal van Leeuwen 	ctx->alg = SAFEXCEL_SM4;
32311769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1;
32321769f704SPascal van Leeuwen 	ctx->state_sz = SHA1_DIGEST_SIZE;
32331769f704SPascal van Leeuwen 	return 0;
32341769f704SPascal van Leeuwen }
32351769f704SPascal van Leeuwen 
32361769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_sm4 = {
32371769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
32381769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1,
32391769f704SPascal van Leeuwen 	.alg.aead = {
32401769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
32411769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_sm4_blk_encrypt,
32421769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_sm4_blk_decrypt,
32431769f704SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
32441769f704SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
32451769f704SPascal van Leeuwen 		.base = {
32461769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),cbc(sm4))",
32471769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-sm4",
32481769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
32491769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
32501769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
32511769f704SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
32521769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
32531769f704SPascal van Leeuwen 			.cra_alignmask = 0,
32541769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4cbc_sha1_cra_init,
32551769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
32561769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
32571769f704SPascal van Leeuwen 		},
32581769f704SPascal van Leeuwen 	},
32591769f704SPascal van Leeuwen };
32601769f704SPascal van Leeuwen 
32611769f704SPascal van Leeuwen static int safexcel_aead_fallback_setkey(struct crypto_aead *ctfm,
32621769f704SPascal van Leeuwen 					 const u8 *key, unsigned int len)
32631769f704SPascal van Leeuwen {
32641769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
32651769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
32661769f704SPascal van Leeuwen 
32671769f704SPascal van Leeuwen 	/* Keep fallback cipher synchronized */
32681769f704SPascal van Leeuwen 	return crypto_aead_setkey(ctx->fback, (u8 *)key, len) ?:
32691769f704SPascal van Leeuwen 	       safexcel_aead_setkey(ctfm, key, len);
32701769f704SPascal van Leeuwen }
32711769f704SPascal van Leeuwen 
32721769f704SPascal van Leeuwen static int safexcel_aead_fallback_setauthsize(struct crypto_aead *ctfm,
32731769f704SPascal van Leeuwen 					      unsigned int authsize)
32741769f704SPascal van Leeuwen {
32751769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
32761769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
32771769f704SPascal van Leeuwen 
32781769f704SPascal van Leeuwen 	/* Keep fallback cipher synchronized */
32791769f704SPascal van Leeuwen 	return crypto_aead_setauthsize(ctx->fback, authsize);
32801769f704SPascal van Leeuwen }
32811769f704SPascal van Leeuwen 
32821769f704SPascal van Leeuwen static int safexcel_aead_fallback_crypt(struct aead_request *req,
32831769f704SPascal van Leeuwen 					enum safexcel_cipher_direction dir)
32841769f704SPascal van Leeuwen {
32851769f704SPascal van Leeuwen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
32861769f704SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
32871769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
32881769f704SPascal van Leeuwen 	struct aead_request *subreq = aead_request_ctx(req);
32891769f704SPascal van Leeuwen 
32901769f704SPascal van Leeuwen 	aead_request_set_tfm(subreq, ctx->fback);
32911769f704SPascal van Leeuwen 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
32921769f704SPascal van Leeuwen 				  req->base.data);
32931769f704SPascal van Leeuwen 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
32941769f704SPascal van Leeuwen 			       req->iv);
32951769f704SPascal van Leeuwen 	aead_request_set_ad(subreq, req->assoclen);
32961769f704SPascal van Leeuwen 
32971769f704SPascal van Leeuwen 	return (dir ==  SAFEXCEL_ENCRYPT) ?
32981769f704SPascal van Leeuwen 		crypto_aead_encrypt(subreq) :
32991769f704SPascal van Leeuwen 		crypto_aead_decrypt(subreq);
33001769f704SPascal van Leeuwen }
33011769f704SPascal van Leeuwen 
33021769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_encrypt(struct aead_request *req)
33031769f704SPascal van Leeuwen {
33041769f704SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
33051769f704SPascal van Leeuwen 
33061769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
33071769f704SPascal van Leeuwen 	if (req->cryptlen & (SM4_BLOCK_SIZE - 1))
33081769f704SPascal van Leeuwen 		return -EINVAL;
33091769f704SPascal van Leeuwen 	else if (req->cryptlen || req->assoclen) /* If input length > 0 only */
33101769f704SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
33111769f704SPascal van Leeuwen 
33121769f704SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
33131769f704SPascal van Leeuwen 	return safexcel_aead_fallback_crypt(req, SAFEXCEL_ENCRYPT);
33141769f704SPascal van Leeuwen }
33151769f704SPascal van Leeuwen 
33161769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_decrypt(struct aead_request *req)
33171769f704SPascal van Leeuwen {
33181769f704SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
33191769f704SPascal van Leeuwen 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
33201769f704SPascal van Leeuwen 
33211769f704SPascal van Leeuwen 	/* Workaround for HW bug: EIP96 4.3 does not report blocksize error */
33221769f704SPascal van Leeuwen 	if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1))
33231769f704SPascal van Leeuwen 		return -EINVAL;
33241769f704SPascal van Leeuwen 	else if (req->cryptlen > crypto_aead_authsize(tfm) || req->assoclen)
33251769f704SPascal van Leeuwen 		/* If input length > 0 only */
33261769f704SPascal van Leeuwen 		return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
33271769f704SPascal van Leeuwen 
33281769f704SPascal van Leeuwen 	/* HW cannot do full (AAD+payload) zero length, use fallback */
33291769f704SPascal van Leeuwen 	return safexcel_aead_fallback_crypt(req, SAFEXCEL_DECRYPT);
33301769f704SPascal van Leeuwen }
33311769f704SPascal van Leeuwen 
33321769f704SPascal van Leeuwen static int safexcel_aead_sm4cbc_sm3_cra_init(struct crypto_tfm *tfm)
33331769f704SPascal van Leeuwen {
33341769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33351769f704SPascal van Leeuwen 
33361769f704SPascal van Leeuwen 	safexcel_aead_fallback_cra_init(tfm);
33371769f704SPascal van Leeuwen 	ctx->alg = SAFEXCEL_SM4;
33381769f704SPascal van Leeuwen 	ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3;
33391769f704SPascal van Leeuwen 	ctx->state_sz = SM3_DIGEST_SIZE;
33401769f704SPascal van Leeuwen 	return 0;
33411769f704SPascal van Leeuwen }
33421769f704SPascal van Leeuwen 
33431769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_cbc_sm4 = {
33441769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
33451769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3,
33461769f704SPascal van Leeuwen 	.alg.aead = {
33471769f704SPascal van Leeuwen 		.setkey = safexcel_aead_fallback_setkey,
33481769f704SPascal van Leeuwen 		.setauthsize = safexcel_aead_fallback_setauthsize,
33491769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_sm4cbc_sm3_encrypt,
33501769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_sm4cbc_sm3_decrypt,
33511769f704SPascal van Leeuwen 		.ivsize = SM4_BLOCK_SIZE,
33521769f704SPascal van Leeuwen 		.maxauthsize = SM3_DIGEST_SIZE,
33531769f704SPascal van Leeuwen 		.base = {
33541769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sm3),cbc(sm4))",
33551769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sm3-cbc-sm4",
33561769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
33571769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
33581769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY |
33591769f704SPascal van Leeuwen 				     CRYPTO_ALG_NEED_FALLBACK,
33601769f704SPascal van Leeuwen 			.cra_blocksize = SM4_BLOCK_SIZE,
33611769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
33621769f704SPascal van Leeuwen 			.cra_alignmask = 0,
33631769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4cbc_sm3_cra_init,
33641769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_fallback_cra_exit,
33651769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
33661769f704SPascal van Leeuwen 		},
33671769f704SPascal van Leeuwen 	},
33681769f704SPascal van Leeuwen };
33691769f704SPascal van Leeuwen 
33701769f704SPascal van Leeuwen static int safexcel_aead_sm4ctr_sha1_cra_init(struct crypto_tfm *tfm)
33711769f704SPascal van Leeuwen {
33721769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
33731769f704SPascal van Leeuwen 
33741769f704SPascal van Leeuwen 	safexcel_aead_sm4cbc_sha1_cra_init(tfm);
33751769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
33761769f704SPascal van Leeuwen 	return 0;
33771769f704SPascal van Leeuwen }
33781769f704SPascal van Leeuwen 
33791769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_sm4 = {
33801769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
33811769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1,
33821769f704SPascal van Leeuwen 	.alg.aead = {
33831769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
33841769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
33851769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
33861769f704SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
33871769f704SPascal van Leeuwen 		.maxauthsize = SHA1_DIGEST_SIZE,
33881769f704SPascal van Leeuwen 		.base = {
33891769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sha1),rfc3686(ctr(sm4)))",
33901769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-sm4",
33911769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
33921769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
33931769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
33941769f704SPascal van Leeuwen 			.cra_blocksize = 1,
33951769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
33961769f704SPascal van Leeuwen 			.cra_alignmask = 0,
33971769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4ctr_sha1_cra_init,
33981769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
33991769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
34001769f704SPascal van Leeuwen 		},
34011769f704SPascal van Leeuwen 	},
34021769f704SPascal van Leeuwen };
34031769f704SPascal van Leeuwen 
34041769f704SPascal van Leeuwen static int safexcel_aead_sm4ctr_sm3_cra_init(struct crypto_tfm *tfm)
34051769f704SPascal van Leeuwen {
34061769f704SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
34071769f704SPascal van Leeuwen 
34081769f704SPascal van Leeuwen 	safexcel_aead_sm4cbc_sm3_cra_init(tfm);
34091769f704SPascal van Leeuwen 	ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD;
34101769f704SPascal van Leeuwen 	return 0;
34111769f704SPascal van Leeuwen }
34121769f704SPascal van Leeuwen 
34131769f704SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_ctr_sm4 = {
34141769f704SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
34151769f704SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3,
34161769f704SPascal van Leeuwen 	.alg.aead = {
34171769f704SPascal van Leeuwen 		.setkey = safexcel_aead_setkey,
34181769f704SPascal van Leeuwen 		.encrypt = safexcel_aead_encrypt,
34191769f704SPascal van Leeuwen 		.decrypt = safexcel_aead_decrypt,
34201769f704SPascal van Leeuwen 		.ivsize = CTR_RFC3686_IV_SIZE,
34211769f704SPascal van Leeuwen 		.maxauthsize = SM3_DIGEST_SIZE,
34221769f704SPascal van Leeuwen 		.base = {
34231769f704SPascal van Leeuwen 			.cra_name = "authenc(hmac(sm3),rfc3686(ctr(sm4)))",
34241769f704SPascal van Leeuwen 			.cra_driver_name = "safexcel-authenc-hmac-sm3-ctr-sm4",
34251769f704SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
34261769f704SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
34271769f704SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
34281769f704SPascal van Leeuwen 			.cra_blocksize = 1,
34291769f704SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
34301769f704SPascal van Leeuwen 			.cra_alignmask = 0,
34311769f704SPascal van Leeuwen 			.cra_init = safexcel_aead_sm4ctr_sm3_cra_init,
34321769f704SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
34331769f704SPascal van Leeuwen 			.cra_module = THIS_MODULE,
34341769f704SPascal van Leeuwen 		},
34351769f704SPascal van Leeuwen 	},
34361769f704SPascal van Leeuwen };
3437a19052d4SPascal van Leeuwen 
3438a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_setkey(struct crypto_aead *ctfm, const u8 *key,
3439a19052d4SPascal van Leeuwen 				       unsigned int len)
3440a19052d4SPascal van Leeuwen {
3441a19052d4SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
3442a19052d4SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3443a19052d4SPascal van Leeuwen 
3444a19052d4SPascal van Leeuwen 	/* last 4 bytes of key are the nonce! */
3445a19052d4SPascal van Leeuwen 	ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE);
3446a19052d4SPascal van Leeuwen 
3447a19052d4SPascal van Leeuwen 	len -= CTR_RFC3686_NONCE_SIZE;
3448a19052d4SPascal van Leeuwen 	return safexcel_aead_gcm_setkey(ctfm, key, len);
3449a19052d4SPascal van Leeuwen }
3450a19052d4SPascal van Leeuwen 
3451a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_setauthsize(struct crypto_aead *tfm,
3452a19052d4SPascal van Leeuwen 					    unsigned int authsize)
3453a19052d4SPascal van Leeuwen {
3454a19052d4SPascal van Leeuwen 	return crypto_rfc4106_check_authsize(authsize);
3455a19052d4SPascal van Leeuwen }
3456a19052d4SPascal van Leeuwen 
3457a19052d4SPascal van Leeuwen static int safexcel_rfc4106_encrypt(struct aead_request *req)
3458a19052d4SPascal van Leeuwen {
3459a19052d4SPascal van Leeuwen 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
3460a19052d4SPascal van Leeuwen 	       safexcel_aead_encrypt(req);
3461a19052d4SPascal van Leeuwen }
3462a19052d4SPascal van Leeuwen 
3463a19052d4SPascal van Leeuwen static int safexcel_rfc4106_decrypt(struct aead_request *req)
3464a19052d4SPascal van Leeuwen {
3465a19052d4SPascal van Leeuwen 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
3466a19052d4SPascal van Leeuwen 	       safexcel_aead_decrypt(req);
3467a19052d4SPascal van Leeuwen }
3468a19052d4SPascal van Leeuwen 
3469a19052d4SPascal van Leeuwen static int safexcel_rfc4106_gcm_cra_init(struct crypto_tfm *tfm)
3470a19052d4SPascal van Leeuwen {
3471a19052d4SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3472a19052d4SPascal van Leeuwen 	int ret;
3473a19052d4SPascal van Leeuwen 
3474a19052d4SPascal van Leeuwen 	ret = safexcel_aead_gcm_cra_init(tfm);
3475a19052d4SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3476a19052d4SPascal van Leeuwen 	return ret;
3477a19052d4SPascal van Leeuwen }
3478a19052d4SPascal van Leeuwen 
3479a19052d4SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4106_gcm = {
3480a19052d4SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3481a19052d4SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
3482a19052d4SPascal van Leeuwen 	.alg.aead = {
3483a19052d4SPascal van Leeuwen 		.setkey = safexcel_rfc4106_gcm_setkey,
3484a19052d4SPascal van Leeuwen 		.setauthsize = safexcel_rfc4106_gcm_setauthsize,
3485a19052d4SPascal van Leeuwen 		.encrypt = safexcel_rfc4106_encrypt,
3486a19052d4SPascal van Leeuwen 		.decrypt = safexcel_rfc4106_decrypt,
3487a19052d4SPascal van Leeuwen 		.ivsize = GCM_RFC4106_IV_SIZE,
3488a19052d4SPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
3489a19052d4SPascal van Leeuwen 		.base = {
3490a19052d4SPascal van Leeuwen 			.cra_name = "rfc4106(gcm(aes))",
3491a19052d4SPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4106-gcm-aes",
3492a19052d4SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3493a19052d4SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3494a19052d4SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3495a19052d4SPascal van Leeuwen 			.cra_blocksize = 1,
3496a19052d4SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3497a19052d4SPascal van Leeuwen 			.cra_alignmask = 0,
3498a19052d4SPascal van Leeuwen 			.cra_init = safexcel_rfc4106_gcm_cra_init,
3499a19052d4SPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
3500a19052d4SPascal van Leeuwen 		},
3501a19052d4SPascal van Leeuwen 	},
3502a19052d4SPascal van Leeuwen };
350392c60cefSPascal van Leeuwen 
350492c60cefSPascal van Leeuwen static int safexcel_rfc4543_gcm_setauthsize(struct crypto_aead *tfm,
350592c60cefSPascal van Leeuwen 					    unsigned int authsize)
350692c60cefSPascal van Leeuwen {
350792c60cefSPascal van Leeuwen 	if (authsize != GHASH_DIGEST_SIZE)
350892c60cefSPascal van Leeuwen 		return -EINVAL;
350992c60cefSPascal van Leeuwen 
351092c60cefSPascal van Leeuwen 	return 0;
351192c60cefSPascal van Leeuwen }
351292c60cefSPascal van Leeuwen 
351392c60cefSPascal van Leeuwen static int safexcel_rfc4543_gcm_cra_init(struct crypto_tfm *tfm)
351492c60cefSPascal van Leeuwen {
351592c60cefSPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
351692c60cefSPascal van Leeuwen 	int ret;
351792c60cefSPascal van Leeuwen 
351892c60cefSPascal van Leeuwen 	ret = safexcel_aead_gcm_cra_init(tfm);
351992c60cefSPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP_GMAC;
352092c60cefSPascal van Leeuwen 	return ret;
352192c60cefSPascal van Leeuwen }
352292c60cefSPascal van Leeuwen 
352392c60cefSPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4543_gcm = {
352492c60cefSPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
352592c60cefSPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH,
352692c60cefSPascal van Leeuwen 	.alg.aead = {
352792c60cefSPascal van Leeuwen 		.setkey = safexcel_rfc4106_gcm_setkey,
352892c60cefSPascal van Leeuwen 		.setauthsize = safexcel_rfc4543_gcm_setauthsize,
352992c60cefSPascal van Leeuwen 		.encrypt = safexcel_rfc4106_encrypt,
353092c60cefSPascal van Leeuwen 		.decrypt = safexcel_rfc4106_decrypt,
353192c60cefSPascal van Leeuwen 		.ivsize = GCM_RFC4543_IV_SIZE,
353292c60cefSPascal van Leeuwen 		.maxauthsize = GHASH_DIGEST_SIZE,
353392c60cefSPascal van Leeuwen 		.base = {
353492c60cefSPascal van Leeuwen 			.cra_name = "rfc4543(gcm(aes))",
353592c60cefSPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4543-gcm-aes",
353692c60cefSPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
353792c60cefSPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
353892c60cefSPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
353992c60cefSPascal van Leeuwen 			.cra_blocksize = 1,
354092c60cefSPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
354192c60cefSPascal van Leeuwen 			.cra_alignmask = 0,
354292c60cefSPascal van Leeuwen 			.cra_init = safexcel_rfc4543_gcm_cra_init,
354392c60cefSPascal van Leeuwen 			.cra_exit = safexcel_aead_gcm_cra_exit,
354492c60cefSPascal van Leeuwen 		},
354592c60cefSPascal van Leeuwen 	},
354692c60cefSPascal van Leeuwen };
3547a9a89624SPascal van Leeuwen 
3548a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_setkey(struct crypto_aead *ctfm, const u8 *key,
3549a9a89624SPascal van Leeuwen 				       unsigned int len)
3550a9a89624SPascal van Leeuwen {
3551a9a89624SPascal van Leeuwen 	struct crypto_tfm *tfm = crypto_aead_tfm(ctfm);
3552a9a89624SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3553a9a89624SPascal van Leeuwen 
3554a9a89624SPascal van Leeuwen 	/* First byte of the nonce = L = always 3 for RFC4309 (4 byte ctr) */
3555a9a89624SPascal van Leeuwen 	*(u8 *)&ctx->nonce = EIP197_AEAD_IPSEC_COUNTER_SIZE - 1;
3556a9a89624SPascal van Leeuwen 	/* last 3 bytes of key are the nonce! */
3557a9a89624SPascal van Leeuwen 	memcpy((u8 *)&ctx->nonce + 1, key + len -
3558a9a89624SPascal van Leeuwen 	       EIP197_AEAD_IPSEC_CCM_NONCE_SIZE,
3559a9a89624SPascal van Leeuwen 	       EIP197_AEAD_IPSEC_CCM_NONCE_SIZE);
3560a9a89624SPascal van Leeuwen 
3561a9a89624SPascal van Leeuwen 	len -= EIP197_AEAD_IPSEC_CCM_NONCE_SIZE;
3562a9a89624SPascal van Leeuwen 	return safexcel_aead_ccm_setkey(ctfm, key, len);
3563a9a89624SPascal van Leeuwen }
3564a9a89624SPascal van Leeuwen 
3565a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_setauthsize(struct crypto_aead *tfm,
3566a9a89624SPascal van Leeuwen 					    unsigned int authsize)
3567a9a89624SPascal van Leeuwen {
3568a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3569a9a89624SPascal van Leeuwen 	switch (authsize) {
3570a9a89624SPascal van Leeuwen 	case 8:
3571a9a89624SPascal van Leeuwen 	case 12:
3572a9a89624SPascal van Leeuwen 	case 16:
3573a9a89624SPascal van Leeuwen 		break;
3574a9a89624SPascal van Leeuwen 	default:
3575a9a89624SPascal van Leeuwen 		return -EINVAL;
3576a9a89624SPascal van Leeuwen 	}
3577a9a89624SPascal van Leeuwen 
3578a9a89624SPascal van Leeuwen 	return 0;
3579a9a89624SPascal van Leeuwen }
3580a9a89624SPascal van Leeuwen 
3581a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_encrypt(struct aead_request *req)
3582a9a89624SPascal van Leeuwen {
3583a9a89624SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
3584a9a89624SPascal van Leeuwen 
3585a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3586a9a89624SPascal van Leeuwen 	if (req->assoclen != 16 && req->assoclen != 20)
3587a9a89624SPascal van Leeuwen 		return -EINVAL;
3588a9a89624SPascal van Leeuwen 
3589a9a89624SPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT);
3590a9a89624SPascal van Leeuwen }
3591a9a89624SPascal van Leeuwen 
3592a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_decrypt(struct aead_request *req)
3593a9a89624SPascal van Leeuwen {
3594a9a89624SPascal van Leeuwen 	struct safexcel_cipher_req *creq = aead_request_ctx(req);
3595a9a89624SPascal van Leeuwen 
3596a9a89624SPascal van Leeuwen 	/* Borrowed from crypto/ccm.c */
3597a9a89624SPascal van Leeuwen 	if (req->assoclen != 16 && req->assoclen != 20)
3598a9a89624SPascal van Leeuwen 		return -EINVAL;
3599a9a89624SPascal van Leeuwen 
3600a9a89624SPascal van Leeuwen 	return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT);
3601a9a89624SPascal van Leeuwen }
3602a9a89624SPascal van Leeuwen 
3603a9a89624SPascal van Leeuwen static int safexcel_rfc4309_ccm_cra_init(struct crypto_tfm *tfm)
3604a9a89624SPascal van Leeuwen {
3605a9a89624SPascal van Leeuwen 	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
3606a9a89624SPascal van Leeuwen 	int ret;
3607a9a89624SPascal van Leeuwen 
3608a9a89624SPascal van Leeuwen 	ret = safexcel_aead_ccm_cra_init(tfm);
3609a9a89624SPascal van Leeuwen 	ctx->aead  = EIP197_AEAD_TYPE_IPSEC_ESP;
3610a9a89624SPascal van Leeuwen 	return ret;
3611a9a89624SPascal van Leeuwen }
3612a9a89624SPascal van Leeuwen 
3613a9a89624SPascal van Leeuwen struct safexcel_alg_template safexcel_alg_rfc4309_ccm = {
3614a9a89624SPascal van Leeuwen 	.type = SAFEXCEL_ALG_TYPE_AEAD,
3615a9a89624SPascal van Leeuwen 	.algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL,
3616a9a89624SPascal van Leeuwen 	.alg.aead = {
3617a9a89624SPascal van Leeuwen 		.setkey = safexcel_rfc4309_ccm_setkey,
3618a9a89624SPascal van Leeuwen 		.setauthsize = safexcel_rfc4309_ccm_setauthsize,
3619a9a89624SPascal van Leeuwen 		.encrypt = safexcel_rfc4309_ccm_encrypt,
3620a9a89624SPascal van Leeuwen 		.decrypt = safexcel_rfc4309_ccm_decrypt,
3621a9a89624SPascal van Leeuwen 		.ivsize = EIP197_AEAD_IPSEC_IV_SIZE,
3622a9a89624SPascal van Leeuwen 		.maxauthsize = AES_BLOCK_SIZE,
3623a9a89624SPascal van Leeuwen 		.base = {
3624a9a89624SPascal van Leeuwen 			.cra_name = "rfc4309(ccm(aes))",
3625a9a89624SPascal van Leeuwen 			.cra_driver_name = "safexcel-rfc4309-ccm-aes",
3626a9a89624SPascal van Leeuwen 			.cra_priority = SAFEXCEL_CRA_PRIORITY,
3627a9a89624SPascal van Leeuwen 			.cra_flags = CRYPTO_ALG_ASYNC |
3628a9a89624SPascal van Leeuwen 				     CRYPTO_ALG_KERN_DRIVER_ONLY,
3629a9a89624SPascal van Leeuwen 			.cra_blocksize = 1,
3630a9a89624SPascal van Leeuwen 			.cra_ctxsize = sizeof(struct safexcel_cipher_ctx),
3631a9a89624SPascal van Leeuwen 			.cra_alignmask = 0,
3632a9a89624SPascal van Leeuwen 			.cra_init = safexcel_rfc4309_ccm_cra_init,
3633a9a89624SPascal van Leeuwen 			.cra_exit = safexcel_aead_cra_exit,
3634a9a89624SPascal van Leeuwen 			.cra_module = THIS_MODULE,
3635a9a89624SPascal van Leeuwen 		},
3636a9a89624SPascal van Leeuwen 	},
3637a9a89624SPascal van Leeuwen };
3638