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, ¶m, in, inlen);
242d48b2f5eSHarald Freudenberger
243d48b2f5eSHarald Freudenberger memcpy(digest, ¶m, 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