186fbf5e2SHarald Freudenberger // SPDX-License-Identifier: GPL-2.0 286fbf5e2SHarald Freudenberger /* 386fbf5e2SHarald Freudenberger * pkey cca specific code 486fbf5e2SHarald Freudenberger * 586fbf5e2SHarald Freudenberger * Copyright IBM Corp. 2024 686fbf5e2SHarald Freudenberger */ 786fbf5e2SHarald Freudenberger 886fbf5e2SHarald Freudenberger #define KMSG_COMPONENT "pkey" 986fbf5e2SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 1086fbf5e2SHarald Freudenberger 118fcc231cSHarald Freudenberger #include <linux/init.h> 128fcc231cSHarald Freudenberger #include <linux/module.h> 138fcc231cSHarald Freudenberger #include <linux/cpufeature.h> 148fcc231cSHarald Freudenberger 1586fbf5e2SHarald Freudenberger #include "zcrypt_api.h" 1686fbf5e2SHarald Freudenberger #include "zcrypt_ccamisc.h" 1786fbf5e2SHarald Freudenberger #include "pkey_base.h" 1886fbf5e2SHarald Freudenberger 198fcc231cSHarald Freudenberger MODULE_LICENSE("GPL"); 208fcc231cSHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 218fcc231cSHarald Freudenberger MODULE_DESCRIPTION("s390 protected key CCA handler"); 228fcc231cSHarald Freudenberger 238fcc231cSHarald Freudenberger #if IS_MODULE(CONFIG_PKEY_CCA) 248fcc231cSHarald Freudenberger static struct ap_device_id pkey_cca_card_ids[] = { 258fcc231cSHarald Freudenberger { .dev_type = AP_DEVICE_TYPE_CEX4 }, 268fcc231cSHarald Freudenberger { .dev_type = AP_DEVICE_TYPE_CEX5 }, 278fcc231cSHarald Freudenberger { .dev_type = AP_DEVICE_TYPE_CEX6 }, 288fcc231cSHarald Freudenberger { .dev_type = AP_DEVICE_TYPE_CEX7 }, 298fcc231cSHarald Freudenberger { .dev_type = AP_DEVICE_TYPE_CEX8 }, 308fcc231cSHarald Freudenberger { /* end of list */ }, 318fcc231cSHarald Freudenberger }; 328fcc231cSHarald Freudenberger MODULE_DEVICE_TABLE(ap, pkey_cca_card_ids); 338fcc231cSHarald Freudenberger #endif 348fcc231cSHarald Freudenberger 3586fbf5e2SHarald Freudenberger /* 3686fbf5e2SHarald Freudenberger * Check key blob for known and supported CCA key. 3786fbf5e2SHarald Freudenberger */ 388fcc231cSHarald Freudenberger static bool is_cca_key(const u8 *key, u32 keylen) 3986fbf5e2SHarald Freudenberger { 4086fbf5e2SHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 4186fbf5e2SHarald Freudenberger 4286fbf5e2SHarald Freudenberger if (keylen < sizeof(*hdr)) 4386fbf5e2SHarald Freudenberger return false; 4486fbf5e2SHarald Freudenberger 4586fbf5e2SHarald Freudenberger switch (hdr->type) { 4686fbf5e2SHarald Freudenberger case TOKTYPE_CCA_INTERNAL: 4786fbf5e2SHarald Freudenberger switch (hdr->version) { 4886fbf5e2SHarald Freudenberger case TOKVER_CCA_AES: 4986fbf5e2SHarald Freudenberger case TOKVER_CCA_VLSC: 5086fbf5e2SHarald Freudenberger return true; 5186fbf5e2SHarald Freudenberger default: 5286fbf5e2SHarald Freudenberger return false; 5386fbf5e2SHarald Freudenberger } 5486fbf5e2SHarald Freudenberger case TOKTYPE_CCA_INTERNAL_PKA: 5586fbf5e2SHarald Freudenberger return true; 5686fbf5e2SHarald Freudenberger default: 5786fbf5e2SHarald Freudenberger return false; 5886fbf5e2SHarald Freudenberger } 5986fbf5e2SHarald Freudenberger } 6086fbf5e2SHarald Freudenberger 618fcc231cSHarald Freudenberger static bool is_cca_keytype(enum pkey_key_type key_type) 6286fbf5e2SHarald Freudenberger { 6386fbf5e2SHarald Freudenberger switch (key_type) { 6486fbf5e2SHarald Freudenberger case PKEY_TYPE_CCA_DATA: 6586fbf5e2SHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 6686fbf5e2SHarald Freudenberger case PKEY_TYPE_CCA_ECC: 6786fbf5e2SHarald Freudenberger return true; 6886fbf5e2SHarald Freudenberger default: 6986fbf5e2SHarald Freudenberger return false; 7086fbf5e2SHarald Freudenberger } 7186fbf5e2SHarald Freudenberger } 7286fbf5e2SHarald Freudenberger 738fcc231cSHarald Freudenberger static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags, 748fcc231cSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 758fcc231cSHarald Freudenberger { 768fcc231cSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 778fcc231cSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 788fcc231cSHarald Freudenberger int rc; 798fcc231cSHarald Freudenberger 808fcc231cSHarald Freudenberger if (!flags) 818fcc231cSHarald Freudenberger flags = PKEY_FLAGS_MATCH_CUR_MKVP | PKEY_FLAGS_MATCH_ALT_MKVP; 828fcc231cSHarald Freudenberger 838fcc231cSHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 848fcc231cSHarald Freudenberger return -EINVAL; 858fcc231cSHarald Freudenberger 868fcc231cSHarald Freudenberger zcrypt_wait_api_operational(); 878fcc231cSHarald Freudenberger 888fcc231cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL) { 898fcc231cSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 908fcc231cSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 918fcc231cSHarald Freudenberger 928fcc231cSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 938fcc231cSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 948fcc231cSHarald Freudenberger 958fcc231cSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 968fcc231cSHarald Freudenberger cur_mkvp = t->mkvp; 978fcc231cSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 988fcc231cSHarald Freudenberger old_mkvp = t->mkvp; 998fcc231cSHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1008fcc231cSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 1018fcc231cSHarald Freudenberger 1028fcc231cSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 1038fcc231cSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1048fcc231cSHarald Freudenberger cur_mkvp = t->mkvp0; 1058fcc231cSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1068fcc231cSHarald Freudenberger old_mkvp = t->mkvp0; 1078fcc231cSHarald Freudenberger } else { 1088fcc231cSHarald Freudenberger /* unknown CCA internal token type */ 1098fcc231cSHarald Freudenberger return -EINVAL; 1108fcc231cSHarald Freudenberger } 1118fcc231cSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1128fcc231cSHarald Freudenberger minhwtype, AES_MK_SET, 1138fcc231cSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1148fcc231cSHarald Freudenberger if (rc) 1158fcc231cSHarald Freudenberger goto out; 1168fcc231cSHarald Freudenberger 1178fcc231cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1188fcc231cSHarald Freudenberger struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; 1198fcc231cSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1208fcc231cSHarald Freudenberger 1218fcc231cSHarald Freudenberger if (t->secid == 0x20) { 1228fcc231cSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1238fcc231cSHarald Freudenberger cur_mkvp = t->mkvp; 1248fcc231cSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1258fcc231cSHarald Freudenberger old_mkvp = t->mkvp; 1268fcc231cSHarald Freudenberger } else { 1278fcc231cSHarald Freudenberger /* unknown CCA internal 2 token type */ 1288fcc231cSHarald Freudenberger return -EINVAL; 1298fcc231cSHarald Freudenberger } 1308fcc231cSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1318fcc231cSHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 1328fcc231cSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1338fcc231cSHarald Freudenberger if (rc) 1348fcc231cSHarald Freudenberger goto out; 1358fcc231cSHarald Freudenberger 1368fcc231cSHarald Freudenberger } else { 1378fcc231cSHarald Freudenberger PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n", 1388fcc231cSHarald Freudenberger __func__, hdr->type, hdr->version); 1398fcc231cSHarald Freudenberger return -EINVAL; 1408fcc231cSHarald Freudenberger } 1418fcc231cSHarald Freudenberger 1428fcc231cSHarald Freudenberger if (apqns) { 1438fcc231cSHarald Freudenberger if (*nr_apqns < _nr_apqns) 1448fcc231cSHarald Freudenberger rc = -ENOSPC; 1458fcc231cSHarald Freudenberger else 1468fcc231cSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 1478fcc231cSHarald Freudenberger } 1488fcc231cSHarald Freudenberger *nr_apqns = _nr_apqns; 1498fcc231cSHarald Freudenberger 1508fcc231cSHarald Freudenberger out: 1518fcc231cSHarald Freudenberger kfree(_apqns); 1528fcc231cSHarald Freudenberger pr_debug("rc=%d\n", rc); 1538fcc231cSHarald Freudenberger return rc; 1548fcc231cSHarald Freudenberger } 1558fcc231cSHarald Freudenberger 1568fcc231cSHarald Freudenberger static int cca_apqns4type(enum pkey_key_type ktype, 1578fcc231cSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 1588fcc231cSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 1598fcc231cSHarald Freudenberger { 1608fcc231cSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 1618fcc231cSHarald Freudenberger int rc; 1628fcc231cSHarald Freudenberger 1638fcc231cSHarald Freudenberger zcrypt_wait_api_operational(); 1648fcc231cSHarald Freudenberger 1658fcc231cSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 1668fcc231cSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1678fcc231cSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 1688fcc231cSHarald Freudenberger 1698fcc231cSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1708fcc231cSHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 1718fcc231cSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1728fcc231cSHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 1738fcc231cSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 1748fcc231cSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 1758fcc231cSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1768fcc231cSHarald Freudenberger minhwtype, AES_MK_SET, 1778fcc231cSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1788fcc231cSHarald Freudenberger if (rc) 1798fcc231cSHarald Freudenberger goto out; 1808fcc231cSHarald Freudenberger 1818fcc231cSHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_ECC) { 1828fcc231cSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1838fcc231cSHarald Freudenberger 1848fcc231cSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1858fcc231cSHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 1868fcc231cSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1878fcc231cSHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 1888fcc231cSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1898fcc231cSHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 1908fcc231cSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1918fcc231cSHarald Freudenberger if (rc) 1928fcc231cSHarald Freudenberger goto out; 1938fcc231cSHarald Freudenberger 1948fcc231cSHarald Freudenberger } else { 1958fcc231cSHarald Freudenberger PKEY_DBF_ERR("%s unknown/unsupported key type %d", 1968fcc231cSHarald Freudenberger __func__, (int)ktype); 1978fcc231cSHarald Freudenberger return -EINVAL; 1988fcc231cSHarald Freudenberger } 1998fcc231cSHarald Freudenberger 2008fcc231cSHarald Freudenberger if (apqns) { 2018fcc231cSHarald Freudenberger if (*nr_apqns < _nr_apqns) 2028fcc231cSHarald Freudenberger rc = -ENOSPC; 2038fcc231cSHarald Freudenberger else 2048fcc231cSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 2058fcc231cSHarald Freudenberger } 2068fcc231cSHarald Freudenberger *nr_apqns = _nr_apqns; 2078fcc231cSHarald Freudenberger 2088fcc231cSHarald Freudenberger out: 2098fcc231cSHarald Freudenberger kfree(_apqns); 2108fcc231cSHarald Freudenberger pr_debug("rc=%d\n", rc); 2118fcc231cSHarald Freudenberger return rc; 2128fcc231cSHarald Freudenberger } 2138fcc231cSHarald Freudenberger 2148fcc231cSHarald Freudenberger static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns, 21586fbf5e2SHarald Freudenberger const u8 *key, u32 keylen, 21686fbf5e2SHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 21786fbf5e2SHarald Freudenberger { 21886fbf5e2SHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 2198fcc231cSHarald Freudenberger struct pkey_apqn *local_apqns = NULL; 2208fcc231cSHarald Freudenberger int i, rc; 22186fbf5e2SHarald Freudenberger 22286fbf5e2SHarald Freudenberger if (keylen < sizeof(*hdr)) 22386fbf5e2SHarald Freudenberger return -EINVAL; 22486fbf5e2SHarald Freudenberger 22586fbf5e2SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 22686fbf5e2SHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 22786fbf5e2SHarald Freudenberger /* CCA AES data key */ 22886fbf5e2SHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 22986fbf5e2SHarald Freudenberger return -EINVAL; 23086fbf5e2SHarald Freudenberger if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0)) 23186fbf5e2SHarald Freudenberger return -EINVAL; 23286fbf5e2SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 23386fbf5e2SHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 23486fbf5e2SHarald Freudenberger /* CCA AES cipher key */ 23586fbf5e2SHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 23686fbf5e2SHarald Freudenberger return -EINVAL; 23786fbf5e2SHarald Freudenberger if (cca_check_secaescipherkey(pkey_dbf_info, 23886fbf5e2SHarald Freudenberger 3, key, 0, 1)) 23986fbf5e2SHarald Freudenberger return -EINVAL; 24086fbf5e2SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 24186fbf5e2SHarald Freudenberger /* CCA ECC (private) key */ 24286fbf5e2SHarald Freudenberger if (keylen < sizeof(struct eccprivkeytoken)) 24386fbf5e2SHarald Freudenberger return -EINVAL; 24486fbf5e2SHarald Freudenberger if (cca_check_sececckeytoken(pkey_dbf_info, 3, key, keylen, 1)) 24586fbf5e2SHarald Freudenberger return -EINVAL; 24686fbf5e2SHarald Freudenberger } else { 24786fbf5e2SHarald Freudenberger PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n", 24886fbf5e2SHarald Freudenberger __func__, hdr->type, hdr->version); 2498fcc231cSHarald Freudenberger return -EINVAL; 25086fbf5e2SHarald Freudenberger } 25186fbf5e2SHarald Freudenberger 2528fcc231cSHarald Freudenberger zcrypt_wait_api_operational(); 2538fcc231cSHarald Freudenberger 2548fcc231cSHarald Freudenberger if (!apqns || (nr_apqns == 1 && 2558fcc231cSHarald Freudenberger apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { 2568fcc231cSHarald Freudenberger nr_apqns = MAXAPQNSINLIST; 2578fcc231cSHarald Freudenberger local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), 2588fcc231cSHarald Freudenberger GFP_KERNEL); 2598fcc231cSHarald Freudenberger if (!local_apqns) 2608fcc231cSHarald Freudenberger return -ENOMEM; 2618fcc231cSHarald Freudenberger rc = cca_apqns4key(key, keylen, 0, local_apqns, &nr_apqns); 2628fcc231cSHarald Freudenberger if (rc) 2638fcc231cSHarald Freudenberger goto out; 2648fcc231cSHarald Freudenberger apqns = local_apqns; 2658fcc231cSHarald Freudenberger } 2668fcc231cSHarald Freudenberger 2678fcc231cSHarald Freudenberger for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 2688fcc231cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 2698fcc231cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 2708fcc231cSHarald Freudenberger rc = cca_sec2protkey(apqns[i].card, apqns[i].domain, 2718fcc231cSHarald Freudenberger key, protkey, 2728fcc231cSHarald Freudenberger protkeylen, protkeytype); 2738fcc231cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 2748fcc231cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 2758fcc231cSHarald Freudenberger rc = cca_cipher2protkey(apqns[i].card, apqns[i].domain, 2768fcc231cSHarald Freudenberger key, protkey, 2778fcc231cSHarald Freudenberger protkeylen, protkeytype); 2788fcc231cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 2798fcc231cSHarald Freudenberger rc = cca_ecc2protkey(apqns[i].card, apqns[i].domain, 2808fcc231cSHarald Freudenberger key, protkey, 2818fcc231cSHarald Freudenberger protkeylen, protkeytype); 2828fcc231cSHarald Freudenberger } else { 2838fcc231cSHarald Freudenberger rc = -EINVAL; 2848fcc231cSHarald Freudenberger break; 2858fcc231cSHarald Freudenberger } 2868fcc231cSHarald Freudenberger } 2878fcc231cSHarald Freudenberger 2888fcc231cSHarald Freudenberger out: 2898fcc231cSHarald Freudenberger kfree(local_apqns); 2908fcc231cSHarald Freudenberger pr_debug("rc=%d\n", rc); 29186fbf5e2SHarald Freudenberger return rc; 29286fbf5e2SHarald Freudenberger } 29386fbf5e2SHarald Freudenberger 29486fbf5e2SHarald Freudenberger /* 29586fbf5e2SHarald Freudenberger * Generate CCA secure key. 29686fbf5e2SHarald Freudenberger * As of now only CCA AES Data or Cipher secure keys are 29786fbf5e2SHarald Freudenberger * supported. 29886fbf5e2SHarald Freudenberger * keytype is one of the PKEY_KEYTYPE_* constants, 29986fbf5e2SHarald Freudenberger * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER, 30086fbf5e2SHarald Freudenberger * keybitsize is the bit size of the key (may be 0 for 30186fbf5e2SHarald Freudenberger * keytype PKEY_KEYTYPE_AES_*). 30286fbf5e2SHarald Freudenberger */ 3038fcc231cSHarald Freudenberger static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns, 30486fbf5e2SHarald Freudenberger u32 keytype, u32 subtype, 30586fbf5e2SHarald Freudenberger u32 keybitsize, u32 flags, 306ea88e171SHarald Freudenberger u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) 30786fbf5e2SHarald Freudenberger { 3088fcc231cSHarald Freudenberger struct pkey_apqn *local_apqns = NULL; 3098fcc231cSHarald Freudenberger int i, len, rc; 31086fbf5e2SHarald Freudenberger 31186fbf5e2SHarald Freudenberger /* check keytype, subtype, keybitsize */ 31286fbf5e2SHarald Freudenberger switch (keytype) { 31386fbf5e2SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 31486fbf5e2SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 31586fbf5e2SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 31686fbf5e2SHarald Freudenberger len = pkey_keytype_aes_to_size(keytype); 31786fbf5e2SHarald Freudenberger if (keybitsize && keybitsize != 8 * len) { 31886fbf5e2SHarald Freudenberger PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n", 31986fbf5e2SHarald Freudenberger __func__, keybitsize); 32086fbf5e2SHarald Freudenberger return -EINVAL; 32186fbf5e2SHarald Freudenberger } 32286fbf5e2SHarald Freudenberger keybitsize = 8 * len; 32386fbf5e2SHarald Freudenberger switch (subtype) { 32486fbf5e2SHarald Freudenberger case PKEY_TYPE_CCA_DATA: 32586fbf5e2SHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 32686fbf5e2SHarald Freudenberger break; 32786fbf5e2SHarald Freudenberger default: 32886fbf5e2SHarald Freudenberger PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n", 32986fbf5e2SHarald Freudenberger __func__, subtype); 33086fbf5e2SHarald Freudenberger return -EINVAL; 33186fbf5e2SHarald Freudenberger } 33286fbf5e2SHarald Freudenberger break; 33386fbf5e2SHarald Freudenberger default: 33486fbf5e2SHarald Freudenberger PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n", 33586fbf5e2SHarald Freudenberger __func__, keytype); 33686fbf5e2SHarald Freudenberger return -EINVAL; 33786fbf5e2SHarald Freudenberger } 33886fbf5e2SHarald Freudenberger 33986fbf5e2SHarald Freudenberger zcrypt_wait_api_operational(); 34086fbf5e2SHarald Freudenberger 3418fcc231cSHarald Freudenberger if (!apqns || (nr_apqns == 1 && 3428fcc231cSHarald Freudenberger apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { 3438fcc231cSHarald Freudenberger nr_apqns = MAXAPQNSINLIST; 3448fcc231cSHarald Freudenberger local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), 3458fcc231cSHarald Freudenberger GFP_KERNEL); 3468fcc231cSHarald Freudenberger if (!local_apqns) 3478fcc231cSHarald Freudenberger return -ENOMEM; 3488fcc231cSHarald Freudenberger rc = cca_apqns4type(subtype, NULL, NULL, 0, 3498fcc231cSHarald Freudenberger local_apqns, &nr_apqns); 3508fcc231cSHarald Freudenberger if (rc) 3518fcc231cSHarald Freudenberger goto out; 3528fcc231cSHarald Freudenberger apqns = local_apqns; 35386fbf5e2SHarald Freudenberger } 35486fbf5e2SHarald Freudenberger 3558fcc231cSHarald Freudenberger for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 3568fcc231cSHarald Freudenberger if (subtype == PKEY_TYPE_CCA_CIPHER) { 3578fcc231cSHarald Freudenberger rc = cca_gencipherkey(apqns[i].card, apqns[i].domain, 3588fcc231cSHarald Freudenberger keybitsize, flags, 3598fcc231cSHarald Freudenberger keybuf, keybuflen); 3608fcc231cSHarald Freudenberger } else { 3618fcc231cSHarald Freudenberger /* PKEY_TYPE_CCA_DATA */ 3628fcc231cSHarald Freudenberger rc = cca_genseckey(apqns[i].card, apqns[i].domain, 3638fcc231cSHarald Freudenberger keybitsize, keybuf); 3648fcc231cSHarald Freudenberger *keybuflen = (rc ? 0 : SECKEYBLOBSIZE); 3658fcc231cSHarald Freudenberger } 3668fcc231cSHarald Freudenberger } 3678fcc231cSHarald Freudenberger 3688fcc231cSHarald Freudenberger out: 3698fcc231cSHarald Freudenberger kfree(local_apqns); 3708fcc231cSHarald Freudenberger pr_debug("rc=%d\n", rc); 37186fbf5e2SHarald Freudenberger return rc; 37286fbf5e2SHarald Freudenberger } 37386fbf5e2SHarald Freudenberger 37486fbf5e2SHarald Freudenberger /* 37586fbf5e2SHarald Freudenberger * Generate CCA secure key with given clear key value. 37686fbf5e2SHarald Freudenberger * As of now only CCA AES Data or Cipher secure keys are 37786fbf5e2SHarald Freudenberger * supported. 37886fbf5e2SHarald Freudenberger * keytype is one of the PKEY_KEYTYPE_* constants, 37986fbf5e2SHarald Freudenberger * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER, 38086fbf5e2SHarald Freudenberger * keybitsize is the bit size of the key (may be 0 for 38186fbf5e2SHarald Freudenberger * keytype PKEY_KEYTYPE_AES_*). 38286fbf5e2SHarald Freudenberger */ 3838fcc231cSHarald Freudenberger static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns, 38486fbf5e2SHarald Freudenberger u32 keytype, u32 subtype, 38586fbf5e2SHarald Freudenberger u32 keybitsize, u32 flags, 38686fbf5e2SHarald Freudenberger const u8 *clrkey, u32 clrkeylen, 387ea88e171SHarald Freudenberger u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) 38886fbf5e2SHarald Freudenberger { 3898fcc231cSHarald Freudenberger struct pkey_apqn *local_apqns = NULL; 3908fcc231cSHarald Freudenberger int i, len, rc; 39186fbf5e2SHarald Freudenberger 39286fbf5e2SHarald Freudenberger /* check keytype, subtype, clrkeylen, keybitsize */ 39386fbf5e2SHarald Freudenberger switch (keytype) { 39486fbf5e2SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 39586fbf5e2SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 39686fbf5e2SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 39786fbf5e2SHarald Freudenberger len = pkey_keytype_aes_to_size(keytype); 39886fbf5e2SHarald Freudenberger if (keybitsize && keybitsize != 8 * len) { 39986fbf5e2SHarald Freudenberger PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n", 40086fbf5e2SHarald Freudenberger __func__, keybitsize); 40186fbf5e2SHarald Freudenberger return -EINVAL; 40286fbf5e2SHarald Freudenberger } 40386fbf5e2SHarald Freudenberger keybitsize = 8 * len; 40486fbf5e2SHarald Freudenberger if (clrkeylen != len) { 40586fbf5e2SHarald Freudenberger PKEY_DBF_ERR("%s invalid clear key len %d != %d\n", 40686fbf5e2SHarald Freudenberger __func__, clrkeylen, len); 40786fbf5e2SHarald Freudenberger return -EINVAL; 40886fbf5e2SHarald Freudenberger } 40986fbf5e2SHarald Freudenberger switch (subtype) { 41086fbf5e2SHarald Freudenberger case PKEY_TYPE_CCA_DATA: 41186fbf5e2SHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 41286fbf5e2SHarald Freudenberger break; 41386fbf5e2SHarald Freudenberger default: 41486fbf5e2SHarald Freudenberger PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n", 41586fbf5e2SHarald Freudenberger __func__, subtype); 41686fbf5e2SHarald Freudenberger return -EINVAL; 41786fbf5e2SHarald Freudenberger } 41886fbf5e2SHarald Freudenberger break; 41986fbf5e2SHarald Freudenberger default: 42086fbf5e2SHarald Freudenberger PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n", 42186fbf5e2SHarald Freudenberger __func__, keytype); 42286fbf5e2SHarald Freudenberger return -EINVAL; 42386fbf5e2SHarald Freudenberger } 42486fbf5e2SHarald Freudenberger 42586fbf5e2SHarald Freudenberger zcrypt_wait_api_operational(); 42686fbf5e2SHarald Freudenberger 4278fcc231cSHarald Freudenberger if (!apqns || (nr_apqns == 1 && 4288fcc231cSHarald Freudenberger apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { 4298fcc231cSHarald Freudenberger nr_apqns = MAXAPQNSINLIST; 4308fcc231cSHarald Freudenberger local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), 4318fcc231cSHarald Freudenberger GFP_KERNEL); 4328fcc231cSHarald Freudenberger if (!local_apqns) 4338fcc231cSHarald Freudenberger return -ENOMEM; 4348fcc231cSHarald Freudenberger rc = cca_apqns4type(subtype, NULL, NULL, 0, 4358fcc231cSHarald Freudenberger local_apqns, &nr_apqns); 4368fcc231cSHarald Freudenberger if (rc) 4378fcc231cSHarald Freudenberger goto out; 4388fcc231cSHarald Freudenberger apqns = local_apqns; 43986fbf5e2SHarald Freudenberger } 44086fbf5e2SHarald Freudenberger 4418fcc231cSHarald Freudenberger for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 4428fcc231cSHarald Freudenberger if (subtype == PKEY_TYPE_CCA_CIPHER) { 4438fcc231cSHarald Freudenberger rc = cca_clr2cipherkey(apqns[i].card, apqns[i].domain, 4448fcc231cSHarald Freudenberger keybitsize, flags, clrkey, 4458fcc231cSHarald Freudenberger keybuf, keybuflen); 4468fcc231cSHarald Freudenberger } else { 4478fcc231cSHarald Freudenberger /* PKEY_TYPE_CCA_DATA */ 4488fcc231cSHarald Freudenberger rc = cca_clr2seckey(apqns[i].card, apqns[i].domain, 4498fcc231cSHarald Freudenberger keybitsize, clrkey, keybuf); 4508fcc231cSHarald Freudenberger *keybuflen = (rc ? 0 : SECKEYBLOBSIZE); 4518fcc231cSHarald Freudenberger } 4528fcc231cSHarald Freudenberger } 4538fcc231cSHarald Freudenberger 4548fcc231cSHarald Freudenberger out: 4558fcc231cSHarald Freudenberger kfree(local_apqns); 4568fcc231cSHarald Freudenberger pr_debug("rc=%d\n", rc); 45786fbf5e2SHarald Freudenberger return rc; 45886fbf5e2SHarald Freudenberger } 45986fbf5e2SHarald Freudenberger 4608fcc231cSHarald Freudenberger static int cca_verifykey(const u8 *key, u32 keylen, 46186fbf5e2SHarald Freudenberger u16 *card, u16 *dom, 46286fbf5e2SHarald Freudenberger u32 *keytype, u32 *keybitsize, u32 *flags) 46386fbf5e2SHarald Freudenberger { 46486fbf5e2SHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 46586fbf5e2SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 46686fbf5e2SHarald Freudenberger int rc; 46786fbf5e2SHarald Freudenberger 46886fbf5e2SHarald Freudenberger if (keylen < sizeof(*hdr)) 46986fbf5e2SHarald Freudenberger return -EINVAL; 47086fbf5e2SHarald Freudenberger 47186fbf5e2SHarald Freudenberger zcrypt_wait_api_operational(); 47286fbf5e2SHarald Freudenberger 47386fbf5e2SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 47486fbf5e2SHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 47586fbf5e2SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 47686fbf5e2SHarald Freudenberger 47786fbf5e2SHarald Freudenberger rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0); 47886fbf5e2SHarald Freudenberger if (rc) 47986fbf5e2SHarald Freudenberger goto out; 48086fbf5e2SHarald Freudenberger *keytype = PKEY_TYPE_CCA_DATA; 48186fbf5e2SHarald Freudenberger *keybitsize = t->bitsize; 48286fbf5e2SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom, 48386fbf5e2SHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, 48486fbf5e2SHarald Freudenberger t->mkvp, 0, 1); 48586fbf5e2SHarald Freudenberger if (!rc) 48686fbf5e2SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 48786fbf5e2SHarald Freudenberger if (rc == -ENODEV) { 48886fbf5e2SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom, 48986fbf5e2SHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, 49086fbf5e2SHarald Freudenberger 0, t->mkvp, 1); 49186fbf5e2SHarald Freudenberger if (!rc) 49286fbf5e2SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 49386fbf5e2SHarald Freudenberger } 49486fbf5e2SHarald Freudenberger if (rc) 49586fbf5e2SHarald Freudenberger goto out; 49686fbf5e2SHarald Freudenberger 49786fbf5e2SHarald Freudenberger *card = ((struct pkey_apqn *)apqns)->card; 49886fbf5e2SHarald Freudenberger *dom = ((struct pkey_apqn *)apqns)->domain; 49986fbf5e2SHarald Freudenberger 50086fbf5e2SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 50186fbf5e2SHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 50286fbf5e2SHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 50386fbf5e2SHarald Freudenberger 50486fbf5e2SHarald Freudenberger rc = cca_check_secaescipherkey(pkey_dbf_info, 3, key, 0, 1); 50586fbf5e2SHarald Freudenberger if (rc) 50686fbf5e2SHarald Freudenberger goto out; 50786fbf5e2SHarald Freudenberger *keytype = PKEY_TYPE_CCA_CIPHER; 50886fbf5e2SHarald Freudenberger *keybitsize = PKEY_SIZE_UNKNOWN; 50986fbf5e2SHarald Freudenberger if (!t->plfver && t->wpllen == 512) 51086fbf5e2SHarald Freudenberger *keybitsize = PKEY_SIZE_AES_128; 51186fbf5e2SHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 51286fbf5e2SHarald Freudenberger *keybitsize = PKEY_SIZE_AES_192; 51386fbf5e2SHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 51486fbf5e2SHarald Freudenberger *keybitsize = PKEY_SIZE_AES_256; 51586fbf5e2SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom, 51686fbf5e2SHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, 51786fbf5e2SHarald Freudenberger t->mkvp0, 0, 1); 51886fbf5e2SHarald Freudenberger if (!rc) 51986fbf5e2SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 52086fbf5e2SHarald Freudenberger if (rc == -ENODEV) { 52186fbf5e2SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom, 52286fbf5e2SHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, 52386fbf5e2SHarald Freudenberger 0, t->mkvp0, 1); 52486fbf5e2SHarald Freudenberger if (!rc) 52586fbf5e2SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 52686fbf5e2SHarald Freudenberger } 52786fbf5e2SHarald Freudenberger if (rc) 52886fbf5e2SHarald Freudenberger goto out; 52986fbf5e2SHarald Freudenberger 53086fbf5e2SHarald Freudenberger *card = ((struct pkey_apqn *)apqns)->card; 53186fbf5e2SHarald Freudenberger *dom = ((struct pkey_apqn *)apqns)->domain; 53286fbf5e2SHarald Freudenberger 53386fbf5e2SHarald Freudenberger } else { 53486fbf5e2SHarald Freudenberger /* unknown/unsupported key blob */ 53586fbf5e2SHarald Freudenberger rc = -EINVAL; 53686fbf5e2SHarald Freudenberger } 53786fbf5e2SHarald Freudenberger 53886fbf5e2SHarald Freudenberger out: 53986fbf5e2SHarald Freudenberger kfree(apqns); 54086fbf5e2SHarald Freudenberger pr_debug("rc=%d\n", rc); 54186fbf5e2SHarald Freudenberger return rc; 54286fbf5e2SHarald Freudenberger } 54386fbf5e2SHarald Freudenberger 544*2fc401b9SHarald Freudenberger /* 545*2fc401b9SHarald Freudenberger * This function provides an alternate but usually slow way 546*2fc401b9SHarald Freudenberger * to convert a 'clear key token' with AES key material into 547*2fc401b9SHarald Freudenberger * a protected key. This is done via an intermediate step 548*2fc401b9SHarald Freudenberger * which creates a CCA AES DATA secure key first and then 549*2fc401b9SHarald Freudenberger * derives the protected key from this secure key. 550*2fc401b9SHarald Freudenberger */ 551*2fc401b9SHarald Freudenberger static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns, 552*2fc401b9SHarald Freudenberger size_t nr_apqns, 553*2fc401b9SHarald Freudenberger const u8 *key, u32 keylen, 554*2fc401b9SHarald Freudenberger u8 *protkey, u32 *protkeylen, 555*2fc401b9SHarald Freudenberger u32 *protkeytype) 556*2fc401b9SHarald Freudenberger { 557*2fc401b9SHarald Freudenberger const struct keytoken_header *hdr = (const struct keytoken_header *)key; 558*2fc401b9SHarald Freudenberger const struct clearkeytoken *t = (const struct clearkeytoken *)key; 559*2fc401b9SHarald Freudenberger u32 tmplen, keysize = 0; 560*2fc401b9SHarald Freudenberger u8 *tmpbuf; 561*2fc401b9SHarald Freudenberger int i, rc; 562*2fc401b9SHarald Freudenberger 563*2fc401b9SHarald Freudenberger if (keylen < sizeof(*hdr)) 564*2fc401b9SHarald Freudenberger return -EINVAL; 565*2fc401b9SHarald Freudenberger 566*2fc401b9SHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 567*2fc401b9SHarald Freudenberger hdr->version == TOKVER_CLEAR_KEY) 568*2fc401b9SHarald Freudenberger keysize = pkey_keytype_aes_to_size(t->keytype); 569*2fc401b9SHarald Freudenberger if (!keysize || t->len != keysize) 570*2fc401b9SHarald Freudenberger return -EINVAL; 571*2fc401b9SHarald Freudenberger 572*2fc401b9SHarald Freudenberger /* alloc tmp key buffer */ 573*2fc401b9SHarald Freudenberger tmpbuf = kmalloc(SECKEYBLOBSIZE, GFP_ATOMIC); 574*2fc401b9SHarald Freudenberger if (!tmpbuf) 575*2fc401b9SHarald Freudenberger return -ENOMEM; 576*2fc401b9SHarald Freudenberger 577*2fc401b9SHarald Freudenberger /* try two times in case of failure */ 578*2fc401b9SHarald Freudenberger for (i = 0, rc = -ENODEV; i < 2 && rc; i++) { 579*2fc401b9SHarald Freudenberger tmplen = SECKEYBLOBSIZE; 580*2fc401b9SHarald Freudenberger rc = cca_clr2key(NULL, 0, t->keytype, PKEY_TYPE_CCA_DATA, 581*2fc401b9SHarald Freudenberger 8 * keysize, 0, t->clearkey, t->len, 582*2fc401b9SHarald Freudenberger tmpbuf, &tmplen, NULL); 583*2fc401b9SHarald Freudenberger pr_debug("cca_clr2key()=%d\n", rc); 584*2fc401b9SHarald Freudenberger if (rc) 585*2fc401b9SHarald Freudenberger continue; 586*2fc401b9SHarald Freudenberger rc = cca_key2protkey(NULL, 0, tmpbuf, tmplen, 587*2fc401b9SHarald Freudenberger protkey, protkeylen, protkeytype); 588*2fc401b9SHarald Freudenberger pr_debug("cca_key2protkey()=%d\n", rc); 589*2fc401b9SHarald Freudenberger } 590*2fc401b9SHarald Freudenberger 591*2fc401b9SHarald Freudenberger kfree(tmpbuf); 592*2fc401b9SHarald Freudenberger pr_debug("rc=%d\n", rc); 593*2fc401b9SHarald Freudenberger return rc; 594*2fc401b9SHarald Freudenberger } 595*2fc401b9SHarald Freudenberger 5968fcc231cSHarald Freudenberger static struct pkey_handler cca_handler = { 5978fcc231cSHarald Freudenberger .module = THIS_MODULE, 5988fcc231cSHarald Freudenberger .name = "PKEY CCA handler", 5998fcc231cSHarald Freudenberger .is_supported_key = is_cca_key, 6008fcc231cSHarald Freudenberger .is_supported_keytype = is_cca_keytype, 6018fcc231cSHarald Freudenberger .key_to_protkey = cca_key2protkey, 602*2fc401b9SHarald Freudenberger .slowpath_key_to_protkey = cca_slowpath_key2protkey, 6038fcc231cSHarald Freudenberger .gen_key = cca_gen_key, 6048fcc231cSHarald Freudenberger .clr_to_key = cca_clr2key, 6058fcc231cSHarald Freudenberger .verify_key = cca_verifykey, 6068fcc231cSHarald Freudenberger .apqns_for_key = cca_apqns4key, 6078fcc231cSHarald Freudenberger .apqns_for_keytype = cca_apqns4type, 6088fcc231cSHarald Freudenberger }; 6098fcc231cSHarald Freudenberger 6108fcc231cSHarald Freudenberger /* 6118fcc231cSHarald Freudenberger * Module init 6128fcc231cSHarald Freudenberger */ 6138fcc231cSHarald Freudenberger static int __init pkey_cca_init(void) 61486fbf5e2SHarald Freudenberger { 6158fcc231cSHarald Freudenberger /* register this module as pkey handler for all the cca stuff */ 6168fcc231cSHarald Freudenberger return pkey_handler_register(&cca_handler); 61786fbf5e2SHarald Freudenberger } 61886fbf5e2SHarald Freudenberger 6198fcc231cSHarald Freudenberger /* 6208fcc231cSHarald Freudenberger * Module exit 6218fcc231cSHarald Freudenberger */ 6228fcc231cSHarald Freudenberger static void __exit pkey_cca_exit(void) 62386fbf5e2SHarald Freudenberger { 6248fcc231cSHarald Freudenberger /* unregister this module as pkey handler */ 6258fcc231cSHarald Freudenberger pkey_handler_unregister(&cca_handler); 62686fbf5e2SHarald Freudenberger } 62786fbf5e2SHarald Freudenberger 6288fcc231cSHarald Freudenberger module_init(pkey_cca_init); 6298fcc231cSHarald Freudenberger module_exit(pkey_cca_exit); 630