Commit f2bbc96e authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Vasily Gorbik

s390/pkey: add CCA AES cipher key support

Introduce new ioctls and structs to be used with these new ioctls
which are able to handle CCA AES secure keys and CCA AES cipher keys:

PKEY_GENSECK2: Generate secure key, version 2.
  Generate either a CCA AES secure key or a CCA AES cipher key.

PKEY_CLR2SECK2: Generate secure key from clear key value, version 2.
  Construct a CCA AES secure key or CCA AES cipher key from a given
  clear key value.

PKEY_VERIFYKEY2: Verify the given secure key, version 2.
  Check for correct key type. If cardnr and domain are given, also
  check if this apqn is able to handle this type of key. If cardnr and
  domain are 0xFFFF, on return these values are filled with an apqn
  able to handle this key. The function also checks for the master key
  verification patterns of the key matching to the current or
  alternate mkvp of the apqn. CCA AES cipher keys are also checked
  for CPACF export allowed (CPRTCPAC flag). Currently CCA AES secure
  keys and CCA AES cipher keys are supported (may get extended in the
  future).

PKEY_KBLOB2PROTK2: Transform a key blob (of any type) into
  a protected key, version 2. Difference to version 1 is only that
  this new ioctl has additional parameters to provide a list of
  apqns to be used for the transformation.

PKEY_APQNS4K: Generate a list of APQNs based on the key blob given.
  Is able to find out which type of secure key is given (CCA AES
  secure key or CCA AES cipher key) and tries to find all matching
  crypto cards based on the MKVP and maybe other criterias (like CCA
  AES cipher keys need a CEX6C or higher). The list of APQNs is
  further filtered by the key's mkvp which needs to match to either
  the current mkvp or the alternate mkvp (which is the old mkvp on CCA
  adapters) of the apqns. The flags argument may be used to limit the
  matching apqns. If the PKEY_FLAGS_MATCH_CUR_MKVP is given, only the
  current mkvp of each apqn is compared. Likewise with the
  PKEY_FLAGS_MATCH_ALT_MKVP. If both are given it is assumed to return
  apqns where either the current or the alternate mkvp matches. If no
  matching APQN is found, the ioctl returns with 0 but the
  apqn_entries value is 0.

PKEY_APQNS4KT: Generate a list of APQNs based on the key type given.
  Build a list of APQNs based on the given key type and maybe further
  restrict the list by given master key verification patterns.
  For different key types there may be different ways to match the
  master key verification patterns. For CCA keys (CCA data key and CCA
  cipher key) the first 8 bytes of cur_mkvp refer to the current mkvp
  value of the apqn and the first 8 bytes of the alt_mkvp refer to the
  old mkvp. The flags argument controls if the apqns current and/or
  alternate mkvp should match. If the PKEY_FLAGS_MATCH_CUR_MKVP is
  given, only the current mkvp of each apqn is compared. Likewise with
  the PKEY_FLAGS_MATCH_ALT_MKVP. If both are given, it is assumed to
  return apqns where either the current or the alternate mkvp
  matches. If no matching APQN is found, the ioctl returns with 0 but
  the apqn_entries value is 0.

These new ioctls are now prepared for another new type of secure key
blob which may come in the future. They all use a pointer to the key
blob and a key blob length information instead of some hardcoded byte
array. They all use the new enums pkey_key_type, pkey_key_size and
pkey_key_info for getting/setting key type, key size and additional
info about the key. All but the PKEY_VERIFY2 ioctl now work based on a
list of apqns. This list is walked through trying to perform the
operation on exactly this apqn without any further checking (like card
type or online state). If the apqn fails, simple the next one in the
list is tried until success (return 0) or the end of the list is
reached (return -1 with errno ENODEV). All apqns in the list need to
be exact apqns (0xFFFF as any card or domain is not allowed). There
are two new ioctls which can be used to build a list of apqns based on
a key or key type and maybe restricted by match to a current or
alternate master key verifcation pattern.
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 4bc123b1
This diff is collapsed.
This diff is collapsed.
...@@ -270,7 +270,7 @@ static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb) ...@@ -270,7 +270,7 @@ static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb)
* Generate (random) CCA AES DATA secure key. * Generate (random) CCA AES DATA secure key.
*/ */
int cca_genseckey(u16 cardnr, u16 domain, int cca_genseckey(u16 cardnr, u16 domain,
u32 keytype, u8 seckey[SECKEYBLOBSIZE]) u32 keybitsize, u8 seckey[SECKEYBLOBSIZE])
{ {
int i, rc, keysize; int i, rc, keysize;
int seckeysize; int seckeysize;
...@@ -325,22 +325,25 @@ int cca_genseckey(u16 cardnr, u16 domain, ...@@ -325,22 +325,25 @@ int cca_genseckey(u16 cardnr, u16 domain,
preqparm->rule_array_len = sizeof(preqparm->rule_array_len); preqparm->rule_array_len = sizeof(preqparm->rule_array_len);
preqparm->lv1.len = sizeof(struct lv1); preqparm->lv1.len = sizeof(struct lv1);
memcpy(preqparm->lv1.key_form, "OP ", 8); memcpy(preqparm->lv1.key_form, "OP ", 8);
switch (keytype) { switch (keybitsize) {
case PKEY_KEYTYPE_AES_128: case PKEY_SIZE_AES_128:
case PKEY_KEYTYPE_AES_128: /* older ioctls used this */
keysize = 16; keysize = 16;
memcpy(preqparm->lv1.key_length, "KEYLN16 ", 8); memcpy(preqparm->lv1.key_length, "KEYLN16 ", 8);
break; break;
case PKEY_KEYTYPE_AES_192: case PKEY_SIZE_AES_192:
case PKEY_KEYTYPE_AES_192: /* older ioctls used this */
keysize = 24; keysize = 24;
memcpy(preqparm->lv1.key_length, "KEYLN24 ", 8); memcpy(preqparm->lv1.key_length, "KEYLN24 ", 8);
break; break;
case PKEY_KEYTYPE_AES_256: case PKEY_SIZE_AES_256:
case PKEY_KEYTYPE_AES_256: /* older ioctls used this */
keysize = 32; keysize = 32;
memcpy(preqparm->lv1.key_length, "KEYLN32 ", 8); memcpy(preqparm->lv1.key_length, "KEYLN32 ", 8);
break; break;
default: default:
DEBUG_ERR("%s unknown/unsupported keytype %d\n", DEBUG_ERR("%s unknown/unsupported keybitsize %d\n",
__func__, keytype); __func__, keybitsize);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
...@@ -408,7 +411,7 @@ EXPORT_SYMBOL(cca_genseckey); ...@@ -408,7 +411,7 @@ EXPORT_SYMBOL(cca_genseckey);
/* /*
* Generate an CCA AES DATA secure key with given key value. * Generate an CCA AES DATA secure key with given key value.
*/ */
int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
const u8 *clrkey, u8 seckey[SECKEYBLOBSIZE]) const u8 *clrkey, u8 seckey[SECKEYBLOBSIZE])
{ {
int rc, keysize, seckeysize; int rc, keysize, seckeysize;
...@@ -462,19 +465,22 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, ...@@ -462,19 +465,22 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype,
memcpy(preqparm->rule_array, "AES ", 8); memcpy(preqparm->rule_array, "AES ", 8);
preqparm->rule_array_len = preqparm->rule_array_len =
sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array);
switch (keytype) { switch (keybitsize) {
case PKEY_KEYTYPE_AES_128: case PKEY_SIZE_AES_128:
case PKEY_KEYTYPE_AES_128: /* older ioctls used this */
keysize = 16; keysize = 16;
break; break;
case PKEY_KEYTYPE_AES_192: case PKEY_SIZE_AES_192:
case PKEY_KEYTYPE_AES_192: /* older ioctls used this */
keysize = 24; keysize = 24;
break; break;
case PKEY_KEYTYPE_AES_256: case PKEY_SIZE_AES_256:
case PKEY_KEYTYPE_AES_256: /* older ioctls used this */
keysize = 32; keysize = 32;
break; break;
default: default:
DEBUG_ERR("%s unknown/unsupported keytype %d\n", DEBUG_ERR("%s unknown/unsupported keybitsize %d\n",
__func__, keytype); __func__, keybitsize);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
...@@ -545,8 +551,7 @@ EXPORT_SYMBOL(cca_clr2seckey); ...@@ -545,8 +551,7 @@ EXPORT_SYMBOL(cca_clr2seckey);
*/ */
int cca_sec2protkey(u16 cardnr, u16 domain, int cca_sec2protkey(u16 cardnr, u16 domain,
const u8 seckey[SECKEYBLOBSIZE], const u8 seckey[SECKEYBLOBSIZE],
u8 *protkey, u32 *protkeylen, u8 *protkey, u32 *protkeylen, u32 *protkeytype)
u32 *keytype)
{ {
int rc; int rc;
u8 *mem; u8 *mem;
...@@ -656,21 +661,21 @@ int cca_sec2protkey(u16 cardnr, u16 domain, ...@@ -656,21 +661,21 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
switch (prepparm->lv3.keyblock.len) { switch (prepparm->lv3.keyblock.len) {
case 16+32: case 16+32:
/* AES 128 protected key */ /* AES 128 protected key */
if (keytype) if (protkeytype)
*keytype = PKEY_KEYTYPE_AES_128; *protkeytype = PKEY_KEYTYPE_AES_128;
break; break;
case 24+32: case 24+32:
/* AES 192 protected key */ /* AES 192 protected key */
if (keytype) if (protkeytype)
*keytype = PKEY_KEYTYPE_AES_192; *protkeytype = PKEY_KEYTYPE_AES_192;
break; break;
case 32+32: case 32+32:
/* AES 256 protected key */ /* AES 256 protected key */
if (keytype) if (protkeytype)
*keytype = PKEY_KEYTYPE_AES_256; *protkeytype = PKEY_KEYTYPE_AES_256;
break; break;
default: default:
DEBUG_ERR("%s unknown/unsupported keytype %d\n", DEBUG_ERR("%s unknown/unsupported keylen %d\n",
__func__, prepparm->lv3.keyblock.len); __func__, prepparm->lv3.keyblock.len);
rc = -EIO; rc = -EIO;
goto out; goto out;
...@@ -1645,6 +1650,7 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain, ...@@ -1645,6 +1650,7 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain,
int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify) int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify)
{ {
u64 mkvp; u64 mkvp;
int minhwtype = 0;
const struct keytoken_header *hdr = (struct keytoken_header *) key; const struct keytoken_header *hdr = (struct keytoken_header *) key;
if (hdr->type != TOKTYPE_CCA_INTERNAL) if (hdr->type != TOKTYPE_CCA_INTERNAL)
...@@ -1654,11 +1660,15 @@ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify) ...@@ -1654,11 +1660,15 @@ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify)
case TOKVER_CCA_AES: case TOKVER_CCA_AES:
mkvp = ((struct secaeskeytoken *)key)->mkvp; mkvp = ((struct secaeskeytoken *)key)->mkvp;
break; break;
case TOKVER_CCA_VLSC:
mkvp = ((struct cipherkeytoken *)key)->mkvp0;
minhwtype = AP_DEVICE_TYPE_CEX6;
break;
default: default:
return -EINVAL; return -EINVAL;
} }
return findcard(mkvp, pcardnr, pdomain, verify, 0); return findcard(mkvp, pcardnr, pdomain, verify, minhwtype);
} }
EXPORT_SYMBOL(cca_findcard); EXPORT_SYMBOL(cca_findcard);
......
...@@ -124,12 +124,12 @@ int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl, ...@@ -124,12 +124,12 @@ int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl,
/* /*
* Generate (random) CCA AES DATA secure key. * Generate (random) CCA AES DATA secure key.
*/ */
int cca_genseckey(u16 cardnr, u16 domain, u32 keytype, u8 *seckey); int cca_genseckey(u16 cardnr, u16 domain, u32 keybitsize, u8 *seckey);
/* /*
* Generate CCA AES DATA secure key with given clear key value. * Generate CCA AES DATA secure key with given clear key value.
*/ */
int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
const u8 *clrkey, u8 *seckey); const u8 *clrkey, u8 *seckey);
/* /*
...@@ -137,8 +137,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, ...@@ -137,8 +137,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype,
*/ */
int cca_sec2protkey(u16 cardnr, u16 domain, int cca_sec2protkey(u16 cardnr, u16 domain,
const u8 seckey[SECKEYBLOBSIZE], const u8 seckey[SECKEYBLOBSIZE],
u8 *protkey, u32 *protkeylen, u8 *protkey, u32 *protkeylen, u32 *protkeytype);
u32 *protkeytype);
/* /*
* Generate (random) CCA AES CIPHER secure key. * Generate (random) CCA AES CIPHER secure key.
...@@ -169,6 +168,7 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain, ...@@ -169,6 +168,7 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
/* /*
* Search for a matching crypto card based on the Master Key * Search for a matching crypto card based on the Master Key
* Verification Pattern provided inside a secure key. * Verification Pattern provided inside a secure key.
* Works with CCA AES data and cipher keys.
* Returns < 0 on failure, 0 if CURRENT MKVP matches and * Returns < 0 on failure, 0 if CURRENT MKVP matches and
* 1 if OLD MKVP matches. * 1 if OLD MKVP matches.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment