Commit 1daafea4 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Vasily Gorbik
Browse files

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: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarIngo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent e1bff843
Loading
Loading
Loading
Loading
+20 −8
Original line number Diff line number Diff line
@@ -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 :
+12 −3
Original line number Diff line number Diff line
@@ -662,6 +662,9 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
			  __func__,
			  (int) prepcblk->ccp_rtcode,
			  (int) prepcblk->ccp_rscode);
		if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
			rc = -EAGAIN;
		else
			rc = -EIO;
		goto out;
	}
@@ -1275,6 +1278,9 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
			__func__,
			(int) prepcblk->ccp_rtcode,
			(int) prepcblk->ccp_rscode);
		if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
			rc = -EAGAIN;
		else
			rc = -EIO;
		goto out;
	}
@@ -1441,6 +1447,9 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
			__func__,
			(int) prepcblk->ccp_rtcode,
			(int) prepcblk->ccp_rscode);
		if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
			rc = -EAGAIN;
		else
			rc = -EIO;
		goto out;
	}