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