s390/crypto: improve retry logic in case of master key change
authorHarald Freudenberger <freude@linux.ibm.com>
Fri, 15 Jan 2021 07:56:19 +0000 (08:56 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Wed, 27 Jan 2021 12:00:48 +0000 (13:00 +0100)
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 <freude@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/crypto/paes_s390.c
drivers/s390/crypto/zcrypt_ccamisc.c

index f3caeb1..a279b7d 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
+#include <linux/delay.h>
 #include <crypto/internal/skcipher.h>
 #include <crypto/xts.h>
 #include <asm/cpacf.h>
@@ -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 :
index b104681..d68c0ed 100644 (file)
@@ -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) {