diff options
Diffstat (limited to 'drivers/s390/crypto/pkey_api.c')
-rw-r--r-- | drivers/s390/crypto/pkey_api.c | 418 |
1 files changed, 331 insertions, 87 deletions
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 2f33c5fcf676..5a05d1cdfec2 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -31,11 +31,9 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("s390 protected key interface"); -#define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ -#define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ - -/* mask of available pckmo subfunctions, fetched once at module init */ -static cpacf_mask_t pckmo_functions; +#define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ +#define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */ +#define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ /* * debug feature data and functions @@ -80,7 +78,7 @@ struct clearaeskeytoken { u8 res1[3]; u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ u32 len; /* bytes actually stored in clearkey[] */ - u8 clearkey[0]; /* clear key value */ + u8 clearkey[]; /* clear key value */ } __packed; /* @@ -90,6 +88,9 @@ static int pkey_clr2protkey(u32 keytype, const struct pkey_clrkey *clrkey, struct pkey_protkey *protkey) { + /* mask of available pckmo subfunctions */ + static cpacf_mask_t pckmo_functions; + long fc; int keysize; u8 paramblock[64]; @@ -113,11 +114,13 @@ static int pkey_clr2protkey(u32 keytype, return -EINVAL; } - /* - * Check if the needed pckmo subfunction is available. - * These subfunctions can be enabled/disabled by customers - * in the LPAR profile or may even change on the fly. - */ + /* Did we already check for PCKMO ? */ + if (!pckmo_functions.bytes[0]) { + /* no, so check now */ + if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) + return -ENODEV; + } + /* check for the pckmo subfunction we need now */ if (!cpacf_test_func(&pckmo_functions, fc)) { DEBUG_ERR("%s pckmo functions not available\n", __func__); return -ENODEV; @@ -147,10 +150,12 @@ 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 - * of the mkvp into the cache. Try 3 times: First witout verify + * of the mkvp into the cache. Try 3 times: First without verify * then with verify and last round with verify and old master * key verification pattern match not ignored. */ @@ -194,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); @@ -225,7 +232,9 @@ static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) int i, rc; u16 card, dom; u32 nr_apqns, *apqns = NULL; - struct ep11keyblob *kb = (struct ep11keyblob *) key; + 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, @@ -237,8 +246,9 @@ static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { card = apqns[i] >> 16; dom = apqns[i] & 0xFFFF; - rc = ep11_key2protkey(card, dom, key, kb->head.len, - pkey->protkey, &pkey->len, &pkey->type); + pkey->len = sizeof(pkey->protkey); + rc = ep11_kblob2protkey(card, dom, key, kb->head.len, + pkey->protkey, &pkey->len, &pkey->type); if (rc == 0) break; } @@ -257,12 +267,12 @@ static int pkey_verifykey(const struct pkey_seckey *seckey, u16 *pcardnr, u16 *pdomain, u16 *pkeysize, u32 *pattributes) { - struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; + struct secaeskeytoken *t = (struct secaeskeytoken *)seckey; u16 cardnr, domain; int rc; /* check the secure key for valid AES secure key */ - rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *) seckey, 0); + rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *)seckey, 0); if (rc) goto out; if (pattributes) @@ -415,9 +425,9 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, t = (struct clearaeskeytoken *)key; if (keylen != sizeof(*t) + t->len) goto out; - if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) - || (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) - || (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) + if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) || + (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) || + (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) memcpy(ckey.clrkey, t->clearkey, t->len); else goto out; @@ -432,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) @@ -449,15 +460,21 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, break; } case TOKVER_EP11_AES: { - if (keylen < MINEP11AESKEYBLOBSIZE) - goto out; /* check ep11 key for exportable as protected key */ - rc = ep11_check_aeskeyblob(debug_info, 3, key, 0, 1); + rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); if (rc) goto out; rc = pkey_ep11key2pkey(key, protkey); break; } + case TOKVER_EP11_AES_WITH_HEADER: + /* check ep11 key with header for exportable as protected key */ + rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1); + if (rc) + goto out; + rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header), + protkey); + break; default: DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", __func__, hdr->version); @@ -524,7 +541,6 @@ int pkey_keyblob2pkey(const u8 *key, u32 keylen, DEBUG_DBG("%s rc=%d\n", __func__, rc); return rc; - } EXPORT_SYMBOL(pkey_keyblob2pkey); @@ -571,9 +587,11 @@ static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, } else if (ktype == PKEY_TYPE_CCA_DATA) { rc = cca_genseckey(card, dom, ksize, keybuf); *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); - } else /* TOKVER_CCA_VLSC */ + } else { + /* TOKVER_CCA_VLSC */ rc = cca_gencipherkey(card, dom, ksize, kflags, keybuf, keybufsize); + } if (rc == 0) break; } @@ -615,6 +633,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; @@ -626,9 +646,11 @@ static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, rc = cca_clr2seckey(card, dom, ksize, clrkey, keybuf); *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); - } else /* TOKVER_CCA_VLSC */ + } else { + /* TOKVER_CCA_VLSC */ rc = cca_clr2cipherkey(card, dom, ksize, kflags, clrkey, keybuf, keybufsize); + } if (rc == 0) break; } @@ -648,8 +670,8 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, if (keylen < sizeof(struct keytoken_header)) return -EINVAL; - if (hdr->type == TOKTYPE_CCA_INTERNAL - && hdr->version == TOKVER_CCA_AES) { + if (hdr->type == TOKTYPE_CCA_INTERNAL && + hdr->version == TOKVER_CCA_AES) { struct secaeskeytoken *t = (struct secaeskeytoken *)key; rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); @@ -658,16 +680,17 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, if (ktype) *ktype = PKEY_TYPE_CCA_DATA; if (ksize) - *ksize = (enum pkey_key_size) t->bitsize; + *ksize = (enum pkey_key_size)t->bitsize; rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, - ZCRYPT_CEX3C, t->mkvp, 0, 1); + ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); if (rc == 0 && flags) *flags = PKEY_FLAGS_MATCH_CUR_MKVP; if (rc == -ENODEV) { rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, - ZCRYPT_CEX3C, 0, t->mkvp, 1); + ZCRYPT_CEX3C, AES_MK_SET, + 0, t->mkvp, 1); if (rc == 0 && flags) *flags = PKEY_FLAGS_MATCH_ALT_MKVP; } @@ -677,8 +700,8 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, *cardnr = ((struct pkey_apqn *)_apqns)->card; *domain = ((struct pkey_apqn *)_apqns)->domain; - } else if (hdr->type == TOKTYPE_CCA_INTERNAL - && hdr->version == TOKVER_CCA_VLSC) { + } else if (hdr->type == TOKTYPE_CCA_INTERNAL && + hdr->version == TOKVER_CCA_VLSC) { struct cipherkeytoken *t = (struct cipherkeytoken *)key; rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); @@ -697,13 +720,14 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, } rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, - ZCRYPT_CEX6, t->mkvp0, 0, 1); + ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); if (rc == 0 && flags) *flags = PKEY_FLAGS_MATCH_CUR_MKVP; if (rc == -ENODEV) { rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, - ZCRYPT_CEX6, 0, t->mkvp0, 1); + ZCRYPT_CEX6, AES_MK_SET, + 0, t->mkvp0, 1); if (rc == 0 && flags) *flags = PKEY_FLAGS_MATCH_ALT_MKVP; } @@ -713,11 +737,11 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, *cardnr = ((struct pkey_apqn *)_apqns)->card; *domain = ((struct pkey_apqn *)_apqns)->domain; - } else if (hdr->type == TOKTYPE_NON_CCA - && hdr->version == TOKVER_EP11_AES) { + } else if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_AES) { struct ep11keyblob *kb = (struct ep11keyblob *)key; - rc = ep11_check_aeskeyblob(debug_info, 3, key, 0, 1); + rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); if (rc) goto out; if (ktype) @@ -736,8 +760,9 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, *cardnr = ((struct pkey_apqn *)_apqns)->card; *domain = ((struct pkey_apqn *)_apqns)->domain; - } else + } else { rc = -EINVAL; + } out: kfree(_apqns); @@ -778,7 +803,7 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, if (hdr->version == TOKVER_EP11_AES) { if (keylen < sizeof(struct ep11keyblob)) return -EINVAL; - if (ep11_check_aeskeyblob(debug_info, 3, key, 0, 1)) + if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) return -EINVAL; } else { return pkey_nonccatok2pkey(key, keylen, pkey); @@ -789,24 +814,28 @@ 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; dom = apqns[i].domain; - if (hdr->type == TOKTYPE_CCA_INTERNAL - && hdr->version == TOKVER_CCA_AES) + if (hdr->type == TOKTYPE_CCA_INTERNAL && + hdr->version == TOKVER_CCA_AES) { rc = cca_sec2protkey(card, dom, key, pkey->protkey, &pkey->len, &pkey->type); - else if (hdr->type == TOKTYPE_CCA_INTERNAL - && hdr->version == TOKVER_CCA_VLSC) + } else if (hdr->type == TOKTYPE_CCA_INTERNAL && + hdr->version == TOKVER_CCA_VLSC) { rc = cca_cipher2protkey(card, dom, key, pkey->protkey, &pkey->len, &pkey->type); - else { /* EP11 AES secure key blob */ - struct ep11keyblob *kb = (struct ep11keyblob *) key; + } else { + /* EP11 AES secure key blob */ + struct ep11keyblob *kb = (struct ep11keyblob *)key; - rc = ep11_key2protkey(card, dom, key, kb->head.len, - pkey->protkey, &pkey->len, - &pkey->type); + pkey->len = sizeof(pkey->protkey); + rc = ep11_kblob2protkey(card, dom, key, kb->head.len, + pkey->protkey, &pkey->len, + &pkey->type); } if (rc == 0) break; @@ -818,16 +847,38 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, struct pkey_apqn *apqns, size_t *nr_apqns) { - int rc = EINVAL; + int rc; u32 _nr_apqns, *_apqns = NULL; struct keytoken_header *hdr = (struct keytoken_header *)key; if (keylen < sizeof(struct keytoken_header) || flags == 0) return -EINVAL; - if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES) { + zcrypt_wait_api_operational(); + + if (hdr->type == TOKTYPE_NON_CCA && + (hdr->version == TOKVER_EP11_AES_WITH_HEADER || + hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && + is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { int minhwtype = 0, api = 0; - struct ep11keyblob *kb = (struct ep11keyblob *) key; + struct ep11keyblob *kb = (struct ep11keyblob *) + (key + sizeof(struct ep11kblob_header)); + + if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) + return -EINVAL; + if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { + minhwtype = ZCRYPT_CEX7; + api = EP11_API_V; + } + rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + minhwtype, api, kb->wkvp); + if (rc) + goto out; + } else if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_AES && + is_ep11_keyblob(key)) { + int minhwtype = 0, api = 0; + struct ep11keyblob *kb = (struct ep11keyblob *)key; if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) return -EINVAL; @@ -863,11 +914,31 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, return -EINVAL; } rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - minhwtype, cur_mkvp, old_mkvp, 1); + minhwtype, AES_MK_SET, + cur_mkvp, old_mkvp, 1); if (rc) goto out; - } else + } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { + u64 cur_mkvp = 0, old_mkvp = 0; + struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; + + if (t->secid == 0x20) { + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + cur_mkvp = t->mkvp; + if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) + old_mkvp = t->mkvp; + } else { + /* unknown cca internal 2 token type */ + return -EINVAL; + } + rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + ZCRYPT_CEX7, APKA_MK_SET, + cur_mkvp, old_mkvp, 1); + if (rc) + goto out; + } else { return -EINVAL; + } if (apqns) { if (*nr_apqns < _nr_apqns) @@ -886,24 +957,42 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype, u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, struct pkey_apqn *apqns, size_t *nr_apqns) { - int rc = -EINVAL; + 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; if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) - cur_mkvp = *((u64 *) cur_mkvp); + cur_mkvp = *((u64 *)cur_mkvp); if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) - old_mkvp = *((u64 *) alt_mkvp); + old_mkvp = *((u64 *)alt_mkvp); if (ktype == PKEY_TYPE_CCA_CIPHER) minhwtype = ZCRYPT_CEX6; rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - minhwtype, cur_mkvp, old_mkvp, 1); + minhwtype, AES_MK_SET, + cur_mkvp, old_mkvp, 1); if (rc) goto out; - } else if (ktype == PKEY_TYPE_EP11) { + } else if (ktype == PKEY_TYPE_CCA_ECC) { + u64 cur_mkvp = 0, old_mkvp = 0; + + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + cur_mkvp = *((u64 *)cur_mkvp); + if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) + old_mkvp = *((u64 *)alt_mkvp); + rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + ZCRYPT_CEX7, APKA_MK_SET, + cur_mkvp, old_mkvp, 1); + if (rc) + goto out; + + } else if (ktype == PKEY_TYPE_EP11 || + ktype == PKEY_TYPE_EP11_AES || + ktype == PKEY_TYPE_EP11_ECC) { u8 *wkvp = NULL; if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) @@ -913,8 +1002,9 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype, if (rc) goto out; - } else + } else { return -EINVAL; + } if (apqns) { if (*nr_apqns < _nr_apqns) @@ -929,6 +1019,111 @@ out: return rc; } +static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, + const u8 *key, size_t keylen, u32 *protkeytype, + u8 *protkey, u32 *protkeylen) +{ + int i, card, dom, rc; + struct keytoken_header *hdr = (struct keytoken_header *)key; + + /* check for at least one apqn given */ + if (!apqns || !nr_apqns) + return -EINVAL; + + if (keylen < sizeof(struct keytoken_header)) + return -EINVAL; + + if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_AES_WITH_HEADER && + is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { + /* EP11 AES key blob with header */ + if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1)) + return -EINVAL; + } else if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_ECC_WITH_HEADER && + is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { + /* EP11 ECC key blob with header */ + if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1)) + return -EINVAL; + } else if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_AES && + is_ep11_keyblob(key)) { + /* EP11 AES key blob with header in session field */ + if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) + return -EINVAL; + } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { + if (hdr->version == TOKVER_CCA_AES) { + /* CCA AES data key */ + if (keylen != sizeof(struct secaeskeytoken)) + return -EINVAL; + if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) + return -EINVAL; + } else if (hdr->version == TOKVER_CCA_VLSC) { + /* CCA AES cipher key */ + if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) + return -EINVAL; + if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) + return -EINVAL; + } else { + DEBUG_ERR("%s unknown CCA internal token version %d\n", + __func__, hdr->version); + return -EINVAL; + } + } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { + /* CCA ECC (private) key */ + if (keylen < sizeof(struct eccprivkeytoken)) + return -EINVAL; + if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) + return -EINVAL; + } else if (hdr->type == TOKTYPE_NON_CCA) { + struct pkey_protkey pkey; + + rc = pkey_nonccatok2pkey(key, keylen, &pkey); + if (rc) + return rc; + memcpy(protkey, pkey.protkey, pkey.len); + *protkeylen = pkey.len; + *protkeytype = pkey.type; + return 0; + } else { + DEBUG_ERR("%s unknown/unsupported blob type %d\n", + __func__, hdr->type); + return -EINVAL; + } + + /* simple try all apqns from the list */ + for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { + card = apqns[i].card; + dom = apqns[i].domain; + if (hdr->type == TOKTYPE_NON_CCA && + (hdr->version == TOKVER_EP11_AES_WITH_HEADER || + hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && + is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) + rc = ep11_kblob2protkey(card, dom, key, hdr->len, + protkey, protkeylen, protkeytype); + else if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_AES && + is_ep11_keyblob(key)) + rc = ep11_kblob2protkey(card, dom, key, hdr->len, + protkey, protkeylen, protkeytype); + else if (hdr->type == TOKTYPE_CCA_INTERNAL && + hdr->version == TOKVER_CCA_AES) + rc = cca_sec2protkey(card, dom, key, protkey, + protkeylen, protkeytype); + else if (hdr->type == TOKTYPE_CCA_INTERNAL && + hdr->version == TOKVER_CCA_VLSC) + rc = cca_cipher2protkey(card, dom, key, protkey, + protkeylen, protkeytype); + else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) + rc = cca_ecc2protkey(card, dom, key, protkey, + protkeylen, protkeytype); + else + return -EINVAL; + } + + return rc; +} + /* * File io functions */ @@ -956,7 +1151,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, switch (cmd) { case PKEY_GENSECK: { - struct pkey_genseck __user *ugs = (void __user *) arg; + struct pkey_genseck __user *ugs = (void __user *)arg; struct pkey_genseck kgs; if (copy_from_user(&kgs, ugs, sizeof(kgs))) @@ -971,7 +1166,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_CLR2SECK: { - struct pkey_clr2seck __user *ucs = (void __user *) arg; + struct pkey_clr2seck __user *ucs = (void __user *)arg; struct pkey_clr2seck kcs; if (copy_from_user(&kcs, ucs, sizeof(kcs))) @@ -987,7 +1182,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_SEC2PROTK: { - struct pkey_sec2protk __user *usp = (void __user *) arg; + struct pkey_sec2protk __user *usp = (void __user *)arg; struct pkey_sec2protk ksp; if (copy_from_user(&ksp, usp, sizeof(ksp))) @@ -1003,7 +1198,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_CLR2PROTK: { - struct pkey_clr2protk __user *ucp = (void __user *) arg; + struct pkey_clr2protk __user *ucp = (void __user *)arg; struct pkey_clr2protk kcp; if (copy_from_user(&kcp, ucp, sizeof(kcp))) @@ -1019,7 +1214,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_FINDCARD: { - struct pkey_findcard __user *ufc = (void __user *) arg; + struct pkey_findcard __user *ufc = (void __user *)arg; struct pkey_findcard kfc; if (copy_from_user(&kfc, ufc, sizeof(kfc))) @@ -1034,7 +1229,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_SKEY2PKEY: { - struct pkey_skey2pkey __user *usp = (void __user *) arg; + struct pkey_skey2pkey __user *usp = (void __user *)arg; struct pkey_skey2pkey ksp; if (copy_from_user(&ksp, usp, sizeof(ksp))) @@ -1048,7 +1243,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_VERIFYKEY: { - struct pkey_verifykey __user *uvk = (void __user *) arg; + struct pkey_verifykey __user *uvk = (void __user *)arg; struct pkey_verifykey kvk; if (copy_from_user(&kvk, uvk, sizeof(kvk))) @@ -1063,7 +1258,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_GENPROTK: { - struct pkey_genprotk __user *ugp = (void __user *) arg; + struct pkey_genprotk __user *ugp = (void __user *)arg; struct pkey_genprotk kgp; if (copy_from_user(&kgp, ugp, sizeof(kgp))) @@ -1077,7 +1272,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_VERIFYPROTK: { - struct pkey_verifyprotk __user *uvp = (void __user *) arg; + struct pkey_verifyprotk __user *uvp = (void __user *)arg; struct pkey_verifyprotk kvp; if (copy_from_user(&kvp, uvp, sizeof(kvp))) @@ -1087,7 +1282,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_KBLOB2PROTK: { - struct pkey_kblob2pkey __user *utp = (void __user *) arg; + struct pkey_kblob2pkey __user *utp = (void __user *)arg; struct pkey_kblob2pkey ktp; u8 *kkey; @@ -1106,7 +1301,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_GENSECK2: { - struct pkey_genseck2 __user *ugs = (void __user *) arg; + struct pkey_genseck2 __user *ugs = (void __user *)arg; struct pkey_genseck2 kgs; struct pkey_apqn *apqns; size_t klen = KEYBLOBBUFSIZE; @@ -1148,7 +1343,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_CLR2SECK2: { - struct pkey_clr2seck2 __user *ucs = (void __user *) arg; + struct pkey_clr2seck2 __user *ucs = (void __user *)arg; struct pkey_clr2seck2 kcs; struct pkey_apqn *apqns; size_t klen = KEYBLOBBUFSIZE; @@ -1191,7 +1386,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_VERIFYKEY2: { - struct pkey_verifykey2 __user *uvk = (void __user *) arg; + struct pkey_verifykey2 __user *uvk = (void __user *)arg; struct pkey_verifykey2 kvk; u8 *kkey; @@ -1212,7 +1407,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_KBLOB2PROTK2: { - struct pkey_kblob2pkey2 __user *utp = (void __user *) arg; + struct pkey_kblob2pkey2 __user *utp = (void __user *)arg; struct pkey_kblob2pkey2 ktp; struct pkey_apqn *apqns = NULL; u8 *kkey; @@ -1239,7 +1434,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_APQNS4K: { - struct pkey_apqns4key __user *uak = (void __user *) arg; + struct pkey_apqns4key __user *uak = (void __user *)arg; struct pkey_apqns4key kak; struct pkey_apqn *apqns = NULL; size_t nr_apqns, len; @@ -1288,7 +1483,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, break; } case PKEY_APQNS4KT: { - struct pkey_apqns4keytype __user *uat = (void __user *) arg; + struct pkey_apqns4keytype __user *uat = (void __user *)arg; struct pkey_apqns4keytype kat; struct pkey_apqn *apqns = NULL; size_t nr_apqns, len; @@ -1329,6 +1524,55 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kfree(apqns); break; } + case PKEY_KBLOB2PROTK3: { + struct pkey_kblob2pkey3 __user *utp = (void __user *)arg; + struct pkey_kblob2pkey3 ktp; + struct pkey_apqn *apqns = NULL; + u32 protkeylen = PROTKEYBLOBBUFSIZE; + u8 *kkey, *protkey; + + if (copy_from_user(&ktp, utp, sizeof(ktp))) + return -EFAULT; + apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); + if (IS_ERR(apqns)) + return PTR_ERR(apqns); + kkey = _copy_key_from_user(ktp.key, ktp.keylen); + if (IS_ERR(kkey)) { + kfree(apqns); + return PTR_ERR(kkey); + } + protkey = kmalloc(protkeylen, GFP_KERNEL); + if (!protkey) { + kfree(apqns); + kfree(kkey); + return -ENOMEM; + } + rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, kkey, + ktp.keylen, &ktp.pkeytype, + protkey, &protkeylen); + DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); + kfree(apqns); + kfree(kkey); + if (rc) { + kfree(protkey); + break; + } + if (ktp.pkey && ktp.pkeylen) { + if (protkeylen > ktp.pkeylen) { + kfree(protkey); + return -EINVAL; + } + if (copy_to_user(ktp.pkey, protkey, protkeylen)) { + kfree(protkey); + return -EFAULT; + } + } + kfree(protkey); + ktp.pkeylen = protkeylen; + if (copy_to_user(utp, &ktp, sizeof(ktp))) + return -EFAULT; + break; + } default: /* unknown/unsupported ioctl cmd */ return -ENOTTY; @@ -1471,7 +1715,7 @@ static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, loff_t off, size_t count) { int rc; - struct pkey_seckey *seckey = (struct pkey_seckey *) buf; + struct pkey_seckey *seckey = (struct pkey_seckey *)buf; if (off != 0 || count < sizeof(struct secaeskeytoken)) return -EINVAL; @@ -1589,7 +1833,7 @@ static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, /* build a list of apqns able to generate an cipher key */ rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX6, 0, 0, 0); + ZCRYPT_CEX6, 0, 0, 0, 0); if (rc) return rc; @@ -1603,8 +1847,8 @@ static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, if (rc == 0) break; } - if (rc) - return rc; + if (rc) + return rc; if (is_xts) { keysize = CCACIPHERTOKENSIZE; @@ -1838,7 +2082,7 @@ static struct miscdevice pkey_dev = { */ static int __init pkey_init(void) { - cpacf_mask_t kmc_functions; + cpacf_mask_t func_mask; /* * The pckmo instruction should be available - even if we don't @@ -1846,15 +2090,15 @@ static int __init pkey_init(void) * is also the minimum level for the kmc instructions which * are able to work with protected keys. */ - if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) + if (!cpacf_query(CPACF_PCKMO, &func_mask)) return -ENODEV; /* check for kmc instructions available */ - if (!cpacf_query(CPACF_KMC, &kmc_functions)) + if (!cpacf_query(CPACF_KMC, &func_mask)) return -ENODEV; - if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) || - !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) || - !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) + if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) || + !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) || + !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256)) return -ENODEV; pkey_debug_init(); @@ -1871,5 +2115,5 @@ static void __exit pkey_exit(void) pkey_debug_exit(); } -module_cpu_feature_match(MSA, pkey_init); +module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init); module_exit(pkey_exit); |