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