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:
parent
e1bff843cd
commit
1daafea411
@ -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 :
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user