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 <freude@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
Harald Freudenberger 2021-01-15 08:56:19 +01:00 committed by Vasily Gorbik
parent e1bff843cd
commit 1daafea411
2 changed files with 32 additions and 11 deletions

View File

@ -22,6 +22,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/delay.h>
#include <crypto/internal/skcipher.h> #include <crypto/internal/skcipher.h>
#include <crypto/xts.h> #include <crypto/xts.h>
#include <asm/cpacf.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 */ /* try three times in case of failure */
for (i = 0; i < 3; i++) { 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); ret = pkey_keyblob2pkey(kb->key, kb->keylen, pk);
if (ret == 0) if (ret == 0)
break; 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) static inline int __paes_convert_key(struct s390_paes_ctx *ctx)
{ {
int ret;
struct pkey_protkey pkey; struct pkey_protkey pkey;
if (__paes_keyblob2pkey(&ctx->kb, &pkey)) ret = __paes_keyblob2pkey(&ctx->kb, &pkey);
return -EINVAL; if (ret)
return ret;
spin_lock_bh(&ctx->pk_lock); spin_lock_bh(&ctx->pk_lock);
memcpy(&ctx->pk, &pkey, sizeof(pkey)); 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) static inline int __ecb_paes_set_key(struct s390_paes_ctx *ctx)
{ {
int rc;
unsigned long fc; unsigned long fc;
if (__paes_convert_key(ctx)) rc = __paes_convert_key(ctx);
return -EINVAL; if (rc)
return rc;
/* Pick the correct function code based on the protected key type */ /* Pick the correct function code based on the protected key type */
fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KM_PAES_128 : 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) static inline int __cbc_paes_set_key(struct s390_paes_ctx *ctx)
{ {
int rc;
unsigned long fc; unsigned long fc;
if (__paes_convert_key(ctx)) rc = __paes_convert_key(ctx);
return -EINVAL; if (rc)
return rc;
/* Pick the correct function code based on the protected key type */ /* Pick the correct function code based on the protected key type */
fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KMC_PAES_128 : 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) static inline int __ctr_paes_set_key(struct s390_paes_ctx *ctx)
{ {
int rc;
unsigned long fc; unsigned long fc;
if (__paes_convert_key(ctx)) rc = __paes_convert_key(ctx);
return -EINVAL; if (rc)
return rc;
/* Pick the correct function code based on the protected key type */ /* Pick the correct function code based on the protected key type */
fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KMCTR_PAES_128 : fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KMCTR_PAES_128 :

View File

@ -662,7 +662,10 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
__func__, __func__,
(int) prepcblk->ccp_rtcode, (int) prepcblk->ccp_rtcode,
(int) prepcblk->ccp_rscode); (int) prepcblk->ccp_rscode);
rc = -EIO; if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
rc = -EAGAIN;
else
rc = -EIO;
goto out; goto out;
} }
if (prepcblk->ccp_rscode != 0) { if (prepcblk->ccp_rscode != 0) {
@ -1275,7 +1278,10 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
__func__, __func__,
(int) prepcblk->ccp_rtcode, (int) prepcblk->ccp_rtcode,
(int) prepcblk->ccp_rscode); (int) prepcblk->ccp_rscode);
rc = -EIO; if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
rc = -EAGAIN;
else
rc = -EIO;
goto out; goto out;
} }
if (prepcblk->ccp_rscode != 0) { if (prepcblk->ccp_rscode != 0) {
@ -1441,7 +1447,10 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
__func__, __func__,
(int) prepcblk->ccp_rtcode, (int) prepcblk->ccp_rtcode,
(int) prepcblk->ccp_rscode); (int) prepcblk->ccp_rscode);
rc = -EIO; if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
rc = -EAGAIN;
else
rc = -EIO;
goto out; goto out;
} }
if (prepcblk->ccp_rscode != 0) { if (prepcblk->ccp_rscode != 0) {