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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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