Skip to content

Commit

Permalink
s390/zcrypt/pkey: introduce zcrypt_wait_api_operational() function
Browse files Browse the repository at this point in the history
The zcrypt api provides a new function to wait until the zcrypt
api is operational:

  int zcrypt_wait_api_operational(void);

The AP bus scan and the binding of ap devices to device drivers is
an asynchronous job. This function waits until these initial jobs
are done and so the zcrypt api should be ready to serve crypto
requests - if there are resources available. The function uses an
internal timeout of 60s. The very first caller will either wait for
ap bus bindings complete or the timeout happens. This state will be
remembered for further callers which will only be blocked until a
decision is made (timeout or bindings complete).

Reviewed-by: Ingo Franzki <[email protected]>
Signed-off-by: Harald Freudenberger <[email protected]>
Signed-off-by: Heiko Carstens <[email protected]>
  • Loading branch information
hfreude authored and hcahca committed Nov 9, 2020
1 parent 837cd10 commit 43cb5a7
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
15 changes: 15 additions & 0 deletions drivers/s390/crypto/pkey_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey)
u16 cardnr, domain;
struct keytoken_header *hdr = (struct keytoken_header *)key;

zcrypt_wait_api_operational();

/*
* The cca_xxx2protkey call may fail when a card has been
* addressed where the master key was changed after last fetch
Expand Down Expand Up @@ -197,6 +199,8 @@ static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen,
u16 card, dom;
u32 nr_apqns, *apqns = NULL;

zcrypt_wait_api_operational();

/* build a list of apqns suitable for ep11 keys with cpacf support */
rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
ZCRYPT_CEX7, EP11_API_V, NULL);
Expand Down Expand Up @@ -230,6 +234,8 @@ static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey)
u32 nr_apqns, *apqns = NULL;
struct ep11keyblob *kb = (struct ep11keyblob *) key;

zcrypt_wait_api_operational();

/* build a list of apqns suitable for this key */
rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
ZCRYPT_CEX7, EP11_API_V, kb->wkvp);
Expand Down Expand Up @@ -436,6 +442,7 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
if (rc == 0)
break;
/* PCKMO failed, so try the CCA secure key way */
zcrypt_wait_api_operational();
rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype,
ckey.clrkey, tmpbuf);
if (rc == 0)
Expand Down Expand Up @@ -625,6 +632,8 @@ static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns,
return -EINVAL;
}

zcrypt_wait_api_operational();

/* simple try all apqns from the list */
for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
card = apqns[i].card;
Expand Down Expand Up @@ -801,6 +810,8 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
return -EINVAL;
}

zcrypt_wait_api_operational();

/* simple try all apqns from the list */
for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
card = apqns[i].card;
Expand Down Expand Up @@ -838,6 +849,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
if (keylen < sizeof(struct keytoken_header) || flags == 0)
return -EINVAL;

zcrypt_wait_api_operational();

if (hdr->type == TOKTYPE_NON_CCA
&& (hdr->version == TOKVER_EP11_AES_WITH_HEADER
|| hdr->version == TOKVER_EP11_ECC_WITH_HEADER)
Expand Down Expand Up @@ -941,6 +954,8 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype,
int rc;
u32 _nr_apqns, *_apqns = NULL;

zcrypt_wait_api_operational();

if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) {
u64 cur_mkvp = 0, old_mkvp = 0;
int minhwtype = ZCRYPT_CEX3C;
Expand Down
66 changes: 66 additions & 0 deletions drivers/s390/crypto/zcrypt_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1992,6 +1992,72 @@ void zcrypt_rng_device_remove(void)
mutex_unlock(&zcrypt_rng_mutex);
}

/*
* Wait until the zcrypt api is operational.
* The AP bus scan and the binding of ap devices to device drivers is
* an asynchronous job. This function waits until these initial jobs
* are done and so the zcrypt api should be ready to serve crypto
* requests - if there are resources available. The function uses an
* internal timeout of 60s. The very first caller will either wait for
* ap bus bindings complete or the timeout happens. This state will be
* remembered for further callers which will only be blocked until a
* decision is made (timeout or bindings complete).
* On timeout -ETIME is returned, on success the return value is 0.
*/
int zcrypt_wait_api_operational(void)
{
static DEFINE_MUTEX(zcrypt_wait_api_lock);
static int zcrypt_wait_api_state;
int rc;

rc = mutex_lock_interruptible(&zcrypt_wait_api_lock);
if (rc)
return rc;

switch (zcrypt_wait_api_state) {
case 0:
/* initial state, invoke wait for the ap bus complete */
rc = ap_wait_init_apqn_bindings_complete(
msecs_to_jiffies(60 * 1000));
switch (rc) {
case 0:
/* ap bus bindings are complete */
zcrypt_wait_api_state = 1;
break;
case -EINTR:
/* interrupted, go back to caller */
break;
case -ETIME:
/* timeout */
ZCRYPT_DBF(DBF_WARN,
"%s ap_wait_init_apqn_bindings_complete() returned with ETIME\n",
__func__);
zcrypt_wait_api_state = -ETIME;
break;
default:
/* other failure */
ZCRYPT_DBF(DBF_DEBUG,
"%s ap_wait_init_apqn_bindings_complete() failure rc=%d\n",
__func__, rc);
break;
}
break;
case 1:
/* a previous caller already found ap bus bindings complete */
rc = 0;
break;
default:
/* a previous caller had timeout or other failure */
rc = zcrypt_wait_api_state;
break;
}

mutex_unlock(&zcrypt_wait_api_lock);

return rc;
}
EXPORT_SYMBOL(zcrypt_wait_api_operational);

int __init zcrypt_debug_init(void)
{
zcrypt_dbf_info = debug_register("zcrypt", 1, 1,
Expand Down
2 changes: 2 additions & 0 deletions drivers/s390/crypto/zcrypt_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus);
int zcrypt_device_status_ext(int card, int queue,
struct zcrypt_device_status_ext *devstatus);

int zcrypt_wait_api_operational(void);

static inline unsigned long z_copy_from_user(bool userspace,
void *to,
const void __user *from,
Expand Down

0 comments on commit 43cb5a7

Please sign in to comment.