From 1daafea411f36cfa52eb58c2e7f9e2254fd42b28 Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Fri, 15 Jan 2021 08:56:19 +0100 Subject: [PATCH] s390/crypto: improve retry logic in case of master key change A master key change on a CCA card may cause an immediately following request to derive an protected key from a secure key to fail with error condition 8/2290. The recommendation from firmware is to retry with 1 second sleep. So now the low level cca functions return -EAGAIN when this error condition is seen and the paes retry function will evaluate the return value. Seeing EAGAIN and running in process context results in trying to sleep for 1 s now. Signed-off-by: Harald Freudenberger Reviewed-by: Ingo Franzki Signed-off-by: Vasily Gorbik --- arch/s390/crypto/paes_s390.c | 28 ++++++++++++++++++++-------- drivers/s390/crypto/zcrypt_ccamisc.c | 15 ++++++++++++--- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/arch/s390/crypto/paes_s390.c b/arch/s390/crypto/paes_s390.c index f3caeb17c85b..a279b7d23a5e 100644 --- a/arch/s390/crypto/paes_s390.c +++ b/arch/s390/crypto/paes_s390.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,9 @@ static inline int __paes_keyblob2pkey(struct key_blob *kb, /* try three times in case of failure */ for (i = 0; i < 3; i++) { + if (i > 0 && ret == -EAGAIN && in_task()) + if (msleep_interruptible(1000)) + return -EINTR; ret = pkey_keyblob2pkey(kb->key, kb->keylen, pk); if (ret == 0) break; @@ -138,10 +142,12 @@ static inline int __paes_keyblob2pkey(struct key_blob *kb, static inline int __paes_convert_key(struct s390_paes_ctx *ctx) { + int ret; struct pkey_protkey pkey; - if (__paes_keyblob2pkey(&ctx->kb, &pkey)) - return -EINVAL; + ret = __paes_keyblob2pkey(&ctx->kb, &pkey); + if (ret) + return ret; spin_lock_bh(&ctx->pk_lock); memcpy(&ctx->pk, &pkey, sizeof(pkey)); @@ -169,10 +175,12 @@ static void ecb_paes_exit(struct crypto_skcipher *tfm) static inline int __ecb_paes_set_key(struct s390_paes_ctx *ctx) { + int rc; unsigned long fc; - if (__paes_convert_key(ctx)) - return -EINVAL; + rc = __paes_convert_key(ctx); + if (rc) + return rc; /* Pick the correct function code based on the protected key type */ fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KM_PAES_128 : @@ -282,10 +290,12 @@ static void cbc_paes_exit(struct crypto_skcipher *tfm) static inline int __cbc_paes_set_key(struct s390_paes_ctx *ctx) { + int rc; unsigned long fc; - if (__paes_convert_key(ctx)) - return -EINVAL; + rc = __paes_convert_key(ctx); + if (rc) + return rc; /* Pick the correct function code based on the protected key type */ fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KMC_PAES_128 : @@ -577,10 +587,12 @@ static void ctr_paes_exit(struct crypto_skcipher *tfm) static inline int __ctr_paes_set_key(struct s390_paes_ctx *ctx) { + int rc; unsigned long fc; - if (__paes_convert_key(ctx)) - return -EINVAL; + rc = __paes_convert_key(ctx); + if (rc) + return rc; /* Pick the correct function code based on the protected key type */ fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KMCTR_PAES_128 : diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index b1046811450f..d68c0ed5e0dd 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -662,7 +662,10 @@ int cca_sec2protkey(u16 cardnr, u16 domain, __func__, (int) prepcblk->ccp_rtcode, (int) prepcblk->ccp_rscode); - rc = -EIO; + if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290) + rc = -EAGAIN; + else + rc = -EIO; goto out; } if (prepcblk->ccp_rscode != 0) { @@ -1275,7 +1278,10 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey, __func__, (int) prepcblk->ccp_rtcode, (int) prepcblk->ccp_rscode); - rc = -EIO; + if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290) + rc = -EAGAIN; + else + rc = -EIO; goto out; } if (prepcblk->ccp_rscode != 0) { @@ -1441,7 +1447,10 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key, __func__, (int) prepcblk->ccp_rtcode, (int) prepcblk->ccp_rscode); - rc = -EIO; + if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290) + rc = -EAGAIN; + else + rc = -EIO; goto out; } if (prepcblk->ccp_rscode != 0) {