xref: /linux/arch/s390/crypto/phmac_s390.c (revision 44a8c96edd0ee9320a1ad87afc7b10f38e55d5ec)
1cbbc6755SHarald Freudenberger // SPDX-License-Identifier: GPL-2.0+
2cbbc6755SHarald Freudenberger /*
3cbbc6755SHarald Freudenberger  * Copyright IBM Corp. 2025
4cbbc6755SHarald Freudenberger  *
5cbbc6755SHarald Freudenberger  * s390 specific HMAC support for protected keys.
6cbbc6755SHarald Freudenberger  */
7cbbc6755SHarald Freudenberger 
8cbbc6755SHarald Freudenberger #define KMSG_COMPONENT	"phmac_s390"
9cbbc6755SHarald Freudenberger #define pr_fmt(fmt)	KMSG_COMPONENT ": " fmt
10cbbc6755SHarald Freudenberger 
11cbbc6755SHarald Freudenberger #include <asm/cpacf.h>
12cbbc6755SHarald Freudenberger #include <asm/pkey.h>
13cbbc6755SHarald Freudenberger #include <crypto/engine.h>
14cbbc6755SHarald Freudenberger #include <crypto/hash.h>
15cbbc6755SHarald Freudenberger #include <crypto/internal/hash.h>
16cbbc6755SHarald Freudenberger #include <crypto/sha2.h>
17cbbc6755SHarald Freudenberger #include <linux/atomic.h>
18cbbc6755SHarald Freudenberger #include <linux/cpufeature.h>
19cbbc6755SHarald Freudenberger #include <linux/delay.h>
20cbbc6755SHarald Freudenberger #include <linux/miscdevice.h>
21cbbc6755SHarald Freudenberger #include <linux/module.h>
22cbbc6755SHarald Freudenberger #include <linux/spinlock.h>
23cbbc6755SHarald Freudenberger 
24cbbc6755SHarald Freudenberger static struct crypto_engine *phmac_crypto_engine;
25cbbc6755SHarald Freudenberger #define MAX_QLEN 10
26cbbc6755SHarald Freudenberger 
27cbbc6755SHarald Freudenberger /*
28cbbc6755SHarald Freudenberger  * A simple hash walk helper
29cbbc6755SHarald Freudenberger  */
30cbbc6755SHarald Freudenberger 
31cbbc6755SHarald Freudenberger struct hash_walk_helper {
32cbbc6755SHarald Freudenberger 	struct crypto_hash_walk walk;
33cbbc6755SHarald Freudenberger 	const u8 *walkaddr;
34cbbc6755SHarald Freudenberger 	int walkbytes;
35cbbc6755SHarald Freudenberger };
36cbbc6755SHarald Freudenberger 
37cbbc6755SHarald Freudenberger /*
38cbbc6755SHarald Freudenberger  * Prepare hash walk helper.
39cbbc6755SHarald Freudenberger  * Set up the base hash walk, fill walkaddr and walkbytes.
40cbbc6755SHarald Freudenberger  * Returns 0 on success or negative value on error.
41cbbc6755SHarald Freudenberger  */
hwh_prepare(struct ahash_request * req,struct hash_walk_helper * hwh)42cbbc6755SHarald Freudenberger static inline int hwh_prepare(struct ahash_request *req,
43cbbc6755SHarald Freudenberger 			      struct hash_walk_helper *hwh)
44cbbc6755SHarald Freudenberger {
45cbbc6755SHarald Freudenberger 	hwh->walkbytes = crypto_hash_walk_first(req, &hwh->walk);
46cbbc6755SHarald Freudenberger 	if (hwh->walkbytes < 0)
47cbbc6755SHarald Freudenberger 		return hwh->walkbytes;
48cbbc6755SHarald Freudenberger 	hwh->walkaddr = hwh->walk.data;
49cbbc6755SHarald Freudenberger 	return 0;
50cbbc6755SHarald Freudenberger }
51cbbc6755SHarald Freudenberger 
52cbbc6755SHarald Freudenberger /*
53cbbc6755SHarald Freudenberger  * Advance hash walk helper by n bytes.
54cbbc6755SHarald Freudenberger  * Progress the walkbytes and walkaddr fields by n bytes.
55cbbc6755SHarald Freudenberger  * If walkbytes is then 0, pull next hunk from hash walk
56cbbc6755SHarald Freudenberger  * and update walkbytes and walkaddr.
57cbbc6755SHarald Freudenberger  * If n is negative, unmap hash walk and return error.
58cbbc6755SHarald Freudenberger  * Returns 0 on success or negative value on error.
59cbbc6755SHarald Freudenberger  */
hwh_advance(struct hash_walk_helper * hwh,int n)60cbbc6755SHarald Freudenberger static inline int hwh_advance(struct hash_walk_helper *hwh, int n)
61cbbc6755SHarald Freudenberger {
62cbbc6755SHarald Freudenberger 	if (n < 0)
63cbbc6755SHarald Freudenberger 		return crypto_hash_walk_done(&hwh->walk, n);
64cbbc6755SHarald Freudenberger 
65cbbc6755SHarald Freudenberger 	hwh->walkbytes -= n;
66cbbc6755SHarald Freudenberger 	hwh->walkaddr += n;
67cbbc6755SHarald Freudenberger 	if (hwh->walkbytes > 0)
68cbbc6755SHarald Freudenberger 		return 0;
69cbbc6755SHarald Freudenberger 
70cbbc6755SHarald Freudenberger 	hwh->walkbytes = crypto_hash_walk_done(&hwh->walk, 0);
71cbbc6755SHarald Freudenberger 	if (hwh->walkbytes < 0)
72cbbc6755SHarald Freudenberger 		return hwh->walkbytes;
73cbbc6755SHarald Freudenberger 
74cbbc6755SHarald Freudenberger 	hwh->walkaddr = hwh->walk.data;
75cbbc6755SHarald Freudenberger 	return 0;
76cbbc6755SHarald Freudenberger }
77cbbc6755SHarald Freudenberger 
78cbbc6755SHarald Freudenberger /*
79cbbc6755SHarald Freudenberger  * KMAC param block layout for sha2 function codes:
80cbbc6755SHarald Freudenberger  * The layout of the param block for the KMAC instruction depends on the
81cbbc6755SHarald Freudenberger  * blocksize of the used hashing sha2-algorithm function codes. The param block
82cbbc6755SHarald Freudenberger  * contains the hash chaining value (cv), the input message bit-length (imbl)
83cbbc6755SHarald Freudenberger  * and the hmac-secret (key). To prevent code duplication, the sizes of all
84cbbc6755SHarald Freudenberger  * these are calculated based on the blocksize.
85cbbc6755SHarald Freudenberger  *
86cbbc6755SHarald Freudenberger  * param-block:
87cbbc6755SHarald Freudenberger  * +-------+
88cbbc6755SHarald Freudenberger  * | cv    |
89cbbc6755SHarald Freudenberger  * +-------+
90cbbc6755SHarald Freudenberger  * | imbl  |
91cbbc6755SHarald Freudenberger  * +-------+
92cbbc6755SHarald Freudenberger  * | key   |
93cbbc6755SHarald Freudenberger  * +-------+
94cbbc6755SHarald Freudenberger  *
95cbbc6755SHarald Freudenberger  * sizes:
96cbbc6755SHarald Freudenberger  * part | sh2-alg | calculation | size | type
97cbbc6755SHarald Freudenberger  * -----+---------+-------------+------+--------
98cbbc6755SHarald Freudenberger  * cv   | 224/256 | blocksize/2 |   32 |  u64[8]
99cbbc6755SHarald Freudenberger  *      | 384/512 |             |   64 | u128[8]
100cbbc6755SHarald Freudenberger  * imbl | 224/256 | blocksize/8 |    8 |     u64
101cbbc6755SHarald Freudenberger  *      | 384/512 |             |   16 |    u128
102cbbc6755SHarald Freudenberger  * key  | 224/256 | blocksize   |   96 |  u8[96]
103cbbc6755SHarald Freudenberger  *      | 384/512 |             |  160 | u8[160]
104cbbc6755SHarald Freudenberger  */
105cbbc6755SHarald Freudenberger 
106cbbc6755SHarald Freudenberger #define MAX_DIGEST_SIZE		SHA512_DIGEST_SIZE
107cbbc6755SHarald Freudenberger #define MAX_IMBL_SIZE		sizeof(u128)
108cbbc6755SHarald Freudenberger #define MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
109cbbc6755SHarald Freudenberger 
110cbbc6755SHarald Freudenberger #define SHA2_CV_SIZE(bs)	((bs) >> 1)
111cbbc6755SHarald Freudenberger #define SHA2_IMBL_SIZE(bs)	((bs) >> 3)
112cbbc6755SHarald Freudenberger 
113cbbc6755SHarald Freudenberger #define SHA2_IMBL_OFFSET(bs)	(SHA2_CV_SIZE(bs))
114cbbc6755SHarald Freudenberger #define SHA2_KEY_OFFSET(bs)	(SHA2_CV_SIZE(bs) + SHA2_IMBL_SIZE(bs))
115cbbc6755SHarald Freudenberger 
116cbbc6755SHarald Freudenberger #define PHMAC_MAX_KEYSIZE       256
117cbbc6755SHarald Freudenberger #define PHMAC_SHA256_PK_SIZE	(SHA256_BLOCK_SIZE + 32)
118cbbc6755SHarald Freudenberger #define PHMAC_SHA512_PK_SIZE	(SHA512_BLOCK_SIZE + 32)
119cbbc6755SHarald Freudenberger #define PHMAC_MAX_PK_SIZE	PHMAC_SHA512_PK_SIZE
120cbbc6755SHarald Freudenberger 
121cbbc6755SHarald Freudenberger /* phmac protected key struct */
122cbbc6755SHarald Freudenberger struct phmac_protkey {
123cbbc6755SHarald Freudenberger 	u32 type;
124cbbc6755SHarald Freudenberger 	u32 len;
125cbbc6755SHarald Freudenberger 	u8 protkey[PHMAC_MAX_PK_SIZE];
126cbbc6755SHarald Freudenberger };
127cbbc6755SHarald Freudenberger 
128cbbc6755SHarald Freudenberger #define PK_STATE_NO_KEY		     0
129cbbc6755SHarald Freudenberger #define PK_STATE_CONVERT_IN_PROGRESS 1
130cbbc6755SHarald Freudenberger #define PK_STATE_VALID		     2
131cbbc6755SHarald Freudenberger 
132cbbc6755SHarald Freudenberger /* phmac tfm context */
133cbbc6755SHarald Freudenberger struct phmac_tfm_ctx {
134cbbc6755SHarald Freudenberger 	/* source key material used to derive a protected key from */
135cbbc6755SHarald Freudenberger 	u8 keybuf[PHMAC_MAX_KEYSIZE];
136cbbc6755SHarald Freudenberger 	unsigned int keylen;
137cbbc6755SHarald Freudenberger 
138cbbc6755SHarald Freudenberger 	/* cpacf function code to use with this protected key type */
139cbbc6755SHarald Freudenberger 	long fc;
140cbbc6755SHarald Freudenberger 
141cbbc6755SHarald Freudenberger 	/* nr of requests enqueued via crypto engine which use this tfm ctx */
142cbbc6755SHarald Freudenberger 	atomic_t via_engine_ctr;
143cbbc6755SHarald Freudenberger 
144cbbc6755SHarald Freudenberger 	/* spinlock to atomic read/update all the following fields */
145cbbc6755SHarald Freudenberger 	spinlock_t pk_lock;
146cbbc6755SHarald Freudenberger 
147cbbc6755SHarald Freudenberger 	/* see PK_STATE* defines above, < 0 holds convert failure rc  */
148cbbc6755SHarald Freudenberger 	int pk_state;
149cbbc6755SHarald Freudenberger 	/* if state is valid, pk holds the protected key */
150cbbc6755SHarald Freudenberger 	struct phmac_protkey pk;
151cbbc6755SHarald Freudenberger };
152cbbc6755SHarald Freudenberger 
153cbbc6755SHarald Freudenberger union kmac_gr0 {
154cbbc6755SHarald Freudenberger 	unsigned long reg;
155cbbc6755SHarald Freudenberger 	struct {
156cbbc6755SHarald Freudenberger 		unsigned long		: 48;
157cbbc6755SHarald Freudenberger 		unsigned long ikp	:  1;
158cbbc6755SHarald Freudenberger 		unsigned long iimp	:  1;
159cbbc6755SHarald Freudenberger 		unsigned long ccup	:  1;
160cbbc6755SHarald Freudenberger 		unsigned long		:  6;
161cbbc6755SHarald Freudenberger 		unsigned long fc	:  7;
162cbbc6755SHarald Freudenberger 	};
163cbbc6755SHarald Freudenberger };
164cbbc6755SHarald Freudenberger 
165cbbc6755SHarald Freudenberger struct kmac_sha2_ctx {
166cbbc6755SHarald Freudenberger 	u8 param[MAX_DIGEST_SIZE + MAX_IMBL_SIZE + PHMAC_MAX_PK_SIZE];
167cbbc6755SHarald Freudenberger 	union kmac_gr0 gr0;
168cbbc6755SHarald Freudenberger 	u8 buf[MAX_BLOCK_SIZE];
169cbbc6755SHarald Freudenberger 	u64 buflen[2];
170cbbc6755SHarald Freudenberger };
171cbbc6755SHarald Freudenberger 
172cbbc6755SHarald Freudenberger /* phmac request context */
173cbbc6755SHarald Freudenberger struct phmac_req_ctx {
174cbbc6755SHarald Freudenberger 	struct hash_walk_helper hwh;
175cbbc6755SHarald Freudenberger 	struct kmac_sha2_ctx kmac_ctx;
176cbbc6755SHarald Freudenberger 	bool final;
177cbbc6755SHarald Freudenberger };
178cbbc6755SHarald Freudenberger 
179cbbc6755SHarald Freudenberger /*
180d48b2f5eSHarald Freudenberger  * Pkey 'token' struct used to derive a protected key value from a clear key.
181d48b2f5eSHarald Freudenberger  */
182d48b2f5eSHarald Freudenberger struct hmac_clrkey_token {
183d48b2f5eSHarald Freudenberger 	u8  type;
184d48b2f5eSHarald Freudenberger 	u8  res0[3];
185d48b2f5eSHarald Freudenberger 	u8  version;
186d48b2f5eSHarald Freudenberger 	u8  res1[3];
187d48b2f5eSHarald Freudenberger 	u32 keytype;
188d48b2f5eSHarald Freudenberger 	u32 len;
189d48b2f5eSHarald Freudenberger 	u8 key[];
190d48b2f5eSHarald Freudenberger } __packed;
191d48b2f5eSHarald Freudenberger 
hash_key(const u8 * in,unsigned int inlen,u8 * digest,unsigned int digestsize)192d48b2f5eSHarald Freudenberger static int hash_key(const u8 *in, unsigned int inlen,
193d48b2f5eSHarald Freudenberger 		    u8 *digest, unsigned int digestsize)
194d48b2f5eSHarald Freudenberger {
195d48b2f5eSHarald Freudenberger 	unsigned long func;
196d48b2f5eSHarald Freudenberger 	union {
197d48b2f5eSHarald Freudenberger 		struct sha256_paramblock {
198d48b2f5eSHarald Freudenberger 			u32 h[8];
199d48b2f5eSHarald Freudenberger 			u64 mbl;
200d48b2f5eSHarald Freudenberger 		} sha256;
201d48b2f5eSHarald Freudenberger 		struct sha512_paramblock {
202d48b2f5eSHarald Freudenberger 			u64 h[8];
203d48b2f5eSHarald Freudenberger 			u128 mbl;
204d48b2f5eSHarald Freudenberger 		} sha512;
205d48b2f5eSHarald Freudenberger 	} __packed param;
206d48b2f5eSHarald Freudenberger 
207d48b2f5eSHarald Freudenberger #define PARAM_INIT(x, y, z)		   \
208d48b2f5eSHarald Freudenberger 	param.sha##x.h[0] = SHA##y ## _H0; \
209d48b2f5eSHarald Freudenberger 	param.sha##x.h[1] = SHA##y ## _H1; \
210d48b2f5eSHarald Freudenberger 	param.sha##x.h[2] = SHA##y ## _H2; \
211d48b2f5eSHarald Freudenberger 	param.sha##x.h[3] = SHA##y ## _H3; \
212d48b2f5eSHarald Freudenberger 	param.sha##x.h[4] = SHA##y ## _H4; \
213d48b2f5eSHarald Freudenberger 	param.sha##x.h[5] = SHA##y ## _H5; \
214d48b2f5eSHarald Freudenberger 	param.sha##x.h[6] = SHA##y ## _H6; \
215d48b2f5eSHarald Freudenberger 	param.sha##x.h[7] = SHA##y ## _H7; \
216d48b2f5eSHarald Freudenberger 	param.sha##x.mbl = (z)
217d48b2f5eSHarald Freudenberger 
218d48b2f5eSHarald Freudenberger 	switch (digestsize) {
219d48b2f5eSHarald Freudenberger 	case SHA224_DIGEST_SIZE:
220d48b2f5eSHarald Freudenberger 		func = CPACF_KLMD_SHA_256;
221d48b2f5eSHarald Freudenberger 		PARAM_INIT(256, 224, inlen * 8);
222d48b2f5eSHarald Freudenberger 		break;
223d48b2f5eSHarald Freudenberger 	case SHA256_DIGEST_SIZE:
224d48b2f5eSHarald Freudenberger 		func = CPACF_KLMD_SHA_256;
225d48b2f5eSHarald Freudenberger 		PARAM_INIT(256, 256, inlen * 8);
226d48b2f5eSHarald Freudenberger 		break;
227d48b2f5eSHarald Freudenberger 	case SHA384_DIGEST_SIZE:
228d48b2f5eSHarald Freudenberger 		func = CPACF_KLMD_SHA_512;
229d48b2f5eSHarald Freudenberger 		PARAM_INIT(512, 384, inlen * 8);
230d48b2f5eSHarald Freudenberger 		break;
231d48b2f5eSHarald Freudenberger 	case SHA512_DIGEST_SIZE:
232d48b2f5eSHarald Freudenberger 		func = CPACF_KLMD_SHA_512;
233d48b2f5eSHarald Freudenberger 		PARAM_INIT(512, 512, inlen * 8);
234d48b2f5eSHarald Freudenberger 		break;
235d48b2f5eSHarald Freudenberger 	default:
236d48b2f5eSHarald Freudenberger 		return -EINVAL;
237d48b2f5eSHarald Freudenberger 	}
238d48b2f5eSHarald Freudenberger 
239d48b2f5eSHarald Freudenberger #undef PARAM_INIT
240d48b2f5eSHarald Freudenberger 
241d48b2f5eSHarald Freudenberger 	cpacf_klmd(func, &param, in, inlen);
242d48b2f5eSHarald Freudenberger 
243d48b2f5eSHarald Freudenberger 	memcpy(digest, &param, digestsize);
244d48b2f5eSHarald Freudenberger 
245d48b2f5eSHarald Freudenberger 	return 0;
246d48b2f5eSHarald Freudenberger }
247d48b2f5eSHarald Freudenberger 
248d48b2f5eSHarald Freudenberger /*
249d48b2f5eSHarald Freudenberger  * make_clrkey_token() - wrap the clear key into a pkey clearkey token.
250d48b2f5eSHarald Freudenberger  */
make_clrkey_token(const u8 * clrkey,size_t clrkeylen,unsigned int digestsize,u8 * dest)251d48b2f5eSHarald Freudenberger static inline int make_clrkey_token(const u8 *clrkey, size_t clrkeylen,
252d48b2f5eSHarald Freudenberger 				    unsigned int digestsize, u8 *dest)
253d48b2f5eSHarald Freudenberger {
254d48b2f5eSHarald Freudenberger 	struct hmac_clrkey_token *token = (struct hmac_clrkey_token *)dest;
255d48b2f5eSHarald Freudenberger 	unsigned int blocksize;
256d48b2f5eSHarald Freudenberger 	int rc;
257d48b2f5eSHarald Freudenberger 
258d48b2f5eSHarald Freudenberger 	token->type = 0x00;
259d48b2f5eSHarald Freudenberger 	token->version = 0x02;
260d48b2f5eSHarald Freudenberger 	switch (digestsize) {
261d48b2f5eSHarald Freudenberger 	case SHA224_DIGEST_SIZE:
262d48b2f5eSHarald Freudenberger 	case SHA256_DIGEST_SIZE:
263d48b2f5eSHarald Freudenberger 		token->keytype = PKEY_KEYTYPE_HMAC_512;
264d48b2f5eSHarald Freudenberger 		blocksize = 64;
265d48b2f5eSHarald Freudenberger 		break;
266d48b2f5eSHarald Freudenberger 	case SHA384_DIGEST_SIZE:
267d48b2f5eSHarald Freudenberger 	case SHA512_DIGEST_SIZE:
268d48b2f5eSHarald Freudenberger 		token->keytype = PKEY_KEYTYPE_HMAC_1024;
269d48b2f5eSHarald Freudenberger 		blocksize = 128;
270d48b2f5eSHarald Freudenberger 		break;
271d48b2f5eSHarald Freudenberger 	default:
272d48b2f5eSHarald Freudenberger 		return -EINVAL;
273d48b2f5eSHarald Freudenberger 	}
274d48b2f5eSHarald Freudenberger 	token->len = blocksize;
275d48b2f5eSHarald Freudenberger 
276d48b2f5eSHarald Freudenberger 	if (clrkeylen > blocksize) {
277d48b2f5eSHarald Freudenberger 		rc = hash_key(clrkey, clrkeylen, token->key, digestsize);
278d48b2f5eSHarald Freudenberger 		if (rc)
279d48b2f5eSHarald Freudenberger 			return rc;
280d48b2f5eSHarald Freudenberger 	} else {
281d48b2f5eSHarald Freudenberger 		memcpy(token->key, clrkey, clrkeylen);
282d48b2f5eSHarald Freudenberger 	}
283d48b2f5eSHarald Freudenberger 
284d48b2f5eSHarald Freudenberger 	return 0;
285d48b2f5eSHarald Freudenberger }
286d48b2f5eSHarald Freudenberger 
287d48b2f5eSHarald Freudenberger /*
288cbbc6755SHarald Freudenberger  * phmac_tfm_ctx_setkey() - Set key value into tfm context, maybe construct
289cbbc6755SHarald Freudenberger  * a clear key token digestible by pkey from a clear key value.
290cbbc6755SHarald Freudenberger  */
phmac_tfm_ctx_setkey(struct phmac_tfm_ctx * tfm_ctx,const u8 * key,unsigned int keylen)291cbbc6755SHarald Freudenberger static inline int phmac_tfm_ctx_setkey(struct phmac_tfm_ctx *tfm_ctx,
292cbbc6755SHarald Freudenberger 				       const u8 *key, unsigned int keylen)
293cbbc6755SHarald Freudenberger {
294cbbc6755SHarald Freudenberger 	if (keylen > sizeof(tfm_ctx->keybuf))
295cbbc6755SHarald Freudenberger 		return -EINVAL;
296cbbc6755SHarald Freudenberger 
297cbbc6755SHarald Freudenberger 	memcpy(tfm_ctx->keybuf, key, keylen);
298cbbc6755SHarald Freudenberger 	tfm_ctx->keylen = keylen;
299cbbc6755SHarald Freudenberger 
300cbbc6755SHarald Freudenberger 	return 0;
301cbbc6755SHarald Freudenberger }
302cbbc6755SHarald Freudenberger 
303cbbc6755SHarald Freudenberger /*
304cbbc6755SHarald Freudenberger  * Convert the raw key material into a protected key via PKEY api.
305cbbc6755SHarald Freudenberger  * This function may sleep - don't call in non-sleeping context.
306cbbc6755SHarald Freudenberger  */
convert_key(const u8 * key,unsigned int keylen,struct phmac_protkey * pk)307cbbc6755SHarald Freudenberger static inline int convert_key(const u8 *key, unsigned int keylen,
308cbbc6755SHarald Freudenberger 			      struct phmac_protkey *pk)
309cbbc6755SHarald Freudenberger {
310cbbc6755SHarald Freudenberger 	int rc, i;
311cbbc6755SHarald Freudenberger 
312cbbc6755SHarald Freudenberger 	pk->len = sizeof(pk->protkey);
313cbbc6755SHarald Freudenberger 
314cbbc6755SHarald Freudenberger 	/*
315cbbc6755SHarald Freudenberger 	 * In case of a busy card retry with increasing delay
316cbbc6755SHarald Freudenberger 	 * of 200, 400, 800 and 1600 ms - in total 3 s.
317cbbc6755SHarald Freudenberger 	 */
318cbbc6755SHarald Freudenberger 	for (rc = -EIO, i = 0; rc && i < 5; i++) {
319cbbc6755SHarald Freudenberger 		if (rc == -EBUSY && msleep_interruptible((1 << i) * 100)) {
320cbbc6755SHarald Freudenberger 			rc = -EINTR;
321cbbc6755SHarald Freudenberger 			goto out;
322cbbc6755SHarald Freudenberger 		}
323cbbc6755SHarald Freudenberger 		rc = pkey_key2protkey(key, keylen,
324cbbc6755SHarald Freudenberger 				      pk->protkey, &pk->len, &pk->type,
325cbbc6755SHarald Freudenberger 				      PKEY_XFLAG_NOMEMALLOC);
326cbbc6755SHarald Freudenberger 	}
327cbbc6755SHarald Freudenberger 
328cbbc6755SHarald Freudenberger out:
329cbbc6755SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
330cbbc6755SHarald Freudenberger 	return rc;
331cbbc6755SHarald Freudenberger }
332cbbc6755SHarald Freudenberger 
333cbbc6755SHarald Freudenberger /*
334cbbc6755SHarald Freudenberger  * (Re-)Convert the raw key material from the tfm ctx into a protected
335cbbc6755SHarald Freudenberger  * key via convert_key() function. Update the pk_state, pk_type, pk_len
336cbbc6755SHarald Freudenberger  * and the protected key in the tfm context.
337cbbc6755SHarald Freudenberger  * Please note this function may be invoked concurrently with the very
338cbbc6755SHarald Freudenberger  * same tfm context. The pk_lock spinlock in the context ensures an
339cbbc6755SHarald Freudenberger  * atomic update of the pk and the pk state but does not guarantee any
340cbbc6755SHarald Freudenberger  * order of update. So a fresh converted valid protected key may get
341cbbc6755SHarald Freudenberger  * updated with an 'old' expired key value. As the cpacf instructions
342cbbc6755SHarald Freudenberger  * detect this, refuse to operate with an invalid key and the calling
343cbbc6755SHarald Freudenberger  * code triggers a (re-)conversion this does no harm. This may lead to
344cbbc6755SHarald Freudenberger  * unnecessary additional conversion but never to invalid data on the
345cbbc6755SHarald Freudenberger  * hash operation.
346cbbc6755SHarald Freudenberger  */
phmac_convert_key(struct phmac_tfm_ctx * tfm_ctx)347cbbc6755SHarald Freudenberger static int phmac_convert_key(struct phmac_tfm_ctx *tfm_ctx)
348cbbc6755SHarald Freudenberger {
349cbbc6755SHarald Freudenberger 	struct phmac_protkey pk;
350cbbc6755SHarald Freudenberger 	int rc;
351cbbc6755SHarald Freudenberger 
352cbbc6755SHarald Freudenberger 	spin_lock_bh(&tfm_ctx->pk_lock);
353cbbc6755SHarald Freudenberger 	tfm_ctx->pk_state = PK_STATE_CONVERT_IN_PROGRESS;
354cbbc6755SHarald Freudenberger 	spin_unlock_bh(&tfm_ctx->pk_lock);
355cbbc6755SHarald Freudenberger 
356cbbc6755SHarald Freudenberger 	rc = convert_key(tfm_ctx->keybuf, tfm_ctx->keylen, &pk);
357cbbc6755SHarald Freudenberger 
358cbbc6755SHarald Freudenberger 	/* update context */
359cbbc6755SHarald Freudenberger 	spin_lock_bh(&tfm_ctx->pk_lock);
360cbbc6755SHarald Freudenberger 	if (rc) {
361cbbc6755SHarald Freudenberger 		tfm_ctx->pk_state = rc;
362cbbc6755SHarald Freudenberger 	} else {
363cbbc6755SHarald Freudenberger 		tfm_ctx->pk_state = PK_STATE_VALID;
364cbbc6755SHarald Freudenberger 		tfm_ctx->pk = pk;
365cbbc6755SHarald Freudenberger 	}
366cbbc6755SHarald Freudenberger 	spin_unlock_bh(&tfm_ctx->pk_lock);
367cbbc6755SHarald Freudenberger 
368cbbc6755SHarald Freudenberger 	memzero_explicit(&pk, sizeof(pk));
369cbbc6755SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
370cbbc6755SHarald Freudenberger 	return rc;
371cbbc6755SHarald Freudenberger }
372cbbc6755SHarald Freudenberger 
373cbbc6755SHarald Freudenberger /*
374cbbc6755SHarald Freudenberger  * kmac_sha2_set_imbl - sets the input message bit-length based on the blocksize
375cbbc6755SHarald Freudenberger  */
kmac_sha2_set_imbl(u8 * param,u64 buflen_lo,u64 buflen_hi,unsigned int blocksize)376cbbc6755SHarald Freudenberger static inline void kmac_sha2_set_imbl(u8 *param, u64 buflen_lo,
377cbbc6755SHarald Freudenberger 				      u64 buflen_hi, unsigned int blocksize)
378cbbc6755SHarald Freudenberger {
379cbbc6755SHarald Freudenberger 	u8 *imbl = param + SHA2_IMBL_OFFSET(blocksize);
380cbbc6755SHarald Freudenberger 
381cbbc6755SHarald Freudenberger 	switch (blocksize) {
382cbbc6755SHarald Freudenberger 	case SHA256_BLOCK_SIZE:
383cbbc6755SHarald Freudenberger 		*(u64 *)imbl = buflen_lo * BITS_PER_BYTE;
384cbbc6755SHarald Freudenberger 		break;
385cbbc6755SHarald Freudenberger 	case SHA512_BLOCK_SIZE:
386cbbc6755SHarald Freudenberger 		*(u128 *)imbl = (((u128)buflen_hi << 64) + buflen_lo) << 3;
387cbbc6755SHarald Freudenberger 		break;
388cbbc6755SHarald Freudenberger 	default:
389cbbc6755SHarald Freudenberger 		break;
390cbbc6755SHarald Freudenberger 	}
391cbbc6755SHarald Freudenberger }
392cbbc6755SHarald Freudenberger 
phmac_kmac_update(struct ahash_request * req,bool maysleep)393cbbc6755SHarald Freudenberger static int phmac_kmac_update(struct ahash_request *req, bool maysleep)
394cbbc6755SHarald Freudenberger {
395cbbc6755SHarald Freudenberger 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
396cbbc6755SHarald Freudenberger 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
397cbbc6755SHarald Freudenberger 	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
398cbbc6755SHarald Freudenberger 	struct kmac_sha2_ctx *ctx = &req_ctx->kmac_ctx;
399cbbc6755SHarald Freudenberger 	struct hash_walk_helper *hwh = &req_ctx->hwh;
400cbbc6755SHarald Freudenberger 	unsigned int bs = crypto_ahash_blocksize(tfm);
401cbbc6755SHarald Freudenberger 	unsigned int offset, k, n;
402cbbc6755SHarald Freudenberger 	int rc = 0;
403cbbc6755SHarald Freudenberger 
404cbbc6755SHarald Freudenberger 	/*
405cbbc6755SHarald Freudenberger 	 * The walk is always mapped when this function is called.
406cbbc6755SHarald Freudenberger 	 * Note that in case of partial processing or failure the walk
407cbbc6755SHarald Freudenberger 	 * is NOT unmapped here. So a follow up task may reuse the walk
408cbbc6755SHarald Freudenberger 	 * or in case of unrecoverable failure needs to unmap it.
409cbbc6755SHarald Freudenberger 	 */
410cbbc6755SHarald Freudenberger 
411cbbc6755SHarald Freudenberger 	while (hwh->walkbytes > 0) {
412cbbc6755SHarald Freudenberger 		/* check sha2 context buffer */
413cbbc6755SHarald Freudenberger 		offset = ctx->buflen[0] % bs;
414cbbc6755SHarald Freudenberger 		if (offset + hwh->walkbytes < bs)
415cbbc6755SHarald Freudenberger 			goto store;
416cbbc6755SHarald Freudenberger 
417cbbc6755SHarald Freudenberger 		if (offset) {
418cbbc6755SHarald Freudenberger 			/* fill ctx buffer up to blocksize and process this block */
419cbbc6755SHarald Freudenberger 			n = bs - offset;
420cbbc6755SHarald Freudenberger 			memcpy(ctx->buf + offset, hwh->walkaddr, n);
421cbbc6755SHarald Freudenberger 			ctx->gr0.iimp = 1;
422cbbc6755SHarald Freudenberger 			for (;;) {
423cbbc6755SHarald Freudenberger 				k = _cpacf_kmac(&ctx->gr0.reg, ctx->param, ctx->buf, bs);
424cbbc6755SHarald Freudenberger 				if (likely(k == bs))
425cbbc6755SHarald Freudenberger 					break;
426cbbc6755SHarald Freudenberger 				if (unlikely(k > 0)) {
427cbbc6755SHarald Freudenberger 					/*
428cbbc6755SHarald Freudenberger 					 * Can't deal with hunks smaller than blocksize.
429cbbc6755SHarald Freudenberger 					 * And kmac should always return the nr of
430cbbc6755SHarald Freudenberger 					 * processed bytes as 0 or a multiple of the
431cbbc6755SHarald Freudenberger 					 * blocksize.
432cbbc6755SHarald Freudenberger 					 */
433cbbc6755SHarald Freudenberger 					rc = -EIO;
434cbbc6755SHarald Freudenberger 					goto out;
435cbbc6755SHarald Freudenberger 				}
436cbbc6755SHarald Freudenberger 				/* protected key is invalid and needs re-conversion */
437cbbc6755SHarald Freudenberger 				if (!maysleep) {
438cbbc6755SHarald Freudenberger 					rc = -EKEYEXPIRED;
439cbbc6755SHarald Freudenberger 					goto out;
440cbbc6755SHarald Freudenberger 				}
441cbbc6755SHarald Freudenberger 				rc = phmac_convert_key(tfm_ctx);
442cbbc6755SHarald Freudenberger 				if (rc)
443cbbc6755SHarald Freudenberger 					goto out;
444cbbc6755SHarald Freudenberger 				spin_lock_bh(&tfm_ctx->pk_lock);
445cbbc6755SHarald Freudenberger 				memcpy(ctx->param + SHA2_KEY_OFFSET(bs),
446cbbc6755SHarald Freudenberger 				       tfm_ctx->pk.protkey, tfm_ctx->pk.len);
447cbbc6755SHarald Freudenberger 				spin_unlock_bh(&tfm_ctx->pk_lock);
448cbbc6755SHarald Freudenberger 			}
449cbbc6755SHarald Freudenberger 			ctx->buflen[0] += n;
450cbbc6755SHarald Freudenberger 			if (ctx->buflen[0] < n)
451cbbc6755SHarald Freudenberger 				ctx->buflen[1]++;
452cbbc6755SHarald Freudenberger 			rc = hwh_advance(hwh, n);
453cbbc6755SHarald Freudenberger 			if (unlikely(rc))
454cbbc6755SHarald Freudenberger 				goto out;
455cbbc6755SHarald Freudenberger 			offset = 0;
456cbbc6755SHarald Freudenberger 		}
457cbbc6755SHarald Freudenberger 
458cbbc6755SHarald Freudenberger 		/* process as many blocks as possible from the walk */
459cbbc6755SHarald Freudenberger 		while (hwh->walkbytes >= bs) {
460cbbc6755SHarald Freudenberger 			n = (hwh->walkbytes / bs) * bs;
461cbbc6755SHarald Freudenberger 			ctx->gr0.iimp = 1;
462cbbc6755SHarald Freudenberger 			k = _cpacf_kmac(&ctx->gr0.reg, ctx->param, hwh->walkaddr, n);
463cbbc6755SHarald Freudenberger 			if (likely(k > 0)) {
464cbbc6755SHarald Freudenberger 				ctx->buflen[0] += k;
465cbbc6755SHarald Freudenberger 				if (ctx->buflen[0] < k)
466cbbc6755SHarald Freudenberger 					ctx->buflen[1]++;
467cbbc6755SHarald Freudenberger 				rc = hwh_advance(hwh, k);
468cbbc6755SHarald Freudenberger 				if (unlikely(rc))
469cbbc6755SHarald Freudenberger 					goto out;
470cbbc6755SHarald Freudenberger 			}
471cbbc6755SHarald Freudenberger 			if (unlikely(k < n)) {
472cbbc6755SHarald Freudenberger 				/* protected key is invalid and needs re-conversion */
473cbbc6755SHarald Freudenberger 				if (!maysleep) {
474cbbc6755SHarald Freudenberger 					rc = -EKEYEXPIRED;
475cbbc6755SHarald Freudenberger 					goto out;
476cbbc6755SHarald Freudenberger 				}
477cbbc6755SHarald Freudenberger 				rc = phmac_convert_key(tfm_ctx);
478cbbc6755SHarald Freudenberger 				if (rc)
479cbbc6755SHarald Freudenberger 					goto out;
480cbbc6755SHarald Freudenberger 				spin_lock_bh(&tfm_ctx->pk_lock);
481cbbc6755SHarald Freudenberger 				memcpy(ctx->param + SHA2_KEY_OFFSET(bs),
482cbbc6755SHarald Freudenberger 				       tfm_ctx->pk.protkey, tfm_ctx->pk.len);
483cbbc6755SHarald Freudenberger 				spin_unlock_bh(&tfm_ctx->pk_lock);
484cbbc6755SHarald Freudenberger 			}
485cbbc6755SHarald Freudenberger 		}
486cbbc6755SHarald Freudenberger 
487cbbc6755SHarald Freudenberger store:
488cbbc6755SHarald Freudenberger 		/* store incomplete block in context buffer */
489cbbc6755SHarald Freudenberger 		if (hwh->walkbytes) {
490cbbc6755SHarald Freudenberger 			memcpy(ctx->buf + offset, hwh->walkaddr, hwh->walkbytes);
491cbbc6755SHarald Freudenberger 			ctx->buflen[0] += hwh->walkbytes;
492cbbc6755SHarald Freudenberger 			if (ctx->buflen[0] < hwh->walkbytes)
493cbbc6755SHarald Freudenberger 				ctx->buflen[1]++;
494cbbc6755SHarald Freudenberger 			rc = hwh_advance(hwh, hwh->walkbytes);
495cbbc6755SHarald Freudenberger 			if (unlikely(rc))
496cbbc6755SHarald Freudenberger 				goto out;
497cbbc6755SHarald Freudenberger 		}
498cbbc6755SHarald Freudenberger 
499cbbc6755SHarald Freudenberger 	} /* end of while (hwh->walkbytes > 0) */
500cbbc6755SHarald Freudenberger 
501cbbc6755SHarald Freudenberger out:
502cbbc6755SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
503cbbc6755SHarald Freudenberger 	return rc;
504cbbc6755SHarald Freudenberger }
505cbbc6755SHarald Freudenberger 
phmac_kmac_final(struct ahash_request * req,bool maysleep)506cbbc6755SHarald Freudenberger static int phmac_kmac_final(struct ahash_request *req, bool maysleep)
507cbbc6755SHarald Freudenberger {
508cbbc6755SHarald Freudenberger 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
509cbbc6755SHarald Freudenberger 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
510cbbc6755SHarald Freudenberger 	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
511cbbc6755SHarald Freudenberger 	struct kmac_sha2_ctx *ctx = &req_ctx->kmac_ctx;
512cbbc6755SHarald Freudenberger 	unsigned int ds = crypto_ahash_digestsize(tfm);
513cbbc6755SHarald Freudenberger 	unsigned int bs = crypto_ahash_blocksize(tfm);
514cbbc6755SHarald Freudenberger 	unsigned int k, n;
515cbbc6755SHarald Freudenberger 	int rc = 0;
516cbbc6755SHarald Freudenberger 
517cbbc6755SHarald Freudenberger 	n = ctx->buflen[0] % bs;
518cbbc6755SHarald Freudenberger 	ctx->gr0.iimp = 0;
519cbbc6755SHarald Freudenberger 	kmac_sha2_set_imbl(ctx->param, ctx->buflen[0], ctx->buflen[1], bs);
520cbbc6755SHarald Freudenberger 	for (;;) {
521cbbc6755SHarald Freudenberger 		k = _cpacf_kmac(&ctx->gr0.reg, ctx->param, ctx->buf, n);
522cbbc6755SHarald Freudenberger 		if (likely(k == n))
523cbbc6755SHarald Freudenberger 			break;
524cbbc6755SHarald Freudenberger 		if (unlikely(k > 0)) {
525cbbc6755SHarald Freudenberger 			/* Can't deal with hunks smaller than blocksize. */
526cbbc6755SHarald Freudenberger 			rc = -EIO;
527cbbc6755SHarald Freudenberger 			goto out;
528cbbc6755SHarald Freudenberger 		}
529cbbc6755SHarald Freudenberger 		/* protected key is invalid and needs re-conversion */
530cbbc6755SHarald Freudenberger 		if (!maysleep) {
531cbbc6755SHarald Freudenberger 			rc = -EKEYEXPIRED;
532cbbc6755SHarald Freudenberger 			goto out;
533cbbc6755SHarald Freudenberger 		}
534cbbc6755SHarald Freudenberger 		rc = phmac_convert_key(tfm_ctx);
535cbbc6755SHarald Freudenberger 		if (rc)
536cbbc6755SHarald Freudenberger 			goto out;
537cbbc6755SHarald Freudenberger 		spin_lock_bh(&tfm_ctx->pk_lock);
538cbbc6755SHarald Freudenberger 		memcpy(ctx->param + SHA2_KEY_OFFSET(bs),
539cbbc6755SHarald Freudenberger 		       tfm_ctx->pk.protkey, tfm_ctx->pk.len);
540cbbc6755SHarald Freudenberger 		spin_unlock_bh(&tfm_ctx->pk_lock);
541cbbc6755SHarald Freudenberger 	}
542cbbc6755SHarald Freudenberger 
543cbbc6755SHarald Freudenberger 	memcpy(req->result, ctx->param, ds);
544cbbc6755SHarald Freudenberger 
545cbbc6755SHarald Freudenberger out:
546cbbc6755SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
547cbbc6755SHarald Freudenberger 	return rc;
548cbbc6755SHarald Freudenberger }
549cbbc6755SHarald Freudenberger 
phmac_init(struct ahash_request * req)550cbbc6755SHarald Freudenberger static int phmac_init(struct ahash_request *req)
551cbbc6755SHarald Freudenberger {
552cbbc6755SHarald Freudenberger 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
553cbbc6755SHarald Freudenberger 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
554cbbc6755SHarald Freudenberger 	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
555cbbc6755SHarald Freudenberger 	struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
556cbbc6755SHarald Freudenberger 	unsigned int bs = crypto_ahash_blocksize(tfm);
557cbbc6755SHarald Freudenberger 	int rc = 0;
558cbbc6755SHarald Freudenberger 
559cbbc6755SHarald Freudenberger 	/* zero request context (includes the kmac sha2 context) */
560cbbc6755SHarald Freudenberger 	memset(req_ctx, 0, sizeof(*req_ctx));
561cbbc6755SHarald Freudenberger 
562cbbc6755SHarald Freudenberger 	/*
563cbbc6755SHarald Freudenberger 	 * setkey() should have set a valid fc into the tfm context.
564cbbc6755SHarald Freudenberger 	 * Copy this function code into the gr0 field of the kmac context.
565cbbc6755SHarald Freudenberger 	 */
566cbbc6755SHarald Freudenberger 	if (!tfm_ctx->fc) {
567cbbc6755SHarald Freudenberger 		rc = -ENOKEY;
568cbbc6755SHarald Freudenberger 		goto out;
569cbbc6755SHarald Freudenberger 	}
570cbbc6755SHarald Freudenberger 	kmac_ctx->gr0.fc = tfm_ctx->fc;
571cbbc6755SHarald Freudenberger 
572cbbc6755SHarald Freudenberger 	/*
573cbbc6755SHarald Freudenberger 	 * Copy the pk from tfm ctx into kmac ctx. The protected key
574cbbc6755SHarald Freudenberger 	 * may be outdated but update() and final() will handle this.
575cbbc6755SHarald Freudenberger 	 */
576cbbc6755SHarald Freudenberger 	spin_lock_bh(&tfm_ctx->pk_lock);
577cbbc6755SHarald Freudenberger 	memcpy(kmac_ctx->param + SHA2_KEY_OFFSET(bs),
578cbbc6755SHarald Freudenberger 	       tfm_ctx->pk.protkey, tfm_ctx->pk.len);
579cbbc6755SHarald Freudenberger 	spin_unlock_bh(&tfm_ctx->pk_lock);
580cbbc6755SHarald Freudenberger 
581cbbc6755SHarald Freudenberger out:
582cbbc6755SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
583cbbc6755SHarald Freudenberger 	return rc;
584cbbc6755SHarald Freudenberger }
585cbbc6755SHarald Freudenberger 
phmac_update(struct ahash_request * req)586cbbc6755SHarald Freudenberger static int phmac_update(struct ahash_request *req)
587cbbc6755SHarald Freudenberger {
588cbbc6755SHarald Freudenberger 	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
589cbbc6755SHarald Freudenberger 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
590cbbc6755SHarald Freudenberger 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
591cbbc6755SHarald Freudenberger 	struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
592cbbc6755SHarald Freudenberger 	struct hash_walk_helper *hwh = &req_ctx->hwh;
593cbbc6755SHarald Freudenberger 	int rc;
594cbbc6755SHarald Freudenberger 
595cbbc6755SHarald Freudenberger 	/* prep the walk in the request context */
596cbbc6755SHarald Freudenberger 	rc = hwh_prepare(req, hwh);
597cbbc6755SHarald Freudenberger 	if (rc)
598cbbc6755SHarald Freudenberger 		goto out;
599cbbc6755SHarald Freudenberger 
600cbbc6755SHarald Freudenberger 	/* Try synchronous operation if no active engine usage */
601cbbc6755SHarald Freudenberger 	if (!atomic_read(&tfm_ctx->via_engine_ctr)) {
602cbbc6755SHarald Freudenberger 		rc = phmac_kmac_update(req, false);
603cbbc6755SHarald Freudenberger 		if (rc == 0)
604cbbc6755SHarald Freudenberger 			goto out;
605cbbc6755SHarald Freudenberger 	}
606cbbc6755SHarald Freudenberger 
607cbbc6755SHarald Freudenberger 	/*
608cbbc6755SHarald Freudenberger 	 * If sync operation failed or key expired or there are already
609cbbc6755SHarald Freudenberger 	 * requests enqueued via engine, fallback to async. Mark tfm as
610cbbc6755SHarald Freudenberger 	 * using engine to serialize requests.
611cbbc6755SHarald Freudenberger 	 */
612cbbc6755SHarald Freudenberger 	if (rc == 0 || rc == -EKEYEXPIRED) {
613cbbc6755SHarald Freudenberger 		atomic_inc(&tfm_ctx->via_engine_ctr);
614cbbc6755SHarald Freudenberger 		rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
615cbbc6755SHarald Freudenberger 		if (rc != -EINPROGRESS)
616cbbc6755SHarald Freudenberger 			atomic_dec(&tfm_ctx->via_engine_ctr);
617cbbc6755SHarald Freudenberger 	}
618cbbc6755SHarald Freudenberger 
619cbbc6755SHarald Freudenberger 	if (rc != -EINPROGRESS) {
620cbbc6755SHarald Freudenberger 		hwh_advance(hwh, rc);
621cbbc6755SHarald Freudenberger 		memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
622cbbc6755SHarald Freudenberger 	}
623cbbc6755SHarald Freudenberger 
624cbbc6755SHarald Freudenberger out:
625cbbc6755SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
626cbbc6755SHarald Freudenberger 	return rc;
627cbbc6755SHarald Freudenberger }
628cbbc6755SHarald Freudenberger 
phmac_final(struct ahash_request * req)629cbbc6755SHarald Freudenberger static int phmac_final(struct ahash_request *req)
630cbbc6755SHarald Freudenberger {
631cbbc6755SHarald Freudenberger 	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
632cbbc6755SHarald Freudenberger 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
633cbbc6755SHarald Freudenberger 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
634cbbc6755SHarald Freudenberger 	struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
635cbbc6755SHarald Freudenberger 	int rc = 0;
636cbbc6755SHarald Freudenberger 
637cbbc6755SHarald Freudenberger 	/* Try synchronous operation if no active engine usage */
638cbbc6755SHarald Freudenberger 	if (!atomic_read(&tfm_ctx->via_engine_ctr)) {
639cbbc6755SHarald Freudenberger 		rc = phmac_kmac_final(req, false);
640cbbc6755SHarald Freudenberger 		if (rc == 0)
641cbbc6755SHarald Freudenberger 			goto out;
642cbbc6755SHarald Freudenberger 	}
643cbbc6755SHarald Freudenberger 
644cbbc6755SHarald Freudenberger 	/*
645cbbc6755SHarald Freudenberger 	 * If sync operation failed or key expired or there are already
646cbbc6755SHarald Freudenberger 	 * requests enqueued via engine, fallback to async. Mark tfm as
647cbbc6755SHarald Freudenberger 	 * using engine to serialize requests.
648cbbc6755SHarald Freudenberger 	 */
649cbbc6755SHarald Freudenberger 	if (rc == 0 || rc == -EKEYEXPIRED) {
650cbbc6755SHarald Freudenberger 		req->nbytes = 0;
651cbbc6755SHarald Freudenberger 		req_ctx->final = true;
652cbbc6755SHarald Freudenberger 		atomic_inc(&tfm_ctx->via_engine_ctr);
653cbbc6755SHarald Freudenberger 		rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
654cbbc6755SHarald Freudenberger 		if (rc != -EINPROGRESS)
655cbbc6755SHarald Freudenberger 			atomic_dec(&tfm_ctx->via_engine_ctr);
656cbbc6755SHarald Freudenberger 	}
657cbbc6755SHarald Freudenberger 
658cbbc6755SHarald Freudenberger out:
659cbbc6755SHarald Freudenberger 	if (rc != -EINPROGRESS)
660cbbc6755SHarald Freudenberger 		memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
661cbbc6755SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
662cbbc6755SHarald Freudenberger 	return rc;
663cbbc6755SHarald Freudenberger }
664cbbc6755SHarald Freudenberger 
phmac_finup(struct ahash_request * req)665cbbc6755SHarald Freudenberger static int phmac_finup(struct ahash_request *req)
666cbbc6755SHarald Freudenberger {
667cbbc6755SHarald Freudenberger 	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
668cbbc6755SHarald Freudenberger 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
669cbbc6755SHarald Freudenberger 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
670cbbc6755SHarald Freudenberger 	struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
671cbbc6755SHarald Freudenberger 	struct hash_walk_helper *hwh = &req_ctx->hwh;
672cbbc6755SHarald Freudenberger 	int rc;
673cbbc6755SHarald Freudenberger 
674cbbc6755SHarald Freudenberger 	/* prep the walk in the request context */
675cbbc6755SHarald Freudenberger 	rc = hwh_prepare(req, hwh);
676cbbc6755SHarald Freudenberger 	if (rc)
677cbbc6755SHarald Freudenberger 		goto out;
678cbbc6755SHarald Freudenberger 
679cbbc6755SHarald Freudenberger 	/* Try synchronous operations if no active engine usage */
680cbbc6755SHarald Freudenberger 	if (!atomic_read(&tfm_ctx->via_engine_ctr)) {
681cbbc6755SHarald Freudenberger 		rc = phmac_kmac_update(req, false);
682cbbc6755SHarald Freudenberger 		if (rc == 0)
683cbbc6755SHarald Freudenberger 			req->nbytes = 0;
684cbbc6755SHarald Freudenberger 	}
685cbbc6755SHarald Freudenberger 	if (!rc && !req->nbytes && !atomic_read(&tfm_ctx->via_engine_ctr)) {
686cbbc6755SHarald Freudenberger 		rc = phmac_kmac_final(req, false);
687cbbc6755SHarald Freudenberger 		if (rc == 0)
688cbbc6755SHarald Freudenberger 			goto out;
689cbbc6755SHarald Freudenberger 	}
690cbbc6755SHarald Freudenberger 
691cbbc6755SHarald Freudenberger 	/*
692cbbc6755SHarald Freudenberger 	 * If sync operation failed or key expired or there are already
693cbbc6755SHarald Freudenberger 	 * requests enqueued via engine, fallback to async. Mark tfm as
694cbbc6755SHarald Freudenberger 	 * using engine to serialize requests.
695cbbc6755SHarald Freudenberger 	 */
696cbbc6755SHarald Freudenberger 	if (rc == 0 || rc == -EKEYEXPIRED) {
697cbbc6755SHarald Freudenberger 		req_ctx->final = true;
698cbbc6755SHarald Freudenberger 		atomic_inc(&tfm_ctx->via_engine_ctr);
699cbbc6755SHarald Freudenberger 		rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
700cbbc6755SHarald Freudenberger 		if (rc != -EINPROGRESS)
701cbbc6755SHarald Freudenberger 			atomic_dec(&tfm_ctx->via_engine_ctr);
702cbbc6755SHarald Freudenberger 	}
703cbbc6755SHarald Freudenberger 
704cbbc6755SHarald Freudenberger 	if (rc != -EINPROGRESS)
705cbbc6755SHarald Freudenberger 		hwh_advance(hwh, rc);
706cbbc6755SHarald Freudenberger 
707cbbc6755SHarald Freudenberger out:
708cbbc6755SHarald Freudenberger 	if (rc != -EINPROGRESS)
709cbbc6755SHarald Freudenberger 		memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
710cbbc6755SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
711cbbc6755SHarald Freudenberger 	return rc;
712cbbc6755SHarald Freudenberger }
713cbbc6755SHarald Freudenberger 
phmac_digest(struct ahash_request * req)714cbbc6755SHarald Freudenberger static int phmac_digest(struct ahash_request *req)
715cbbc6755SHarald Freudenberger {
716cbbc6755SHarald Freudenberger 	int rc;
717cbbc6755SHarald Freudenberger 
718cbbc6755SHarald Freudenberger 	rc = phmac_init(req);
719cbbc6755SHarald Freudenberger 	if (rc)
720cbbc6755SHarald Freudenberger 		goto out;
721cbbc6755SHarald Freudenberger 
722cbbc6755SHarald Freudenberger 	rc = phmac_finup(req);
723cbbc6755SHarald Freudenberger 
724cbbc6755SHarald Freudenberger out:
725cbbc6755SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
726cbbc6755SHarald Freudenberger 	return rc;
727cbbc6755SHarald Freudenberger }
728cbbc6755SHarald Freudenberger 
phmac_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)729cbbc6755SHarald Freudenberger static int phmac_setkey(struct crypto_ahash *tfm,
730cbbc6755SHarald Freudenberger 			const u8 *key, unsigned int keylen)
731cbbc6755SHarald Freudenberger {
732cbbc6755SHarald Freudenberger 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
733cbbc6755SHarald Freudenberger 	unsigned int ds = crypto_ahash_digestsize(tfm);
734d48b2f5eSHarald Freudenberger 	unsigned int bs = crypto_ahash_blocksize(tfm);
735d48b2f5eSHarald Freudenberger 	unsigned int tmpkeylen;
736d48b2f5eSHarald Freudenberger 	u8 *tmpkey = NULL;
737cbbc6755SHarald Freudenberger 	int rc = 0;
738cbbc6755SHarald Freudenberger 
739d48b2f5eSHarald Freudenberger 	if (!crypto_ahash_tested(tfm)) {
740d48b2f5eSHarald Freudenberger 		/*
741d48b2f5eSHarald Freudenberger 		 * selftest running: key is a raw hmac clear key and needs
742d48b2f5eSHarald Freudenberger 		 * to get embedded into a 'clear key token' in order to have
743d48b2f5eSHarald Freudenberger 		 * it correctly processed by the pkey module.
744d48b2f5eSHarald Freudenberger 		 */
745d48b2f5eSHarald Freudenberger 		tmpkeylen = sizeof(struct hmac_clrkey_token) + bs;
746d48b2f5eSHarald Freudenberger 		tmpkey = kzalloc(tmpkeylen, GFP_KERNEL);
747d48b2f5eSHarald Freudenberger 		if (!tmpkey) {
748d48b2f5eSHarald Freudenberger 			rc = -ENOMEM;
749d48b2f5eSHarald Freudenberger 			goto out;
750d48b2f5eSHarald Freudenberger 		}
751d48b2f5eSHarald Freudenberger 		rc = make_clrkey_token(key, keylen, ds, tmpkey);
752d48b2f5eSHarald Freudenberger 		if (rc)
753d48b2f5eSHarald Freudenberger 			goto out;
754d48b2f5eSHarald Freudenberger 		keylen = tmpkeylen;
755d48b2f5eSHarald Freudenberger 		key = tmpkey;
756d48b2f5eSHarald Freudenberger 	}
757d48b2f5eSHarald Freudenberger 
758cbbc6755SHarald Freudenberger 	/* copy raw key into tfm context */
759cbbc6755SHarald Freudenberger 	rc = phmac_tfm_ctx_setkey(tfm_ctx, key, keylen);
760cbbc6755SHarald Freudenberger 	if (rc)
761cbbc6755SHarald Freudenberger 		goto out;
762cbbc6755SHarald Freudenberger 
763cbbc6755SHarald Freudenberger 	/* convert raw key into protected key */
764cbbc6755SHarald Freudenberger 	rc = phmac_convert_key(tfm_ctx);
765cbbc6755SHarald Freudenberger 	if (rc)
766cbbc6755SHarald Freudenberger 		goto out;
767cbbc6755SHarald Freudenberger 
768cbbc6755SHarald Freudenberger 	/* set function code in tfm context, check for valid pk type */
769cbbc6755SHarald Freudenberger 	switch (ds) {
770cbbc6755SHarald Freudenberger 	case SHA224_DIGEST_SIZE:
771cbbc6755SHarald Freudenberger 		if (tfm_ctx->pk.type != PKEY_KEYTYPE_HMAC_512)
772cbbc6755SHarald Freudenberger 			rc = -EINVAL;
773cbbc6755SHarald Freudenberger 		else
774cbbc6755SHarald Freudenberger 			tfm_ctx->fc = CPACF_KMAC_PHMAC_SHA_224;
775cbbc6755SHarald Freudenberger 		break;
776cbbc6755SHarald Freudenberger 	case SHA256_DIGEST_SIZE:
777cbbc6755SHarald Freudenberger 		if (tfm_ctx->pk.type != PKEY_KEYTYPE_HMAC_512)
778cbbc6755SHarald Freudenberger 			rc = -EINVAL;
779cbbc6755SHarald Freudenberger 		else
780cbbc6755SHarald Freudenberger 			tfm_ctx->fc = CPACF_KMAC_PHMAC_SHA_256;
781cbbc6755SHarald Freudenberger 		break;
782cbbc6755SHarald Freudenberger 	case SHA384_DIGEST_SIZE:
783cbbc6755SHarald Freudenberger 		if (tfm_ctx->pk.type != PKEY_KEYTYPE_HMAC_1024)
784cbbc6755SHarald Freudenberger 			rc = -EINVAL;
785cbbc6755SHarald Freudenberger 		else
786cbbc6755SHarald Freudenberger 			tfm_ctx->fc = CPACF_KMAC_PHMAC_SHA_384;
787cbbc6755SHarald Freudenberger 		break;
788cbbc6755SHarald Freudenberger 	case SHA512_DIGEST_SIZE:
789cbbc6755SHarald Freudenberger 		if (tfm_ctx->pk.type != PKEY_KEYTYPE_HMAC_1024)
790cbbc6755SHarald Freudenberger 			rc = -EINVAL;
791cbbc6755SHarald Freudenberger 		else
792cbbc6755SHarald Freudenberger 			tfm_ctx->fc = CPACF_KMAC_PHMAC_SHA_512;
793cbbc6755SHarald Freudenberger 		break;
794cbbc6755SHarald Freudenberger 	default:
795cbbc6755SHarald Freudenberger 		tfm_ctx->fc = 0;
796cbbc6755SHarald Freudenberger 		rc = -EINVAL;
797cbbc6755SHarald Freudenberger 	}
798cbbc6755SHarald Freudenberger 
799cbbc6755SHarald Freudenberger out:
800d48b2f5eSHarald Freudenberger 	kfree(tmpkey);
801cbbc6755SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
802cbbc6755SHarald Freudenberger 	return rc;
803cbbc6755SHarald Freudenberger }
804cbbc6755SHarald Freudenberger 
phmac_export(struct ahash_request * req,void * out)805cbbc6755SHarald Freudenberger static int phmac_export(struct ahash_request *req, void *out)
806cbbc6755SHarald Freudenberger {
807cbbc6755SHarald Freudenberger 	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
808cbbc6755SHarald Freudenberger 	struct kmac_sha2_ctx *ctx = &req_ctx->kmac_ctx;
809cbbc6755SHarald Freudenberger 
810cbbc6755SHarald Freudenberger 	memcpy(out, ctx, sizeof(*ctx));
811cbbc6755SHarald Freudenberger 
812cbbc6755SHarald Freudenberger 	return 0;
813cbbc6755SHarald Freudenberger }
814cbbc6755SHarald Freudenberger 
phmac_import(struct ahash_request * req,const void * in)815cbbc6755SHarald Freudenberger static int phmac_import(struct ahash_request *req, const void *in)
816cbbc6755SHarald Freudenberger {
817cbbc6755SHarald Freudenberger 	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
818cbbc6755SHarald Freudenberger 	struct kmac_sha2_ctx *ctx = &req_ctx->kmac_ctx;
819cbbc6755SHarald Freudenberger 
820cbbc6755SHarald Freudenberger 	memset(req_ctx, 0, sizeof(*req_ctx));
821cbbc6755SHarald Freudenberger 	memcpy(ctx, in, sizeof(*ctx));
822cbbc6755SHarald Freudenberger 
823cbbc6755SHarald Freudenberger 	return 0;
824cbbc6755SHarald Freudenberger }
825cbbc6755SHarald Freudenberger 
phmac_init_tfm(struct crypto_ahash * tfm)826cbbc6755SHarald Freudenberger static int phmac_init_tfm(struct crypto_ahash *tfm)
827cbbc6755SHarald Freudenberger {
828cbbc6755SHarald Freudenberger 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
829cbbc6755SHarald Freudenberger 
830cbbc6755SHarald Freudenberger 	memset(tfm_ctx, 0, sizeof(*tfm_ctx));
831cbbc6755SHarald Freudenberger 	spin_lock_init(&tfm_ctx->pk_lock);
832cbbc6755SHarald Freudenberger 
833cbbc6755SHarald Freudenberger 	crypto_ahash_set_reqsize(tfm, sizeof(struct phmac_req_ctx));
834cbbc6755SHarald Freudenberger 
835cbbc6755SHarald Freudenberger 	return 0;
836cbbc6755SHarald Freudenberger }
837cbbc6755SHarald Freudenberger 
phmac_exit_tfm(struct crypto_ahash * tfm)838cbbc6755SHarald Freudenberger static void phmac_exit_tfm(struct crypto_ahash *tfm)
839cbbc6755SHarald Freudenberger {
840cbbc6755SHarald Freudenberger 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
841cbbc6755SHarald Freudenberger 
842cbbc6755SHarald Freudenberger 	memzero_explicit(tfm_ctx->keybuf, sizeof(tfm_ctx->keybuf));
843cbbc6755SHarald Freudenberger 	memzero_explicit(&tfm_ctx->pk, sizeof(tfm_ctx->pk));
844cbbc6755SHarald Freudenberger }
845cbbc6755SHarald Freudenberger 
phmac_do_one_request(struct crypto_engine * engine,void * areq)846cbbc6755SHarald Freudenberger static int phmac_do_one_request(struct crypto_engine *engine, void *areq)
847cbbc6755SHarald Freudenberger {
848cbbc6755SHarald Freudenberger 	struct ahash_request *req = ahash_request_cast(areq);
849cbbc6755SHarald Freudenberger 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
850cbbc6755SHarald Freudenberger 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
851cbbc6755SHarald Freudenberger 	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
852cbbc6755SHarald Freudenberger 	struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
853cbbc6755SHarald Freudenberger 	struct hash_walk_helper *hwh = &req_ctx->hwh;
854cbbc6755SHarald Freudenberger 	int rc = -EINVAL;
855cbbc6755SHarald Freudenberger 
856cbbc6755SHarald Freudenberger 	/*
857cbbc6755SHarald Freudenberger 	 * Three kinds of requests come in here:
858cbbc6755SHarald Freudenberger 	 * update when req->nbytes > 0 and req_ctx->final is false
859cbbc6755SHarald Freudenberger 	 * final when req->nbytes = 0 and req_ctx->final is true
860cbbc6755SHarald Freudenberger 	 * finup when req->nbytes > 0 and req_ctx->final is true
861cbbc6755SHarald Freudenberger 	 * For update and finup the hwh walk needs to be prepared and
862cbbc6755SHarald Freudenberger 	 * up to date but the actual nr of bytes in req->nbytes may be
863cbbc6755SHarald Freudenberger 	 * any non zero number. For final there is no hwh walk needed.
864cbbc6755SHarald Freudenberger 	 */
865cbbc6755SHarald Freudenberger 
866cbbc6755SHarald Freudenberger 	if (req->nbytes) {
867cbbc6755SHarald Freudenberger 		rc = phmac_kmac_update(req, true);
868cbbc6755SHarald Freudenberger 		if (rc == -EKEYEXPIRED) {
869cbbc6755SHarald Freudenberger 			/*
870cbbc6755SHarald Freudenberger 			 * Protected key expired, conversion is in process.
871cbbc6755SHarald Freudenberger 			 * Trigger a re-schedule of this request by returning
872cbbc6755SHarald Freudenberger 			 * -ENOSPC ("hardware queue full") to the crypto engine.
873cbbc6755SHarald Freudenberger 			 * To avoid immediately re-invocation of this callback,
874cbbc6755SHarald Freudenberger 			 * tell scheduler to voluntarily give up the CPU here.
875cbbc6755SHarald Freudenberger 			 */
876cbbc6755SHarald Freudenberger 			pr_debug("rescheduling request\n");
877cbbc6755SHarald Freudenberger 			cond_resched();
878cbbc6755SHarald Freudenberger 			return -ENOSPC;
879cbbc6755SHarald Freudenberger 		} else if (rc) {
880cbbc6755SHarald Freudenberger 			hwh_advance(hwh, rc);
881cbbc6755SHarald Freudenberger 			goto out;
882cbbc6755SHarald Freudenberger 		}
883cbbc6755SHarald Freudenberger 		req->nbytes = 0;
884cbbc6755SHarald Freudenberger 	}
885cbbc6755SHarald Freudenberger 
886cbbc6755SHarald Freudenberger 	if (req_ctx->final) {
887cbbc6755SHarald Freudenberger 		rc = phmac_kmac_final(req, true);
888cbbc6755SHarald Freudenberger 		if (rc == -EKEYEXPIRED) {
889cbbc6755SHarald Freudenberger 			/*
890cbbc6755SHarald Freudenberger 			 * Protected key expired, conversion is in process.
891cbbc6755SHarald Freudenberger 			 * Trigger a re-schedule of this request by returning
892cbbc6755SHarald Freudenberger 			 * -ENOSPC ("hardware queue full") to the crypto engine.
893cbbc6755SHarald Freudenberger 			 * To avoid immediately re-invocation of this callback,
894cbbc6755SHarald Freudenberger 			 * tell scheduler to voluntarily give up the CPU here.
895cbbc6755SHarald Freudenberger 			 */
896cbbc6755SHarald Freudenberger 			pr_debug("rescheduling request\n");
897cbbc6755SHarald Freudenberger 			cond_resched();
898cbbc6755SHarald Freudenberger 			return -ENOSPC;
899cbbc6755SHarald Freudenberger 		}
900cbbc6755SHarald Freudenberger 	}
901cbbc6755SHarald Freudenberger 
902cbbc6755SHarald Freudenberger out:
903cbbc6755SHarald Freudenberger 	if (rc || req_ctx->final)
904cbbc6755SHarald Freudenberger 		memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
905cbbc6755SHarald Freudenberger 	pr_debug("request complete with rc=%d\n", rc);
906cbbc6755SHarald Freudenberger 	local_bh_disable();
907cbbc6755SHarald Freudenberger 	atomic_dec(&tfm_ctx->via_engine_ctr);
908cbbc6755SHarald Freudenberger 	crypto_finalize_hash_request(engine, req, rc);
909cbbc6755SHarald Freudenberger 	local_bh_enable();
910cbbc6755SHarald Freudenberger 	return rc;
911cbbc6755SHarald Freudenberger }
912cbbc6755SHarald Freudenberger 
913cbbc6755SHarald Freudenberger #define S390_ASYNC_PHMAC_ALG(x)						\
914cbbc6755SHarald Freudenberger {									\
915cbbc6755SHarald Freudenberger 	.base = {							\
916cbbc6755SHarald Freudenberger 		.init	  = phmac_init,					\
917cbbc6755SHarald Freudenberger 		.update	  = phmac_update,				\
918cbbc6755SHarald Freudenberger 		.final	  = phmac_final,				\
919cbbc6755SHarald Freudenberger 		.finup	  = phmac_finup,				\
920cbbc6755SHarald Freudenberger 		.digest	  = phmac_digest,				\
921cbbc6755SHarald Freudenberger 		.setkey	  = phmac_setkey,				\
922cbbc6755SHarald Freudenberger 		.import	  = phmac_import,				\
923cbbc6755SHarald Freudenberger 		.export	  = phmac_export,				\
924cbbc6755SHarald Freudenberger 		.init_tfm = phmac_init_tfm,				\
925cbbc6755SHarald Freudenberger 		.exit_tfm = phmac_exit_tfm,				\
926cbbc6755SHarald Freudenberger 		.halg = {						\
927cbbc6755SHarald Freudenberger 			.digestsize = SHA##x##_DIGEST_SIZE,		\
928cbbc6755SHarald Freudenberger 			.statesize  = sizeof(struct kmac_sha2_ctx),	\
929cbbc6755SHarald Freudenberger 			.base = {					\
930cbbc6755SHarald Freudenberger 				.cra_name = "phmac(sha" #x ")",		\
931cbbc6755SHarald Freudenberger 				.cra_driver_name = "phmac_s390_sha" #x,	\
932cbbc6755SHarald Freudenberger 				.cra_blocksize = SHA##x##_BLOCK_SIZE,	\
933cbbc6755SHarald Freudenberger 				.cra_priority = 400,			\
934cbbc6755SHarald Freudenberger 				.cra_flags = CRYPTO_ALG_ASYNC |		\
935cbbc6755SHarald Freudenberger 					     CRYPTO_ALG_NO_FALLBACK,	\
936cbbc6755SHarald Freudenberger 				.cra_ctxsize = sizeof(struct phmac_tfm_ctx), \
937cbbc6755SHarald Freudenberger 				.cra_module = THIS_MODULE,		\
938cbbc6755SHarald Freudenberger 			},						\
939cbbc6755SHarald Freudenberger 		},							\
940cbbc6755SHarald Freudenberger 	},								\
941cbbc6755SHarald Freudenberger 	.op = {								\
942cbbc6755SHarald Freudenberger 		.do_one_request = phmac_do_one_request,			\
943cbbc6755SHarald Freudenberger 	},								\
944cbbc6755SHarald Freudenberger }
945cbbc6755SHarald Freudenberger 
946cbbc6755SHarald Freudenberger static struct phmac_alg {
947cbbc6755SHarald Freudenberger 	unsigned int fc;
948cbbc6755SHarald Freudenberger 	struct ahash_engine_alg alg;
949cbbc6755SHarald Freudenberger 	bool registered;
950cbbc6755SHarald Freudenberger } phmac_algs[] = {
951cbbc6755SHarald Freudenberger 	{
952cbbc6755SHarald Freudenberger 		.fc = CPACF_KMAC_PHMAC_SHA_224,
953cbbc6755SHarald Freudenberger 		.alg = S390_ASYNC_PHMAC_ALG(224),
954cbbc6755SHarald Freudenberger 	}, {
955cbbc6755SHarald Freudenberger 		.fc = CPACF_KMAC_PHMAC_SHA_256,
956cbbc6755SHarald Freudenberger 		.alg = S390_ASYNC_PHMAC_ALG(256),
957cbbc6755SHarald Freudenberger 	}, {
958cbbc6755SHarald Freudenberger 		.fc = CPACF_KMAC_PHMAC_SHA_384,
959cbbc6755SHarald Freudenberger 		.alg = S390_ASYNC_PHMAC_ALG(384),
960cbbc6755SHarald Freudenberger 	}, {
961cbbc6755SHarald Freudenberger 		.fc = CPACF_KMAC_PHMAC_SHA_512,
962cbbc6755SHarald Freudenberger 		.alg = S390_ASYNC_PHMAC_ALG(512),
963cbbc6755SHarald Freudenberger 	}
964cbbc6755SHarald Freudenberger };
965cbbc6755SHarald Freudenberger 
966cbbc6755SHarald Freudenberger static struct miscdevice phmac_dev = {
967cbbc6755SHarald Freudenberger 	.name	= "phmac",
968cbbc6755SHarald Freudenberger 	.minor	= MISC_DYNAMIC_MINOR,
969cbbc6755SHarald Freudenberger };
970cbbc6755SHarald Freudenberger 
s390_phmac_exit(void)971cbbc6755SHarald Freudenberger static void s390_phmac_exit(void)
972cbbc6755SHarald Freudenberger {
973cbbc6755SHarald Freudenberger 	struct phmac_alg *phmac;
974cbbc6755SHarald Freudenberger 	int i;
975cbbc6755SHarald Freudenberger 
976cbbc6755SHarald Freudenberger 	if (phmac_crypto_engine) {
977cbbc6755SHarald Freudenberger 		crypto_engine_stop(phmac_crypto_engine);
978cbbc6755SHarald Freudenberger 		crypto_engine_exit(phmac_crypto_engine);
979cbbc6755SHarald Freudenberger 	}
980cbbc6755SHarald Freudenberger 
981cbbc6755SHarald Freudenberger 	for (i = ARRAY_SIZE(phmac_algs) - 1; i >= 0; i--) {
982cbbc6755SHarald Freudenberger 		phmac = &phmac_algs[i];
983cbbc6755SHarald Freudenberger 		if (phmac->registered)
984cbbc6755SHarald Freudenberger 			crypto_engine_unregister_ahash(&phmac->alg);
985cbbc6755SHarald Freudenberger 	}
986cbbc6755SHarald Freudenberger 
987cbbc6755SHarald Freudenberger 	misc_deregister(&phmac_dev);
988cbbc6755SHarald Freudenberger }
989cbbc6755SHarald Freudenberger 
s390_phmac_init(void)990cbbc6755SHarald Freudenberger static int __init s390_phmac_init(void)
991cbbc6755SHarald Freudenberger {
992cbbc6755SHarald Freudenberger 	struct phmac_alg *phmac;
993cbbc6755SHarald Freudenberger 	int i, rc;
994cbbc6755SHarald Freudenberger 
995d48b2f5eSHarald Freudenberger 	/* for selftest cpacf klmd subfunction is needed */
996d48b2f5eSHarald Freudenberger 	if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_256))
997d48b2f5eSHarald Freudenberger 		return -ENODEV;
998d48b2f5eSHarald Freudenberger 	if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_512))
999d48b2f5eSHarald Freudenberger 		return -ENODEV;
1000d48b2f5eSHarald Freudenberger 
1001cbbc6755SHarald Freudenberger 	/* register a simple phmac pseudo misc device */
1002cbbc6755SHarald Freudenberger 	rc = misc_register(&phmac_dev);
1003cbbc6755SHarald Freudenberger 	if (rc)
1004cbbc6755SHarald Freudenberger 		return rc;
1005cbbc6755SHarald Freudenberger 
1006cbbc6755SHarald Freudenberger 	/* with this pseudo device alloc and start a crypto engine */
1007cbbc6755SHarald Freudenberger 	phmac_crypto_engine =
1008cbbc6755SHarald Freudenberger 		crypto_engine_alloc_init_and_set(phmac_dev.this_device,
1009*c470ffa6SOvidiu Panait 						 true, false, MAX_QLEN);
1010cbbc6755SHarald Freudenberger 	if (!phmac_crypto_engine) {
1011cbbc6755SHarald Freudenberger 		rc = -ENOMEM;
1012cbbc6755SHarald Freudenberger 		goto out_err;
1013cbbc6755SHarald Freudenberger 	}
1014cbbc6755SHarald Freudenberger 	rc = crypto_engine_start(phmac_crypto_engine);
1015cbbc6755SHarald Freudenberger 	if (rc) {
1016cbbc6755SHarald Freudenberger 		crypto_engine_exit(phmac_crypto_engine);
1017cbbc6755SHarald Freudenberger 		phmac_crypto_engine = NULL;
1018cbbc6755SHarald Freudenberger 		goto out_err;
1019cbbc6755SHarald Freudenberger 	}
1020cbbc6755SHarald Freudenberger 
1021cbbc6755SHarald Freudenberger 	for (i = 0; i < ARRAY_SIZE(phmac_algs); i++) {
1022cbbc6755SHarald Freudenberger 		phmac = &phmac_algs[i];
1023cbbc6755SHarald Freudenberger 		if (!cpacf_query_func(CPACF_KMAC, phmac->fc))
1024cbbc6755SHarald Freudenberger 			continue;
1025cbbc6755SHarald Freudenberger 		rc = crypto_engine_register_ahash(&phmac->alg);
1026cbbc6755SHarald Freudenberger 		if (rc)
1027cbbc6755SHarald Freudenberger 			goto out_err;
1028cbbc6755SHarald Freudenberger 		phmac->registered = true;
1029cbbc6755SHarald Freudenberger 		pr_debug("%s registered\n", phmac->alg.base.halg.base.cra_name);
1030cbbc6755SHarald Freudenberger 	}
1031cbbc6755SHarald Freudenberger 
1032cbbc6755SHarald Freudenberger 	return 0;
1033cbbc6755SHarald Freudenberger 
1034cbbc6755SHarald Freudenberger out_err:
1035cbbc6755SHarald Freudenberger 	s390_phmac_exit();
1036cbbc6755SHarald Freudenberger 	return rc;
1037cbbc6755SHarald Freudenberger }
1038cbbc6755SHarald Freudenberger 
1039cbbc6755SHarald Freudenberger module_init(s390_phmac_init);
1040cbbc6755SHarald Freudenberger module_exit(s390_phmac_exit);
1041cbbc6755SHarald Freudenberger 
1042cbbc6755SHarald Freudenberger MODULE_ALIAS_CRYPTO("phmac(sha224)");
1043cbbc6755SHarald Freudenberger MODULE_ALIAS_CRYPTO("phmac(sha256)");
1044cbbc6755SHarald Freudenberger MODULE_ALIAS_CRYPTO("phmac(sha384)");
1045cbbc6755SHarald Freudenberger MODULE_ALIAS_CRYPTO("phmac(sha512)");
1046cbbc6755SHarald Freudenberger 
1047cbbc6755SHarald Freudenberger MODULE_DESCRIPTION("S390 HMAC driver for protected keys");
1048cbbc6755SHarald Freudenberger MODULE_LICENSE("GPL");
1049