1812141a9SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2e80d4af0SHarald Freudenberger /* 3e80d4af0SHarald Freudenberger * pkey device driver 4e80d4af0SHarald Freudenberger * 59e436c19SHarald Freudenberger * Copyright IBM Corp. 2017, 2023 69e436c19SHarald Freudenberger * 7e80d4af0SHarald Freudenberger * Author(s): Harald Freudenberger 8e80d4af0SHarald Freudenberger */ 9e80d4af0SHarald Freudenberger 10e80d4af0SHarald Freudenberger #define KMSG_COMPONENT "pkey" 11e80d4af0SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 12e80d4af0SHarald Freudenberger 13e80d4af0SHarald Freudenberger #include <linux/fs.h> 14e80d4af0SHarald Freudenberger #include <linux/init.h> 15e80d4af0SHarald Freudenberger #include <linux/miscdevice.h> 16e80d4af0SHarald Freudenberger #include <linux/module.h> 17e80d4af0SHarald Freudenberger #include <linux/slab.h> 18e80d4af0SHarald Freudenberger #include <linux/kallsyms.h> 19e80d4af0SHarald Freudenberger #include <linux/debugfs.h> 20a45a5c7dSIngo Franzki #include <linux/random.h> 2163c19be0SIngo Franzki #include <linux/cpufeature.h> 22e80d4af0SHarald Freudenberger #include <asm/zcrypt.h> 23e80d4af0SHarald Freudenberger #include <asm/cpacf.h> 24e80d4af0SHarald Freudenberger #include <asm/pkey.h> 25cb26b9ffSIngo Franzki #include <crypto/aes.h> 26e80d4af0SHarald Freudenberger 27e80d4af0SHarald Freudenberger #include "zcrypt_api.h" 28efc598e6SHarald Freudenberger #include "zcrypt_ccamisc.h" 2955d0a513SHarald Freudenberger #include "zcrypt_ep11misc.h" 30e80d4af0SHarald Freudenberger 31e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL"); 32e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 33e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface"); 34e80d4af0SHarald Freudenberger 35f2bbc96eSHarald Freudenberger #define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ 369e436c19SHarald Freudenberger #define MINKEYBLOBBUFSIZE (sizeof(struct keytoken_header)) 37fa6999e3SHarald Freudenberger #define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */ 38f2bbc96eSHarald Freudenberger #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ 39f370f45cSHarald Freudenberger #define AES_WK_VP_SIZE 32 /* Size of WK VP block appended to a prot key */ 40f2bbc96eSHarald Freudenberger 41e80d4af0SHarald Freudenberger /* 42e80d4af0SHarald Freudenberger * debug feature data and functions 43e80d4af0SHarald Freudenberger */ 44e80d4af0SHarald Freudenberger 45e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 46e80d4af0SHarald Freudenberger 47e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 48e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 49e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 50e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 51e80d4af0SHarald Freudenberger 52e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 53e80d4af0SHarald Freudenberger { 546b1f16baSHarald Freudenberger /* 5 arguments per dbf entry (including the format string ptr) */ 556b1f16baSHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); 56e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 57e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 58e80d4af0SHarald Freudenberger } 59e80d4af0SHarald Freudenberger 60e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 61e80d4af0SHarald Freudenberger { 62e80d4af0SHarald Freudenberger debug_unregister(debug_info); 63e80d4af0SHarald Freudenberger } 64e80d4af0SHarald Freudenberger 650534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */ 660534bde7SIngo Franzki struct protaeskeytoken { 670534bde7SIngo Franzki u8 type; /* 0x00 for PAES specific key tokens */ 680534bde7SIngo Franzki u8 res0[3]; 690534bde7SIngo Franzki u8 version; /* should be 0x01 for protected AES key token */ 700534bde7SIngo Franzki u8 res1[3]; 710534bde7SIngo Franzki u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 720534bde7SIngo Franzki u32 len; /* bytes actually stored in protkey[] */ 730534bde7SIngo Franzki u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 740534bde7SIngo Franzki } __packed; 750534bde7SIngo Franzki 76888edbc4SHarald Freudenberger /* inside view of a clear key token (type 0x00 version 0x02) */ 779e436c19SHarald Freudenberger struct clearkeytoken { 78888edbc4SHarald Freudenberger u8 type; /* 0x00 for PAES specific key tokens */ 79888edbc4SHarald Freudenberger u8 res0[3]; 809e436c19SHarald Freudenberger u8 version; /* 0x02 for clear key token */ 81888edbc4SHarald Freudenberger u8 res1[3]; 829e436c19SHarald Freudenberger u32 keytype; /* key type, one of the PKEY_KEYTYPE_* values */ 83888edbc4SHarald Freudenberger u32 len; /* bytes actually stored in clearkey[] */ 84fa226f1dSGustavo A. R. Silva u8 clearkey[]; /* clear key value */ 85888edbc4SHarald Freudenberger } __packed; 86888edbc4SHarald Freudenberger 879e436c19SHarald Freudenberger /* helper function which translates the PKEY_KEYTYPE_AES_* to their keysize */ 889e436c19SHarald Freudenberger static inline u32 pkey_keytype_aes_to_size(u32 keytype) 899e436c19SHarald Freudenberger { 909e436c19SHarald Freudenberger switch (keytype) { 919e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 929e436c19SHarald Freudenberger return 16; 939e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 949e436c19SHarald Freudenberger return 24; 959e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 969e436c19SHarald Freudenberger return 32; 979e436c19SHarald Freudenberger default: 989e436c19SHarald Freudenberger return 0; 999e436c19SHarald Freudenberger } 1009e436c19SHarald Freudenberger } 1019e436c19SHarald Freudenberger 102e80d4af0SHarald Freudenberger /* 103f370f45cSHarald Freudenberger * Create a protected key from a clear key value via PCKMO instruction. 104e80d4af0SHarald Freudenberger */ 105f370f45cSHarald Freudenberger static int pkey_clr2protkey(u32 keytype, const u8 *clrkey, 106f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 107e80d4af0SHarald Freudenberger { 1085b35047eSHarald Freudenberger /* mask of available pckmo subfunctions */ 1095b35047eSHarald Freudenberger static cpacf_mask_t pckmo_functions; 1105b35047eSHarald Freudenberger 1119e436c19SHarald Freudenberger u8 paramblock[112]; 1129e436c19SHarald Freudenberger u32 pkeytype; 11346a29b03SHarald Freudenberger int keysize; 11446a29b03SHarald Freudenberger long fc; 115e80d4af0SHarald Freudenberger 116e80d4af0SHarald Freudenberger switch (keytype) { 117e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 1189e436c19SHarald Freudenberger /* 16 byte key, 32 byte aes wkvp, total 48 bytes */ 119e80d4af0SHarald Freudenberger keysize = 16; 1209e436c19SHarald Freudenberger pkeytype = keytype; 121e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 122e80d4af0SHarald Freudenberger break; 123e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 1249e436c19SHarald Freudenberger /* 24 byte key, 32 byte aes wkvp, total 56 bytes */ 125e80d4af0SHarald Freudenberger keysize = 24; 1269e436c19SHarald Freudenberger pkeytype = keytype; 127e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 128e80d4af0SHarald Freudenberger break; 129e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 1309e436c19SHarald Freudenberger /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ 131e80d4af0SHarald Freudenberger keysize = 32; 1329e436c19SHarald Freudenberger pkeytype = keytype; 133e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 134e80d4af0SHarald Freudenberger break; 1359e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P256: 1369e436c19SHarald Freudenberger /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ 1379e436c19SHarald Freudenberger keysize = 32; 1389e436c19SHarald Freudenberger pkeytype = PKEY_KEYTYPE_ECC; 1399e436c19SHarald Freudenberger fc = CPACF_PCKMO_ENC_ECC_P256_KEY; 1409e436c19SHarald Freudenberger break; 1419e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P384: 1429e436c19SHarald Freudenberger /* 48 byte key, 32 byte aes wkvp, total 80 bytes */ 1439e436c19SHarald Freudenberger keysize = 48; 1449e436c19SHarald Freudenberger pkeytype = PKEY_KEYTYPE_ECC; 1459e436c19SHarald Freudenberger fc = CPACF_PCKMO_ENC_ECC_P384_KEY; 1469e436c19SHarald Freudenberger break; 1479e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P521: 1489e436c19SHarald Freudenberger /* 80 byte key, 32 byte aes wkvp, total 112 bytes */ 1499e436c19SHarald Freudenberger keysize = 80; 1509e436c19SHarald Freudenberger pkeytype = PKEY_KEYTYPE_ECC; 1519e436c19SHarald Freudenberger fc = CPACF_PCKMO_ENC_ECC_P521_KEY; 1529e436c19SHarald Freudenberger break; 1539e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED25519: 1549e436c19SHarald Freudenberger /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ 1559e436c19SHarald Freudenberger keysize = 32; 1569e436c19SHarald Freudenberger pkeytype = PKEY_KEYTYPE_ECC; 1579e436c19SHarald Freudenberger fc = CPACF_PCKMO_ENC_ECC_ED25519_KEY; 1589e436c19SHarald Freudenberger break; 1599e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED448: 1609e436c19SHarald Freudenberger /* 64 byte key, 32 byte aes wkvp, total 96 bytes */ 1619e436c19SHarald Freudenberger keysize = 64; 1629e436c19SHarald Freudenberger pkeytype = PKEY_KEYTYPE_ECC; 1639e436c19SHarald Freudenberger fc = CPACF_PCKMO_ENC_ECC_ED448_KEY; 1649e436c19SHarald Freudenberger break; 165e80d4af0SHarald Freudenberger default: 166f370f45cSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", 167ac2b96f3SHarald Freudenberger __func__, keytype); 168e80d4af0SHarald Freudenberger return -EINVAL; 169e80d4af0SHarald Freudenberger } 170e80d4af0SHarald Freudenberger 171f370f45cSHarald Freudenberger if (*protkeylen < keysize + AES_WK_VP_SIZE) { 172f370f45cSHarald Freudenberger DEBUG_ERR("%s prot key buffer size too small: %u < %d\n", 173f370f45cSHarald Freudenberger __func__, *protkeylen, keysize + AES_WK_VP_SIZE); 174f370f45cSHarald Freudenberger return -EINVAL; 175f370f45cSHarald Freudenberger } 176f370f45cSHarald Freudenberger 1775b35047eSHarald Freudenberger /* Did we already check for PCKMO ? */ 1785b35047eSHarald Freudenberger if (!pckmo_functions.bytes[0]) { 1795b35047eSHarald Freudenberger /* no, so check now */ 1805b35047eSHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 1815b35047eSHarald Freudenberger return -ENODEV; 1825b35047eSHarald Freudenberger } 1835b35047eSHarald Freudenberger /* check for the pckmo subfunction we need now */ 184f822ad2cSHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, fc)) { 185f822ad2cSHarald Freudenberger DEBUG_ERR("%s pckmo functions not available\n", __func__); 18658443b67SDavid Hildenbrand return -ENODEV; 187f822ad2cSHarald Freudenberger } 188f822ad2cSHarald Freudenberger 189e80d4af0SHarald Freudenberger /* prepare param block */ 190e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 191f370f45cSHarald Freudenberger memcpy(paramblock, clrkey, keysize); 192e80d4af0SHarald Freudenberger 193e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 194e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 195e80d4af0SHarald Freudenberger 196f370f45cSHarald Freudenberger /* copy created protected key to key buffer including the wkvp block */ 197f370f45cSHarald Freudenberger *protkeylen = keysize + AES_WK_VP_SIZE; 198f370f45cSHarald Freudenberger memcpy(protkey, paramblock, *protkeylen); 1999e436c19SHarald Freudenberger *protkeytype = pkeytype; 200e80d4af0SHarald Freudenberger 201e80d4af0SHarald Freudenberger return 0; 202e80d4af0SHarald Freudenberger } 203e80d4af0SHarald Freudenberger 204e80d4af0SHarald Freudenberger /* 205e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 206e80d4af0SHarald Freudenberger */ 207f370f45cSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, u8 *protkey, 208f370f45cSHarald Freudenberger u32 *protkeylen, u32 *protkeytype) 209e80d4af0SHarald Freudenberger { 210f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 21146a29b03SHarald Freudenberger u16 cardnr, domain; 21246a29b03SHarald Freudenberger int rc, verify; 213e80d4af0SHarald Freudenberger 21443cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 21543cb5a7cSHarald Freudenberger 216e80d4af0SHarald Freudenberger /* 217f2bbc96eSHarald Freudenberger * The cca_xxx2protkey call may fail when a card has been 218e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 219f4272c03SJulia Lawall * of the mkvp into the cache. Try 3 times: First without verify 220efc598e6SHarald Freudenberger * then with verify and last round with verify and old master 221efc598e6SHarald Freudenberger * key verification pattern match not ignored. 222e80d4af0SHarald Freudenberger */ 223efc598e6SHarald Freudenberger for (verify = 0; verify < 3; verify++) { 224f2bbc96eSHarald Freudenberger rc = cca_findcard(key, &cardnr, &domain, verify); 225efc598e6SHarald Freudenberger if (rc < 0) 226e80d4af0SHarald Freudenberger continue; 227efc598e6SHarald Freudenberger if (rc > 0 && verify < 2) 228efc598e6SHarald Freudenberger continue; 229f2bbc96eSHarald Freudenberger switch (hdr->version) { 230f2bbc96eSHarald Freudenberger case TOKVER_CCA_AES: 231f370f45cSHarald Freudenberger rc = cca_sec2protkey(cardnr, domain, key, 232f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 233f2bbc96eSHarald Freudenberger break; 234f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 235f370f45cSHarald Freudenberger rc = cca_cipher2protkey(cardnr, domain, key, 236f370f45cSHarald Freudenberger protkey, protkeylen, 237f370f45cSHarald Freudenberger protkeytype); 238f2bbc96eSHarald Freudenberger break; 239f2bbc96eSHarald Freudenberger default: 240f2bbc96eSHarald Freudenberger return -EINVAL; 241f2bbc96eSHarald Freudenberger } 242e80d4af0SHarald Freudenberger if (rc == 0) 243e80d4af0SHarald Freudenberger break; 244e80d4af0SHarald Freudenberger } 245e80d4af0SHarald Freudenberger 246e80d4af0SHarald Freudenberger if (rc) 247ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 248e80d4af0SHarald Freudenberger 249e80d4af0SHarald Freudenberger return rc; 250e80d4af0SHarald Freudenberger } 251e80d4af0SHarald Freudenberger 252e80d4af0SHarald Freudenberger /* 25355d0a513SHarald Freudenberger * Construct EP11 key with given clear key value. 25455d0a513SHarald Freudenberger */ 25555d0a513SHarald Freudenberger static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, 25655d0a513SHarald Freudenberger u8 *keybuf, size_t *keybuflen) 25755d0a513SHarald Freudenberger { 25855d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 25946a29b03SHarald Freudenberger u16 card, dom; 26046a29b03SHarald Freudenberger int i, rc; 26155d0a513SHarald Freudenberger 26243cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 26343cb5a7cSHarald Freudenberger 26455d0a513SHarald Freudenberger /* build a list of apqns suitable for ep11 keys with cpacf support */ 26555d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 266*386cb81eSHolger Dengler ZCRYPT_CEX7, 267*386cb81eSHolger Dengler ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, 268*386cb81eSHolger Dengler NULL); 26955d0a513SHarald Freudenberger if (rc) 27055d0a513SHarald Freudenberger goto out; 27155d0a513SHarald Freudenberger 27255d0a513SHarald Freudenberger /* go through the list of apqns and try to bild an ep11 key */ 27355d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 27455d0a513SHarald Freudenberger card = apqns[i] >> 16; 27555d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 27655d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, clrkeylen * 8, 277da2863f1SHolger Dengler 0, clrkey, keybuf, keybuflen, 278da2863f1SHolger Dengler PKEY_TYPE_EP11); 27955d0a513SHarald Freudenberger if (rc == 0) 28055d0a513SHarald Freudenberger break; 28155d0a513SHarald Freudenberger } 28255d0a513SHarald Freudenberger 28355d0a513SHarald Freudenberger out: 28455d0a513SHarald Freudenberger kfree(apqns); 28555d0a513SHarald Freudenberger if (rc) 28655d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 28755d0a513SHarald Freudenberger return rc; 28855d0a513SHarald Freudenberger } 28955d0a513SHarald Freudenberger 29055d0a513SHarald Freudenberger /* 29155d0a513SHarald Freudenberger * Find card and transform EP11 secure key into protected key. 29255d0a513SHarald Freudenberger */ 293d1fdfb0bSHolger Dengler static int pkey_ep11key2pkey(const u8 *key, size_t keylen, 294d1fdfb0bSHolger Dengler u8 *protkey, u32 *protkeylen, u32 *protkeytype) 29555d0a513SHarald Freudenberger { 29646a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 29746a29b03SHarald Freudenberger u16 card, dom; 29846a29b03SHarald Freudenberger int i, rc; 29955d0a513SHarald Freudenberger 30043cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 30143cb5a7cSHarald Freudenberger 30255d0a513SHarald Freudenberger /* build a list of apqns suitable for this key */ 30355d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 304*386cb81eSHolger Dengler ZCRYPT_CEX7, 305*386cb81eSHolger Dengler ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, 306d1fdfb0bSHolger Dengler ep11_kb_wkvp(key, keylen)); 30755d0a513SHarald Freudenberger if (rc) 30855d0a513SHarald Freudenberger goto out; 30955d0a513SHarald Freudenberger 31055d0a513SHarald Freudenberger /* go through the list of apqns and try to derive an pkey */ 31155d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 31255d0a513SHarald Freudenberger card = apqns[i] >> 16; 31355d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 314d1fdfb0bSHolger Dengler rc = ep11_kblob2protkey(card, dom, key, keylen, 315f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 31655d0a513SHarald Freudenberger if (rc == 0) 31755d0a513SHarald Freudenberger break; 31855d0a513SHarald Freudenberger } 31955d0a513SHarald Freudenberger 32055d0a513SHarald Freudenberger out: 32155d0a513SHarald Freudenberger kfree(apqns); 32255d0a513SHarald Freudenberger if (rc) 32355d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 32455d0a513SHarald Freudenberger return rc; 32555d0a513SHarald Freudenberger } 32655d0a513SHarald Freudenberger 32755d0a513SHarald Freudenberger /* 328e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 329e61a6134SHarald Freudenberger */ 330183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey, 331e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 332e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 333e61a6134SHarald Freudenberger { 334e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)seckey; 335e61a6134SHarald Freudenberger u16 cardnr, domain; 336e61a6134SHarald Freudenberger int rc; 337e61a6134SHarald Freudenberger 338e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 339efc598e6SHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *)seckey, 0); 340e61a6134SHarald Freudenberger if (rc) 341e61a6134SHarald Freudenberger goto out; 342e61a6134SHarald Freudenberger if (pattributes) 343e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 344e61a6134SHarald Freudenberger if (pkeysize) 345e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 346e61a6134SHarald Freudenberger 347e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 348efc598e6SHarald Freudenberger rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); 349efc598e6SHarald Freudenberger if (rc < 0) 350e61a6134SHarald Freudenberger goto out; 351e61a6134SHarald Freudenberger 352efc598e6SHarald Freudenberger if (rc > 0) { 353efc598e6SHarald Freudenberger /* key mkvp matches to old master key mkvp */ 354ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 355e61a6134SHarald Freudenberger if (pattributes) 356e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 357efc598e6SHarald Freudenberger rc = 0; 358e61a6134SHarald Freudenberger } 359e61a6134SHarald Freudenberger 360e61a6134SHarald Freudenberger if (pcardnr) 361e61a6134SHarald Freudenberger *pcardnr = cardnr; 362e61a6134SHarald Freudenberger if (pdomain) 363e61a6134SHarald Freudenberger *pdomain = domain; 364e61a6134SHarald Freudenberger 365e61a6134SHarald Freudenberger out: 366ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 367e61a6134SHarald Freudenberger return rc; 368e61a6134SHarald Freudenberger } 369e61a6134SHarald Freudenberger 370e61a6134SHarald Freudenberger /* 371a45a5c7dSIngo Franzki * Generate a random protected key 372a45a5c7dSIngo Franzki */ 373f370f45cSHarald Freudenberger static int pkey_genprotkey(u32 keytype, u8 *protkey, 374f370f45cSHarald Freudenberger u32 *protkeylen, u32 *protkeytype) 375a45a5c7dSIngo Franzki { 376f370f45cSHarald Freudenberger u8 clrkey[32]; 377a45a5c7dSIngo Franzki int keysize; 378a45a5c7dSIngo Franzki int rc; 379a45a5c7dSIngo Franzki 3809e436c19SHarald Freudenberger keysize = pkey_keytype_aes_to_size(keytype); 3819e436c19SHarald Freudenberger if (!keysize) { 382a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 383a45a5c7dSIngo Franzki keytype); 384a45a5c7dSIngo Franzki return -EINVAL; 385a45a5c7dSIngo Franzki } 386a45a5c7dSIngo Franzki 387a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 388f370f45cSHarald Freudenberger get_random_bytes(clrkey, keysize); 389a45a5c7dSIngo Franzki 390a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 391f370f45cSHarald Freudenberger rc = pkey_clr2protkey(keytype, clrkey, 392f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 393a45a5c7dSIngo Franzki if (rc) 394a45a5c7dSIngo Franzki return rc; 395a45a5c7dSIngo Franzki 396a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 397f370f45cSHarald Freudenberger get_random_bytes(protkey, keysize); 398a45a5c7dSIngo Franzki 399a45a5c7dSIngo Franzki return 0; 400a45a5c7dSIngo Franzki } 401a45a5c7dSIngo Franzki 402a45a5c7dSIngo Franzki /* 403cb26b9ffSIngo Franzki * Verify if a protected key is still valid 404cb26b9ffSIngo Franzki */ 405f370f45cSHarald Freudenberger static int pkey_verifyprotkey(const u8 *protkey, u32 protkeylen, 406f370f45cSHarald Freudenberger u32 protkeytype) 407cb26b9ffSIngo Franzki { 408cb26b9ffSIngo Franzki struct { 409cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 410cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 411cb26b9ffSIngo Franzki } param; 412cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 413cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 414f370f45cSHarald Freudenberger unsigned int k, pkeylen; 41546a29b03SHarald Freudenberger unsigned long fc; 416cb26b9ffSIngo Franzki 417f370f45cSHarald Freudenberger switch (protkeytype) { 418cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 419f370f45cSHarald Freudenberger pkeylen = 16 + AES_WK_VP_SIZE; 420cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 421cb26b9ffSIngo Franzki break; 422cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 423f370f45cSHarald Freudenberger pkeylen = 24 + AES_WK_VP_SIZE; 424cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 425cb26b9ffSIngo Franzki break; 426cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 427f370f45cSHarald Freudenberger pkeylen = 32 + AES_WK_VP_SIZE; 428cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 429cb26b9ffSIngo Franzki break; 430cb26b9ffSIngo Franzki default: 431f370f45cSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", __func__, 432f370f45cSHarald Freudenberger protkeytype); 433f370f45cSHarald Freudenberger return -EINVAL; 434f370f45cSHarald Freudenberger } 435f370f45cSHarald Freudenberger if (protkeylen != pkeylen) { 436f370f45cSHarald Freudenberger DEBUG_ERR("%s invalid protected key size %u for keytype %u\n", 437f370f45cSHarald Freudenberger __func__, protkeylen, protkeytype); 438cb26b9ffSIngo Franzki return -EINVAL; 439cb26b9ffSIngo Franzki } 440cb26b9ffSIngo Franzki 441cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 442cb26b9ffSIngo Franzki 443cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 444f370f45cSHarald Freudenberger memcpy(param.key, protkey, protkeylen); 445cb26b9ffSIngo Franzki 446cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 447cb26b9ffSIngo Franzki sizeof(null_msg)); 448cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 449cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 450cb26b9ffSIngo Franzki return -EKEYREJECTED; 451cb26b9ffSIngo Franzki } 452cb26b9ffSIngo Franzki 453cb26b9ffSIngo Franzki return 0; 454cb26b9ffSIngo Franzki } 455cb26b9ffSIngo Franzki 4569e436c19SHarald Freudenberger /* Helper for pkey_nonccatok2pkey, handles aes clear key token */ 4579e436c19SHarald Freudenberger static int nonccatokaes2pkey(const struct clearkeytoken *t, 4589e436c19SHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 4599e436c19SHarald Freudenberger { 4609e436c19SHarald Freudenberger size_t tmpbuflen = max_t(size_t, SECKEYBLOBSIZE, MAXEP11AESKEYBLOBSIZE); 4619e436c19SHarald Freudenberger u8 *tmpbuf = NULL; 4629e436c19SHarald Freudenberger u32 keysize; 4639e436c19SHarald Freudenberger int rc; 4649e436c19SHarald Freudenberger 4659e436c19SHarald Freudenberger keysize = pkey_keytype_aes_to_size(t->keytype); 4669e436c19SHarald Freudenberger if (!keysize) { 4679e436c19SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", 4689e436c19SHarald Freudenberger __func__, t->keytype); 4699e436c19SHarald Freudenberger return -EINVAL; 4709e436c19SHarald Freudenberger } 4719e436c19SHarald Freudenberger if (t->len != keysize) { 4729e436c19SHarald Freudenberger DEBUG_ERR("%s non clear key aes token: invalid key len %u\n", 4739e436c19SHarald Freudenberger __func__, t->len); 4749e436c19SHarald Freudenberger return -EINVAL; 4759e436c19SHarald Freudenberger } 4769e436c19SHarald Freudenberger 4779e436c19SHarald Freudenberger /* try direct way with the PCKMO instruction */ 4789e436c19SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, t->clearkey, 4799e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 4809e436c19SHarald Freudenberger if (!rc) 4819e436c19SHarald Freudenberger goto out; 4829e436c19SHarald Freudenberger 4839e436c19SHarald Freudenberger /* PCKMO failed, so try the CCA secure key way */ 4849e436c19SHarald Freudenberger tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 4859e436c19SHarald Freudenberger if (!tmpbuf) 4869e436c19SHarald Freudenberger return -ENOMEM; 4879e436c19SHarald Freudenberger zcrypt_wait_api_operational(); 4889e436c19SHarald Freudenberger rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, t->clearkey, tmpbuf); 4899e436c19SHarald Freudenberger if (rc) 4909e436c19SHarald Freudenberger goto try_via_ep11; 4919e436c19SHarald Freudenberger rc = pkey_skey2pkey(tmpbuf, 4929e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 4939e436c19SHarald Freudenberger if (!rc) 4949e436c19SHarald Freudenberger goto out; 4959e436c19SHarald Freudenberger 4969e436c19SHarald Freudenberger try_via_ep11: 4979e436c19SHarald Freudenberger /* if the CCA way also failed, let's try via EP11 */ 4989e436c19SHarald Freudenberger rc = pkey_clr2ep11key(t->clearkey, t->len, 4999e436c19SHarald Freudenberger tmpbuf, &tmpbuflen); 5009e436c19SHarald Freudenberger if (rc) 5019e436c19SHarald Freudenberger goto failure; 502d1fdfb0bSHolger Dengler rc = pkey_ep11key2pkey(tmpbuf, tmpbuflen, 5039e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 5049e436c19SHarald Freudenberger if (!rc) 5059e436c19SHarald Freudenberger goto out; 5069e436c19SHarald Freudenberger 5079e436c19SHarald Freudenberger failure: 5089e436c19SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", __func__); 5099e436c19SHarald Freudenberger 5109e436c19SHarald Freudenberger out: 5119e436c19SHarald Freudenberger kfree(tmpbuf); 5129e436c19SHarald Freudenberger return rc; 5139e436c19SHarald Freudenberger } 5149e436c19SHarald Freudenberger 5159e436c19SHarald Freudenberger /* Helper for pkey_nonccatok2pkey, handles ecc clear key token */ 5169e436c19SHarald Freudenberger static int nonccatokecc2pkey(const struct clearkeytoken *t, 5179e436c19SHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 5189e436c19SHarald Freudenberger { 5199e436c19SHarald Freudenberger u32 keylen; 5209e436c19SHarald Freudenberger int rc; 5219e436c19SHarald Freudenberger 5229e436c19SHarald Freudenberger switch (t->keytype) { 5239e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P256: 5249e436c19SHarald Freudenberger keylen = 32; 5259e436c19SHarald Freudenberger break; 5269e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P384: 5279e436c19SHarald Freudenberger keylen = 48; 5289e436c19SHarald Freudenberger break; 5299e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P521: 5309e436c19SHarald Freudenberger keylen = 80; 5319e436c19SHarald Freudenberger break; 5329e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED25519: 5339e436c19SHarald Freudenberger keylen = 32; 5349e436c19SHarald Freudenberger break; 5359e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED448: 5369e436c19SHarald Freudenberger keylen = 64; 5379e436c19SHarald Freudenberger break; 5389e436c19SHarald Freudenberger default: 5399e436c19SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", 5409e436c19SHarald Freudenberger __func__, t->keytype); 5419e436c19SHarald Freudenberger return -EINVAL; 5429e436c19SHarald Freudenberger } 5439e436c19SHarald Freudenberger 5449e436c19SHarald Freudenberger if (t->len != keylen) { 5459e436c19SHarald Freudenberger DEBUG_ERR("%s non clear key ecc token: invalid key len %u\n", 5469e436c19SHarald Freudenberger __func__, t->len); 5479e436c19SHarald Freudenberger return -EINVAL; 5489e436c19SHarald Freudenberger } 5499e436c19SHarald Freudenberger 5509e436c19SHarald Freudenberger /* only one path possible: via PCKMO instruction */ 5519e436c19SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, t->clearkey, 5529e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 5539e436c19SHarald Freudenberger if (rc) { 5549e436c19SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", 5559e436c19SHarald Freudenberger __func__); 5569e436c19SHarald Freudenberger } 5579e436c19SHarald Freudenberger 5589e436c19SHarald Freudenberger return rc; 5599e436c19SHarald Freudenberger } 5609e436c19SHarald Freudenberger 561cb26b9ffSIngo Franzki /* 562fb1136d6SIngo Franzki * Transform a non-CCA key token into a protected key 563fb1136d6SIngo Franzki */ 564183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, 565f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 566fb1136d6SIngo Franzki { 567fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 56846a29b03SHarald Freudenberger int rc = -EINVAL; 569fb1136d6SIngo Franzki 570fb1136d6SIngo Franzki switch (hdr->version) { 571888edbc4SHarald Freudenberger case TOKVER_PROTECTED_KEY: { 572888edbc4SHarald Freudenberger struct protaeskeytoken *t; 573fb1136d6SIngo Franzki 574888edbc4SHarald Freudenberger if (keylen != sizeof(struct protaeskeytoken)) 575888edbc4SHarald Freudenberger goto out; 576fb1136d6SIngo Franzki t = (struct protaeskeytoken *)key; 577f370f45cSHarald Freudenberger rc = pkey_verifyprotkey(t->protkey, t->len, t->keytype); 578f370f45cSHarald Freudenberger if (rc) 579f370f45cSHarald Freudenberger goto out; 580f370f45cSHarald Freudenberger memcpy(protkey, t->protkey, t->len); 581f370f45cSHarald Freudenberger *protkeylen = t->len; 582f370f45cSHarald Freudenberger *protkeytype = t->keytype; 583888edbc4SHarald Freudenberger break; 584888edbc4SHarald Freudenberger } 585888edbc4SHarald Freudenberger case TOKVER_CLEAR_KEY: { 5869e436c19SHarald Freudenberger struct clearkeytoken *t = (struct clearkeytoken *)key; 587fb1136d6SIngo Franzki 5889e436c19SHarald Freudenberger if (keylen < sizeof(struct clearkeytoken) || 5899e436c19SHarald Freudenberger keylen != sizeof(*t) + t->len) 590888edbc4SHarald Freudenberger goto out; 5919e436c19SHarald Freudenberger switch (t->keytype) { 5929e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 5939e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 5949e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 5959e436c19SHarald Freudenberger rc = nonccatokaes2pkey(t, protkey, 5969e436c19SHarald Freudenberger protkeylen, protkeytype); 5979e436c19SHarald Freudenberger break; 5989e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P256: 5999e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P384: 6009e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P521: 6019e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED25519: 6029e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED448: 6039e436c19SHarald Freudenberger rc = nonccatokecc2pkey(t, protkey, 6049e436c19SHarald Freudenberger protkeylen, protkeytype); 6059e436c19SHarald Freudenberger break; 6069e436c19SHarald Freudenberger default: 6079e436c19SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported non cca clear key type %u\n", 6089e436c19SHarald Freudenberger __func__, t->keytype); 6099e436c19SHarald Freudenberger return -EINVAL; 61055d0a513SHarald Freudenberger } 611888edbc4SHarald Freudenberger break; 612888edbc4SHarald Freudenberger } 61355d0a513SHarald Freudenberger case TOKVER_EP11_AES: { 61455d0a513SHarald Freudenberger /* check ep11 key for exportable as protected key */ 615fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 61655d0a513SHarald Freudenberger if (rc) 61755d0a513SHarald Freudenberger goto out; 618d1fdfb0bSHolger Dengler rc = pkey_ep11key2pkey(key, keylen, 619f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 62055d0a513SHarald Freudenberger break; 62155d0a513SHarald Freudenberger } 622fa6999e3SHarald Freudenberger case TOKVER_EP11_AES_WITH_HEADER: 623fa6999e3SHarald Freudenberger /* check ep11 key with header for exportable as protected key */ 624fa6999e3SHarald Freudenberger rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1); 625fa6999e3SHarald Freudenberger if (rc) 626fa6999e3SHarald Freudenberger goto out; 627d1fdfb0bSHolger Dengler rc = pkey_ep11key2pkey(key, keylen, 628f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 629fa6999e3SHarald Freudenberger break; 630fb1136d6SIngo Franzki default: 631fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 632fb1136d6SIngo Franzki __func__, hdr->version); 633fb1136d6SIngo Franzki } 634888edbc4SHarald Freudenberger 635888edbc4SHarald Freudenberger out: 636888edbc4SHarald Freudenberger return rc; 637fb1136d6SIngo Franzki } 638fb1136d6SIngo Franzki 639fb1136d6SIngo Franzki /* 640fb1136d6SIngo Franzki * Transform a CCA internal key token into a protected key 641fb1136d6SIngo Franzki */ 642183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, 643f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 644fb1136d6SIngo Franzki { 645fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 646fb1136d6SIngo Franzki 647fb1136d6SIngo Franzki switch (hdr->version) { 648fb1136d6SIngo Franzki case TOKVER_CCA_AES: 649fb1136d6SIngo Franzki if (keylen != sizeof(struct secaeskeytoken)) 650fb1136d6SIngo Franzki return -EINVAL; 651f2bbc96eSHarald Freudenberger break; 652f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 653f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 654f2bbc96eSHarald Freudenberger return -EINVAL; 655f2bbc96eSHarald Freudenberger break; 656fb1136d6SIngo Franzki default: 657fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 658fb1136d6SIngo Franzki __func__, hdr->version); 659fb1136d6SIngo Franzki return -EINVAL; 660fb1136d6SIngo Franzki } 661f2bbc96eSHarald Freudenberger 662f370f45cSHarald Freudenberger return pkey_skey2pkey(key, protkey, protkeylen, protkeytype); 663fb1136d6SIngo Franzki } 664fb1136d6SIngo Franzki 665fb1136d6SIngo Franzki /* 666fb1136d6SIngo Franzki * Transform a key blob (of any type) into a protected key 667fb1136d6SIngo Franzki */ 668183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen, 669f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 670fb1136d6SIngo Franzki { 671fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 67246a29b03SHarald Freudenberger int rc; 673fb1136d6SIngo Franzki 674f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) { 675f2bbc96eSHarald Freudenberger DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); 676f2bbc96eSHarald Freudenberger return -EINVAL; 677f2bbc96eSHarald Freudenberger } 678f2bbc96eSHarald Freudenberger 679f2bbc96eSHarald Freudenberger switch (hdr->type) { 680f2bbc96eSHarald Freudenberger case TOKTYPE_NON_CCA: 681f370f45cSHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, 682f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 683f2bbc96eSHarald Freudenberger break; 684f2bbc96eSHarald Freudenberger case TOKTYPE_CCA_INTERNAL: 685f370f45cSHarald Freudenberger rc = pkey_ccainttok2pkey(key, keylen, 686f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 687f2bbc96eSHarald Freudenberger break; 688f2bbc96eSHarald Freudenberger default: 689f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 690f2bbc96eSHarald Freudenberger __func__, hdr->type); 691f2bbc96eSHarald Freudenberger return -EINVAL; 692f2bbc96eSHarald Freudenberger } 693f2bbc96eSHarald Freudenberger 694f2bbc96eSHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 695f2bbc96eSHarald Freudenberger return rc; 696f2bbc96eSHarald Freudenberger } 697f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey); 698f2bbc96eSHarald Freudenberger 699f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 700f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 701f2bbc96eSHarald Freudenberger u32 kflags, u8 *keybuf, size_t *keybufsize) 702f2bbc96eSHarald Freudenberger { 703f2bbc96eSHarald Freudenberger int i, card, dom, rc; 704f2bbc96eSHarald Freudenberger 705f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 706f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 707f2bbc96eSHarald Freudenberger return -EINVAL; 708f2bbc96eSHarald Freudenberger 709f2bbc96eSHarald Freudenberger /* check key type and size */ 710f2bbc96eSHarald Freudenberger switch (ktype) { 711f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 712f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 713f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 714f2bbc96eSHarald Freudenberger return -EINVAL; 715f2bbc96eSHarald Freudenberger break; 71655d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 71755d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 71855d0a513SHarald Freudenberger return -EINVAL; 71955d0a513SHarald Freudenberger break; 720fb249ce7SHolger Dengler case PKEY_TYPE_EP11_AES: 721fb249ce7SHolger Dengler if (*keybufsize < (sizeof(struct ep11kblob_header) + 722fb249ce7SHolger Dengler MINEP11AESKEYBLOBSIZE)) 723fb249ce7SHolger Dengler return -EINVAL; 724fb249ce7SHolger Dengler break; 725f2bbc96eSHarald Freudenberger default: 726f2bbc96eSHarald Freudenberger return -EINVAL; 727f2bbc96eSHarald Freudenberger } 728f2bbc96eSHarald Freudenberger switch (ksize) { 729f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 730f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 731f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 732f2bbc96eSHarald Freudenberger break; 733f2bbc96eSHarald Freudenberger default: 734f2bbc96eSHarald Freudenberger return -EINVAL; 735f2bbc96eSHarald Freudenberger } 736f2bbc96eSHarald Freudenberger 737f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 738f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 739f2bbc96eSHarald Freudenberger card = apqns[i].card; 740f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 741fb249ce7SHolger Dengler if (ktype == PKEY_TYPE_EP11 || 742fb249ce7SHolger Dengler ktype == PKEY_TYPE_EP11_AES) { 74355d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, ksize, kflags, 744fb249ce7SHolger Dengler keybuf, keybufsize, ktype); 74555d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 746f2bbc96eSHarald Freudenberger rc = cca_genseckey(card, dom, ksize, keybuf); 747f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 7482004b57cSHarald Freudenberger } else { 7492004b57cSHarald Freudenberger /* TOKVER_CCA_VLSC */ 750f2bbc96eSHarald Freudenberger rc = cca_gencipherkey(card, dom, ksize, kflags, 751f2bbc96eSHarald Freudenberger keybuf, keybufsize); 7522004b57cSHarald Freudenberger } 753f2bbc96eSHarald Freudenberger if (rc == 0) 754f2bbc96eSHarald Freudenberger break; 755f2bbc96eSHarald Freudenberger } 756f2bbc96eSHarald Freudenberger 757f2bbc96eSHarald Freudenberger return rc; 758f2bbc96eSHarald Freudenberger } 759f2bbc96eSHarald Freudenberger 760f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 761f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 762f2bbc96eSHarald Freudenberger u32 kflags, const u8 *clrkey, 763f2bbc96eSHarald Freudenberger u8 *keybuf, size_t *keybufsize) 764f2bbc96eSHarald Freudenberger { 765f2bbc96eSHarald Freudenberger int i, card, dom, rc; 766f2bbc96eSHarald Freudenberger 767f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 768f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 769f2bbc96eSHarald Freudenberger return -EINVAL; 770f2bbc96eSHarald Freudenberger 771f2bbc96eSHarald Freudenberger /* check key type and size */ 772f2bbc96eSHarald Freudenberger switch (ktype) { 773f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 774f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 775f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 776f2bbc96eSHarald Freudenberger return -EINVAL; 777f2bbc96eSHarald Freudenberger break; 77855d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 77955d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 78055d0a513SHarald Freudenberger return -EINVAL; 78155d0a513SHarald Freudenberger break; 782da2863f1SHolger Dengler case PKEY_TYPE_EP11_AES: 783da2863f1SHolger Dengler if (*keybufsize < (sizeof(struct ep11kblob_header) + 784da2863f1SHolger Dengler MINEP11AESKEYBLOBSIZE)) 785da2863f1SHolger Dengler return -EINVAL; 786da2863f1SHolger Dengler break; 787f2bbc96eSHarald Freudenberger default: 788f2bbc96eSHarald Freudenberger return -EINVAL; 789f2bbc96eSHarald Freudenberger } 790f2bbc96eSHarald Freudenberger switch (ksize) { 791f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 792f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 793f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 794f2bbc96eSHarald Freudenberger break; 795f2bbc96eSHarald Freudenberger default: 796f2bbc96eSHarald Freudenberger return -EINVAL; 797f2bbc96eSHarald Freudenberger } 798f2bbc96eSHarald Freudenberger 79943cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 80043cb5a7cSHarald Freudenberger 801f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 802f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 803f2bbc96eSHarald Freudenberger card = apqns[i].card; 804f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 805da2863f1SHolger Dengler if (ktype == PKEY_TYPE_EP11 || 806da2863f1SHolger Dengler ktype == PKEY_TYPE_EP11_AES) { 80755d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, ksize, kflags, 808da2863f1SHolger Dengler clrkey, keybuf, keybufsize, 809da2863f1SHolger Dengler ktype); 81055d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 811f2bbc96eSHarald Freudenberger rc = cca_clr2seckey(card, dom, ksize, 812f2bbc96eSHarald Freudenberger clrkey, keybuf); 813f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 8142004b57cSHarald Freudenberger } else { 8152004b57cSHarald Freudenberger /* TOKVER_CCA_VLSC */ 816f2bbc96eSHarald Freudenberger rc = cca_clr2cipherkey(card, dom, ksize, kflags, 817f2bbc96eSHarald Freudenberger clrkey, keybuf, keybufsize); 8182004b57cSHarald Freudenberger } 819f2bbc96eSHarald Freudenberger if (rc == 0) 820f2bbc96eSHarald Freudenberger break; 821f2bbc96eSHarald Freudenberger } 822f2bbc96eSHarald Freudenberger 823f2bbc96eSHarald Freudenberger return rc; 824f2bbc96eSHarald Freudenberger } 825f2bbc96eSHarald Freudenberger 826f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen, 827f2bbc96eSHarald Freudenberger u16 *cardnr, u16 *domain, 828f2bbc96eSHarald Freudenberger enum pkey_key_type *ktype, 829f2bbc96eSHarald Freudenberger enum pkey_key_size *ksize, u32 *flags) 830f2bbc96eSHarald Freudenberger { 831f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 83246a29b03SHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 83346a29b03SHarald Freudenberger int rc; 834f2bbc96eSHarald Freudenberger 83555d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 836f2bbc96eSHarald Freudenberger return -EINVAL; 837f2bbc96eSHarald Freudenberger 8382004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 8392004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 840f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 841f2bbc96eSHarald Freudenberger 842f2bbc96eSHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 843f2bbc96eSHarald Freudenberger if (rc) 844f2bbc96eSHarald Freudenberger goto out; 845f2bbc96eSHarald Freudenberger if (ktype) 846f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_DATA; 847f2bbc96eSHarald Freudenberger if (ksize) 848f2bbc96eSHarald Freudenberger *ksize = (enum pkey_key_size)t->bitsize; 849f2bbc96eSHarald Freudenberger 850f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 85132ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); 852f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 853f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 854f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 855f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 856f2bbc96eSHarald Freudenberger *cardnr, *domain, 85732ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, 85832ca04bbSHarald Freudenberger 0, t->mkvp, 1); 859f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 860f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 861f2bbc96eSHarald Freudenberger } 862f2bbc96eSHarald Freudenberger if (rc) 863f2bbc96eSHarald Freudenberger goto out; 864f2bbc96eSHarald Freudenberger 865f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 866f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 867f2bbc96eSHarald Freudenberger 8682004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 8692004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 870f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 871f2bbc96eSHarald Freudenberger 872f2bbc96eSHarald Freudenberger rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 873f2bbc96eSHarald Freudenberger if (rc) 874f2bbc96eSHarald Freudenberger goto out; 875f2bbc96eSHarald Freudenberger if (ktype) 876f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_CIPHER; 877f2bbc96eSHarald Freudenberger if (ksize) { 878f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_UNKNOWN; 879f2bbc96eSHarald Freudenberger if (!t->plfver && t->wpllen == 512) 880f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_128; 881f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 882f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_192; 883f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 884f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_256; 885f2bbc96eSHarald Freudenberger } 886f2bbc96eSHarald Freudenberger 887f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 88832ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); 889f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 890f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 891f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 892f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 893f2bbc96eSHarald Freudenberger *cardnr, *domain, 89432ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, 89532ca04bbSHarald Freudenberger 0, t->mkvp0, 1); 896f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 897f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 898f2bbc96eSHarald Freudenberger } 899f2bbc96eSHarald Freudenberger if (rc) 900f2bbc96eSHarald Freudenberger goto out; 901f2bbc96eSHarald Freudenberger 902f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 903f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 904f2bbc96eSHarald Freudenberger 9052004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 9062004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES) { 90755d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 908*386cb81eSHolger Dengler int api; 90955d0a513SHarald Freudenberger 910fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 91155d0a513SHarald Freudenberger if (rc) 91255d0a513SHarald Freudenberger goto out; 91355d0a513SHarald Freudenberger if (ktype) 91455d0a513SHarald Freudenberger *ktype = PKEY_TYPE_EP11; 91555d0a513SHarald Freudenberger if (ksize) 91637a08f01SHolger Dengler *ksize = kb->head.bitlen; 91755d0a513SHarald Freudenberger 918*386cb81eSHolger Dengler api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; 91955d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 920*386cb81eSHolger Dengler ZCRYPT_CEX7, api, 921745742dbSHolger Dengler ep11_kb_wkvp(key, keylen)); 92255d0a513SHarald Freudenberger if (rc) 92355d0a513SHarald Freudenberger goto out; 92455d0a513SHarald Freudenberger 92555d0a513SHarald Freudenberger if (flags) 92655d0a513SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 92755d0a513SHarald Freudenberger 92855d0a513SHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 92955d0a513SHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 93055d0a513SHarald Freudenberger 931745742dbSHolger Dengler } else if (hdr->type == TOKTYPE_NON_CCA && 932745742dbSHolger Dengler hdr->version == TOKVER_EP11_AES_WITH_HEADER) { 933745742dbSHolger Dengler struct ep11kblob_header *kh = (struct ep11kblob_header *)key; 934*386cb81eSHolger Dengler int api; 935745742dbSHolger Dengler 936745742dbSHolger Dengler rc = ep11_check_aes_key_with_hdr(debug_info, 3, 937745742dbSHolger Dengler key, keylen, 1); 938745742dbSHolger Dengler if (rc) 939745742dbSHolger Dengler goto out; 940745742dbSHolger Dengler if (ktype) 941745742dbSHolger Dengler *ktype = PKEY_TYPE_EP11_AES; 942745742dbSHolger Dengler if (ksize) 943745742dbSHolger Dengler *ksize = kh->bitlen; 944745742dbSHolger Dengler 945*386cb81eSHolger Dengler api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; 946745742dbSHolger Dengler rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 947*386cb81eSHolger Dengler ZCRYPT_CEX7, api, 948745742dbSHolger Dengler ep11_kb_wkvp(key, keylen)); 949745742dbSHolger Dengler if (rc) 950745742dbSHolger Dengler goto out; 951745742dbSHolger Dengler 952745742dbSHolger Dengler if (flags) 953745742dbSHolger Dengler *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 954745742dbSHolger Dengler 955745742dbSHolger Dengler *cardnr = ((struct pkey_apqn *)_apqns)->card; 956745742dbSHolger Dengler *domain = ((struct pkey_apqn *)_apqns)->domain; 9572004b57cSHarald Freudenberger } else { 958f2bbc96eSHarald Freudenberger rc = -EINVAL; 9592004b57cSHarald Freudenberger } 960f2bbc96eSHarald Freudenberger 961f2bbc96eSHarald Freudenberger out: 962f2bbc96eSHarald Freudenberger kfree(_apqns); 963f2bbc96eSHarald Freudenberger return rc; 964f2bbc96eSHarald Freudenberger } 965f2bbc96eSHarald Freudenberger 966f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 967f2bbc96eSHarald Freudenberger const u8 *key, size_t keylen, 968f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 969f2bbc96eSHarald Freudenberger { 970f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 97146a29b03SHarald Freudenberger int i, card, dom, rc; 972f2bbc96eSHarald Freudenberger 973f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 974f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 975f2bbc96eSHarald Freudenberger return -EINVAL; 976f2bbc96eSHarald Freudenberger 977fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 978fb1136d6SIngo Franzki return -EINVAL; 979fb1136d6SIngo Franzki 98055d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL) { 98155d0a513SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 982f2bbc96eSHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 983f2bbc96eSHarald Freudenberger return -EINVAL; 984f2bbc96eSHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 985f2bbc96eSHarald Freudenberger return -EINVAL; 98655d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 987f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 988f2bbc96eSHarald Freudenberger return -EINVAL; 989f2bbc96eSHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 990f2bbc96eSHarald Freudenberger return -EINVAL; 99155d0a513SHarald Freudenberger } else { 992f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 993f2bbc96eSHarald Freudenberger __func__, hdr->version); 994fb1136d6SIngo Franzki return -EINVAL; 995fb1136d6SIngo Franzki } 99655d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 99755d0a513SHarald Freudenberger if (hdr->version == TOKVER_EP11_AES) { 998fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 99955d0a513SHarald Freudenberger return -EINVAL; 1000d1fdfb0bSHolger Dengler } else if (hdr->version == TOKVER_EP11_AES_WITH_HEADER) { 1001d1fdfb0bSHolger Dengler if (ep11_check_aes_key_with_hdr(debug_info, 3, 1002d1fdfb0bSHolger Dengler key, keylen, 1)) 1003d1fdfb0bSHolger Dengler return -EINVAL; 100455d0a513SHarald Freudenberger } else { 1005f370f45cSHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, 1006f370f45cSHarald Freudenberger protkey, protkeylen, 1007f370f45cSHarald Freudenberger protkeytype); 100855d0a513SHarald Freudenberger } 100955d0a513SHarald Freudenberger } else { 1010f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 1011f2bbc96eSHarald Freudenberger __func__, hdr->type); 1012f2bbc96eSHarald Freudenberger return -EINVAL; 1013fb1136d6SIngo Franzki } 1014f2bbc96eSHarald Freudenberger 101543cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 101643cb5a7cSHarald Freudenberger 1017f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 1018f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 1019f2bbc96eSHarald Freudenberger card = apqns[i].card; 1020f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 10212004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 10222004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 1023f370f45cSHarald Freudenberger rc = cca_sec2protkey(card, dom, key, 1024f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 10252004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 10262004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 1027f370f45cSHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, 1028f370f45cSHarald Freudenberger protkey, protkeylen, 1029f370f45cSHarald Freudenberger protkeytype); 10302004b57cSHarald Freudenberger } else { 1031d1fdfb0bSHolger Dengler rc = ep11_kblob2protkey(card, dom, key, keylen, 1032f370f45cSHarald Freudenberger protkey, protkeylen, 1033f370f45cSHarald Freudenberger protkeytype); 103455d0a513SHarald Freudenberger } 1035f2bbc96eSHarald Freudenberger if (rc == 0) 1036f2bbc96eSHarald Freudenberger break; 1037f2bbc96eSHarald Freudenberger } 1038f2bbc96eSHarald Freudenberger 1039f2bbc96eSHarald Freudenberger return rc; 1040f2bbc96eSHarald Freudenberger } 1041f2bbc96eSHarald Freudenberger 1042f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 1043f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 1044f2bbc96eSHarald Freudenberger { 1045f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 104646a29b03SHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 104746a29b03SHarald Freudenberger int rc; 1048f2bbc96eSHarald Freudenberger 104955d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || flags == 0) 1050f2bbc96eSHarald Freudenberger return -EINVAL; 1051f2bbc96eSHarald Freudenberger 105243cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 105343cb5a7cSHarald Freudenberger 10542004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 10552004b57cSHarald Freudenberger (hdr->version == TOKVER_EP11_AES_WITH_HEADER || 10562004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && 10572004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1058fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) 1059fa6999e3SHarald Freudenberger (key + sizeof(struct ep11kblob_header)); 106046a29b03SHarald Freudenberger int minhwtype = 0, api = 0; 1061fa6999e3SHarald Freudenberger 1062fa6999e3SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 1063fa6999e3SHarald Freudenberger return -EINVAL; 1064fa6999e3SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 1065fa6999e3SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 1066*386cb81eSHolger Dengler api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; 1067fa6999e3SHarald Freudenberger } 1068fa6999e3SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1069fa6999e3SHarald Freudenberger minhwtype, api, kb->wkvp); 1070fa6999e3SHarald Freudenberger if (rc) 1071fa6999e3SHarald Freudenberger goto out; 10722004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 10732004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 10742004b57cSHarald Freudenberger is_ep11_keyblob(key)) { 107555d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 107646a29b03SHarald Freudenberger int minhwtype = 0, api = 0; 107755d0a513SHarald Freudenberger 107855d0a513SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 107955d0a513SHarald Freudenberger return -EINVAL; 108055d0a513SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 108155d0a513SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 1082*386cb81eSHolger Dengler api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; 108355d0a513SHarald Freudenberger } 108455d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 108555d0a513SHarald Freudenberger minhwtype, api, kb->wkvp); 108655d0a513SHarald Freudenberger if (rc) 108755d0a513SHarald Freudenberger goto out; 108855d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 1089f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 109046a29b03SHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 1091f2bbc96eSHarald Freudenberger 1092f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 1093f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 1094f2bbc96eSHarald Freudenberger 1095f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1096f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp; 1097f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1098f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp; 109955d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1100f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 1101f2bbc96eSHarald Freudenberger 1102f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 1103f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1104f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp0; 1105f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1106f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp0; 110755d0a513SHarald Freudenberger } else { 110855d0a513SHarald Freudenberger /* unknown cca internal token type */ 110955d0a513SHarald Freudenberger return -EINVAL; 1110f2bbc96eSHarald Freudenberger } 1111f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 111232ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 111332ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1114f2bbc96eSHarald Freudenberger if (rc) 1115f2bbc96eSHarald Freudenberger goto out; 1116fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1117fa6999e3SHarald Freudenberger struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; 111846a29b03SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1119fa6999e3SHarald Freudenberger 1120fa6999e3SHarald Freudenberger if (t->secid == 0x20) { 1121fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1122fa6999e3SHarald Freudenberger cur_mkvp = t->mkvp; 1123fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1124fa6999e3SHarald Freudenberger old_mkvp = t->mkvp; 1125fa6999e3SHarald Freudenberger } else { 1126fa6999e3SHarald Freudenberger /* unknown cca internal 2 token type */ 1127fa6999e3SHarald Freudenberger return -EINVAL; 1128fa6999e3SHarald Freudenberger } 1129fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1130fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 1131fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 1132fa6999e3SHarald Freudenberger if (rc) 1133fa6999e3SHarald Freudenberger goto out; 11342004b57cSHarald Freudenberger } else { 113555d0a513SHarald Freudenberger return -EINVAL; 11362004b57cSHarald Freudenberger } 113755d0a513SHarald Freudenberger 1138f2bbc96eSHarald Freudenberger if (apqns) { 1139f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 1140f2bbc96eSHarald Freudenberger rc = -ENOSPC; 1141f2bbc96eSHarald Freudenberger else 1142f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 1143f2bbc96eSHarald Freudenberger } 1144f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 1145f2bbc96eSHarald Freudenberger 1146f2bbc96eSHarald Freudenberger out: 1147f2bbc96eSHarald Freudenberger kfree(_apqns); 1148f2bbc96eSHarald Freudenberger return rc; 1149f2bbc96eSHarald Freudenberger } 1150f2bbc96eSHarald Freudenberger 1151f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype, 1152f2bbc96eSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 1153f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 1154f2bbc96eSHarald Freudenberger { 1155f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 115646a29b03SHarald Freudenberger int rc; 1157f2bbc96eSHarald Freudenberger 115843cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 115943cb5a7cSHarald Freudenberger 1160f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 1161f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1162f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 1163f2bbc96eSHarald Freudenberger 1164f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1165f2bbc96eSHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 1166f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1167f2bbc96eSHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 1168f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 1169f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 1170f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 117132ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 117232ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1173f2bbc96eSHarald Freudenberger if (rc) 1174f2bbc96eSHarald Freudenberger goto out; 1175fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_ECC) { 1176fa6999e3SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1177fa6999e3SHarald Freudenberger 1178fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1179fa6999e3SHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 1180fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1181fa6999e3SHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 1182fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1183fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 1184fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 1185fa6999e3SHarald Freudenberger if (rc) 1186fa6999e3SHarald Freudenberger goto out; 1187fa6999e3SHarald Freudenberger 1188fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_EP11 || 1189fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_AES || 1190fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_ECC) { 119155d0a513SHarald Freudenberger u8 *wkvp = NULL; 1192*386cb81eSHolger Dengler int api; 119355d0a513SHarald Freudenberger 119455d0a513SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 119555d0a513SHarald Freudenberger wkvp = cur_mkvp; 1196*386cb81eSHolger Dengler api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; 119755d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1198*386cb81eSHolger Dengler ZCRYPT_CEX7, api, wkvp); 119955d0a513SHarald Freudenberger if (rc) 120055d0a513SHarald Freudenberger goto out; 120155d0a513SHarald Freudenberger 12022004b57cSHarald Freudenberger } else { 120355d0a513SHarald Freudenberger return -EINVAL; 12042004b57cSHarald Freudenberger } 120555d0a513SHarald Freudenberger 1206f2bbc96eSHarald Freudenberger if (apqns) { 1207f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 1208f2bbc96eSHarald Freudenberger rc = -ENOSPC; 1209f2bbc96eSHarald Freudenberger else 1210f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 1211f2bbc96eSHarald Freudenberger } 1212f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 1213f2bbc96eSHarald Freudenberger 1214f2bbc96eSHarald Freudenberger out: 1215f2bbc96eSHarald Freudenberger kfree(_apqns); 1216f2bbc96eSHarald Freudenberger return rc; 1217f2bbc96eSHarald Freudenberger } 1218fb1136d6SIngo Franzki 1219fa6999e3SHarald Freudenberger static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, 1220f370f45cSHarald Freudenberger const u8 *key, size_t keylen, 1221f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 1222fa6999e3SHarald Freudenberger { 1223fa6999e3SHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 122446a29b03SHarald Freudenberger int i, card, dom, rc; 1225fa6999e3SHarald Freudenberger 1226fa6999e3SHarald Freudenberger /* check for at least one apqn given */ 1227fa6999e3SHarald Freudenberger if (!apqns || !nr_apqns) 1228fa6999e3SHarald Freudenberger return -EINVAL; 1229fa6999e3SHarald Freudenberger 1230fa6999e3SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 1231fa6999e3SHarald Freudenberger return -EINVAL; 1232fa6999e3SHarald Freudenberger 12332004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 12342004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES_WITH_HEADER && 12352004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1236fa6999e3SHarald Freudenberger /* EP11 AES key blob with header */ 1237fa6999e3SHarald Freudenberger if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1)) 1238fa6999e3SHarald Freudenberger return -EINVAL; 12392004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 12402004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER && 12412004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1242fa6999e3SHarald Freudenberger /* EP11 ECC key blob with header */ 1243fa6999e3SHarald Freudenberger if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1)) 1244fa6999e3SHarald Freudenberger return -EINVAL; 12452004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 12462004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 12472004b57cSHarald Freudenberger is_ep11_keyblob(key)) { 1248fa6999e3SHarald Freudenberger /* EP11 AES key blob with header in session field */ 1249fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 1250fa6999e3SHarald Freudenberger return -EINVAL; 1251fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 1252fa6999e3SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 1253fa6999e3SHarald Freudenberger /* CCA AES data key */ 1254fa6999e3SHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 1255fa6999e3SHarald Freudenberger return -EINVAL; 1256fa6999e3SHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 1257fa6999e3SHarald Freudenberger return -EINVAL; 1258fa6999e3SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1259fa6999e3SHarald Freudenberger /* CCA AES cipher key */ 1260fa6999e3SHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 1261fa6999e3SHarald Freudenberger return -EINVAL; 1262fa6999e3SHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 1263fa6999e3SHarald Freudenberger return -EINVAL; 1264fa6999e3SHarald Freudenberger } else { 1265fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 1266fa6999e3SHarald Freudenberger __func__, hdr->version); 1267fa6999e3SHarald Freudenberger return -EINVAL; 1268fa6999e3SHarald Freudenberger } 1269fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1270fa6999e3SHarald Freudenberger /* CCA ECC (private) key */ 1271fa6999e3SHarald Freudenberger if (keylen < sizeof(struct eccprivkeytoken)) 1272fa6999e3SHarald Freudenberger return -EINVAL; 1273fa6999e3SHarald Freudenberger if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) 1274fa6999e3SHarald Freudenberger return -EINVAL; 1275fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 1276f370f45cSHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, 1277f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 1278fa6999e3SHarald Freudenberger } else { 1279fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 1280fa6999e3SHarald Freudenberger __func__, hdr->type); 1281fa6999e3SHarald Freudenberger return -EINVAL; 1282fa6999e3SHarald Freudenberger } 1283fa6999e3SHarald Freudenberger 1284fa6999e3SHarald Freudenberger /* simple try all apqns from the list */ 1285fa6999e3SHarald Freudenberger for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 1286fa6999e3SHarald Freudenberger card = apqns[i].card; 1287fa6999e3SHarald Freudenberger dom = apqns[i].domain; 12882004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 12892004b57cSHarald Freudenberger (hdr->version == TOKVER_EP11_AES_WITH_HEADER || 12902004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && 12912004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) 1292fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1293d1fdfb0bSHolger Dengler protkey, protkeylen, 1294d1fdfb0bSHolger Dengler protkeytype); 12952004b57cSHarald Freudenberger else if (hdr->type == TOKTYPE_NON_CCA && 12962004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 12972004b57cSHarald Freudenberger is_ep11_keyblob(key)) 1298fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1299d1fdfb0bSHolger Dengler protkey, protkeylen, 1300d1fdfb0bSHolger Dengler protkeytype); 1301fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1302fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_AES) 1303fa6999e3SHarald Freudenberger rc = cca_sec2protkey(card, dom, key, protkey, 1304fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1305fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1306fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) 1307fa6999e3SHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, protkey, 1308fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1309fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) 1310fa6999e3SHarald Freudenberger rc = cca_ecc2protkey(card, dom, key, protkey, 1311fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1312fa6999e3SHarald Freudenberger else 1313fa6999e3SHarald Freudenberger return -EINVAL; 1314fa6999e3SHarald Freudenberger } 1315fa6999e3SHarald Freudenberger 1316fa6999e3SHarald Freudenberger return rc; 1317fa6999e3SHarald Freudenberger } 1318fa6999e3SHarald Freudenberger 1319fb1136d6SIngo Franzki /* 1320e80d4af0SHarald Freudenberger * File io functions 1321e80d4af0SHarald Freudenberger */ 1322e80d4af0SHarald Freudenberger 1323f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen) 1324f2bbc96eSHarald Freudenberger { 13259e436c19SHarald Freudenberger if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE) 1326f2bbc96eSHarald Freudenberger return ERR_PTR(-EINVAL); 1327f2bbc96eSHarald Freudenberger 13288b57e7c8SMarkus Elfring return memdup_user(ukey, keylen); 1329f2bbc96eSHarald Freudenberger } 1330f2bbc96eSHarald Freudenberger 1331f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 1332f2bbc96eSHarald Freudenberger { 13338b57e7c8SMarkus Elfring if (!uapqns || nr_apqns == 0) 13348b57e7c8SMarkus Elfring return NULL; 1335f2bbc96eSHarald Freudenberger 13368b57e7c8SMarkus Elfring return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); 1337f2bbc96eSHarald Freudenberger } 1338f2bbc96eSHarald Freudenberger 1339e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 1340e80d4af0SHarald Freudenberger unsigned long arg) 1341e80d4af0SHarald Freudenberger { 1342e80d4af0SHarald Freudenberger int rc; 1343e80d4af0SHarald Freudenberger 1344e80d4af0SHarald Freudenberger switch (cmd) { 1345e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1346e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *)arg; 1347e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1348e80d4af0SHarald Freudenberger 1349e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1350e80d4af0SHarald Freudenberger return -EFAULT; 1351efc598e6SHarald Freudenberger rc = cca_genseckey(kgs.cardnr, kgs.domain, 1352efc598e6SHarald Freudenberger kgs.keytype, kgs.seckey.seckey); 1353efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 1354e80d4af0SHarald Freudenberger if (rc) 1355e80d4af0SHarald Freudenberger break; 1356e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1357e80d4af0SHarald Freudenberger return -EFAULT; 1358e80d4af0SHarald Freudenberger break; 1359e80d4af0SHarald Freudenberger } 1360e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1361e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *)arg; 1362e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1363e80d4af0SHarald Freudenberger 1364e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1365e80d4af0SHarald Freudenberger return -EFAULT; 1366efc598e6SHarald Freudenberger rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1367efc598e6SHarald Freudenberger kcs.clrkey.clrkey, kcs.seckey.seckey); 1368efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 1369e80d4af0SHarald Freudenberger if (rc) 1370e80d4af0SHarald Freudenberger break; 1371e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1372e80d4af0SHarald Freudenberger return -EFAULT; 1373e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1374e80d4af0SHarald Freudenberger break; 1375e80d4af0SHarald Freudenberger } 1376e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1377e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *)arg; 1378e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1379e80d4af0SHarald Freudenberger 1380e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1381e80d4af0SHarald Freudenberger return -EFAULT; 1382f370f45cSHarald Freudenberger ksp.protkey.len = sizeof(ksp.protkey.protkey); 1383efc598e6SHarald Freudenberger rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 1384efc598e6SHarald Freudenberger ksp.seckey.seckey, ksp.protkey.protkey, 1385aab73d27SHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1386efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 1387e80d4af0SHarald Freudenberger if (rc) 1388e80d4af0SHarald Freudenberger break; 1389e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1390e80d4af0SHarald Freudenberger return -EFAULT; 1391e80d4af0SHarald Freudenberger break; 1392e80d4af0SHarald Freudenberger } 1393e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1394e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *)arg; 1395e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1396e80d4af0SHarald Freudenberger 1397e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1398e80d4af0SHarald Freudenberger return -EFAULT; 1399f370f45cSHarald Freudenberger kcp.protkey.len = sizeof(kcp.protkey.protkey); 1400f370f45cSHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey, 1401f370f45cSHarald Freudenberger kcp.protkey.protkey, 1402f370f45cSHarald Freudenberger &kcp.protkey.len, &kcp.protkey.type); 1403ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1404e80d4af0SHarald Freudenberger if (rc) 1405e80d4af0SHarald Freudenberger break; 1406e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1407e80d4af0SHarald Freudenberger return -EFAULT; 1408e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1409e80d4af0SHarald Freudenberger break; 1410e80d4af0SHarald Freudenberger } 1411e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1412e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *)arg; 1413e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1414e80d4af0SHarald Freudenberger 1415e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1416e80d4af0SHarald Freudenberger return -EFAULT; 1417efc598e6SHarald Freudenberger rc = cca_findcard(kfc.seckey.seckey, 1418e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1419efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 1420efc598e6SHarald Freudenberger if (rc < 0) 1421e80d4af0SHarald Freudenberger break; 1422e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1423e80d4af0SHarald Freudenberger return -EFAULT; 1424e80d4af0SHarald Freudenberger break; 1425e80d4af0SHarald Freudenberger } 1426e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1427e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *)arg; 1428e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1429e80d4af0SHarald Freudenberger 1430e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1431e80d4af0SHarald Freudenberger return -EFAULT; 1432f370f45cSHarald Freudenberger ksp.protkey.len = sizeof(ksp.protkey.protkey); 1433f370f45cSHarald Freudenberger rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey, 1434f370f45cSHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1435ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1436e80d4af0SHarald Freudenberger if (rc) 1437e80d4af0SHarald Freudenberger break; 1438e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1439e80d4af0SHarald Freudenberger return -EFAULT; 1440e80d4af0SHarald Freudenberger break; 1441e80d4af0SHarald Freudenberger } 1442e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1443e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *)arg; 1444e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1445e61a6134SHarald Freudenberger 1446e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1447e61a6134SHarald Freudenberger return -EFAULT; 1448e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1449e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1450ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1451e61a6134SHarald Freudenberger if (rc) 1452e61a6134SHarald Freudenberger break; 1453e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1454e61a6134SHarald Freudenberger return -EFAULT; 1455e61a6134SHarald Freudenberger break; 1456e61a6134SHarald Freudenberger } 1457a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1458a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *)arg; 1459a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1460a45a5c7dSIngo Franzki 1461a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1462a45a5c7dSIngo Franzki return -EFAULT; 1463f370f45cSHarald Freudenberger kgp.protkey.len = sizeof(kgp.protkey.protkey); 1464f370f45cSHarald Freudenberger rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey, 1465f370f45cSHarald Freudenberger &kgp.protkey.len, &kgp.protkey.type); 1466a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1467a45a5c7dSIngo Franzki if (rc) 1468a45a5c7dSIngo Franzki break; 1469a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1470a45a5c7dSIngo Franzki return -EFAULT; 1471a45a5c7dSIngo Franzki break; 1472a45a5c7dSIngo Franzki } 1473cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 1474cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *)arg; 1475cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 1476cb26b9ffSIngo Franzki 1477cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 1478cb26b9ffSIngo Franzki return -EFAULT; 1479f370f45cSHarald Freudenberger rc = pkey_verifyprotkey(kvp.protkey.protkey, 1480f370f45cSHarald Freudenberger kvp.protkey.len, kvp.protkey.type); 1481cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 1482cb26b9ffSIngo Franzki break; 1483cb26b9ffSIngo Franzki } 1484fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 1485fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *)arg; 1486fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 1487183cb469SHarald Freudenberger u8 *kkey; 1488fb1136d6SIngo Franzki 1489fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 1490fb1136d6SIngo Franzki return -EFAULT; 1491f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1492f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1493f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1494f370f45cSHarald Freudenberger ktp.protkey.len = sizeof(ktp.protkey.protkey); 1495f370f45cSHarald Freudenberger rc = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey, 1496f370f45cSHarald Freudenberger &ktp.protkey.len, &ktp.protkey.type); 1497fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 1498844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1499fb1136d6SIngo Franzki kfree(kkey); 1500fb1136d6SIngo Franzki if (rc) 1501fb1136d6SIngo Franzki break; 1502fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 1503fb1136d6SIngo Franzki return -EFAULT; 1504fb1136d6SIngo Franzki break; 1505fb1136d6SIngo Franzki } 1506f2bbc96eSHarald Freudenberger case PKEY_GENSECK2: { 1507f2bbc96eSHarald Freudenberger struct pkey_genseck2 __user *ugs = (void __user *)arg; 150846a29b03SHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1509f2bbc96eSHarald Freudenberger struct pkey_genseck2 kgs; 1510f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1511f2bbc96eSHarald Freudenberger u8 *kkey; 1512f2bbc96eSHarald Freudenberger 1513f2bbc96eSHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1514f2bbc96eSHarald Freudenberger return -EFAULT; 1515f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 1516f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1517f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1518fb249ce7SHolger Dengler kkey = kzalloc(klen, GFP_KERNEL); 1519f2bbc96eSHarald Freudenberger if (!kkey) { 1520f2bbc96eSHarald Freudenberger kfree(apqns); 1521f2bbc96eSHarald Freudenberger return -ENOMEM; 1522f2bbc96eSHarald Freudenberger } 1523f2bbc96eSHarald Freudenberger rc = pkey_genseckey2(apqns, kgs.apqn_entries, 1524f2bbc96eSHarald Freudenberger kgs.type, kgs.size, kgs.keygenflags, 1525f2bbc96eSHarald Freudenberger kkey, &klen); 1526f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 1527f2bbc96eSHarald Freudenberger kfree(apqns); 1528f2bbc96eSHarald Freudenberger if (rc) { 1529f2bbc96eSHarald Freudenberger kfree(kkey); 1530f2bbc96eSHarald Freudenberger break; 1531f2bbc96eSHarald Freudenberger } 1532f2bbc96eSHarald Freudenberger if (kgs.key) { 1533f2bbc96eSHarald Freudenberger if (kgs.keylen < klen) { 1534f2bbc96eSHarald Freudenberger kfree(kkey); 1535f2bbc96eSHarald Freudenberger return -EINVAL; 1536f2bbc96eSHarald Freudenberger } 1537f2bbc96eSHarald Freudenberger if (copy_to_user(kgs.key, kkey, klen)) { 1538f2bbc96eSHarald Freudenberger kfree(kkey); 1539f2bbc96eSHarald Freudenberger return -EFAULT; 1540f2bbc96eSHarald Freudenberger } 1541f2bbc96eSHarald Freudenberger } 1542f2bbc96eSHarald Freudenberger kgs.keylen = klen; 1543f2bbc96eSHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1544f2bbc96eSHarald Freudenberger rc = -EFAULT; 1545f2bbc96eSHarald Freudenberger kfree(kkey); 1546f2bbc96eSHarald Freudenberger break; 1547f2bbc96eSHarald Freudenberger } 1548f2bbc96eSHarald Freudenberger case PKEY_CLR2SECK2: { 1549f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 __user *ucs = (void __user *)arg; 155046a29b03SHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1551f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 kcs; 1552f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1553f2bbc96eSHarald Freudenberger u8 *kkey; 1554f2bbc96eSHarald Freudenberger 1555f2bbc96eSHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1556f2bbc96eSHarald Freudenberger return -EFAULT; 1557f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 1558f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1559f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1560da2863f1SHolger Dengler kkey = kzalloc(klen, GFP_KERNEL); 1561f2bbc96eSHarald Freudenberger if (!kkey) { 1562f2bbc96eSHarald Freudenberger kfree(apqns); 1563f2bbc96eSHarald Freudenberger return -ENOMEM; 1564f2bbc96eSHarald Freudenberger } 1565f2bbc96eSHarald Freudenberger rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 1566f2bbc96eSHarald Freudenberger kcs.type, kcs.size, kcs.keygenflags, 1567f2bbc96eSHarald Freudenberger kcs.clrkey.clrkey, kkey, &klen); 1568f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 1569f2bbc96eSHarald Freudenberger kfree(apqns); 1570f2bbc96eSHarald Freudenberger if (rc) { 1571f2bbc96eSHarald Freudenberger kfree(kkey); 1572f2bbc96eSHarald Freudenberger break; 1573f2bbc96eSHarald Freudenberger } 1574f2bbc96eSHarald Freudenberger if (kcs.key) { 1575f2bbc96eSHarald Freudenberger if (kcs.keylen < klen) { 1576f2bbc96eSHarald Freudenberger kfree(kkey); 1577f2bbc96eSHarald Freudenberger return -EINVAL; 1578f2bbc96eSHarald Freudenberger } 1579f2bbc96eSHarald Freudenberger if (copy_to_user(kcs.key, kkey, klen)) { 1580f2bbc96eSHarald Freudenberger kfree(kkey); 1581f2bbc96eSHarald Freudenberger return -EFAULT; 1582f2bbc96eSHarald Freudenberger } 1583f2bbc96eSHarald Freudenberger } 1584f2bbc96eSHarald Freudenberger kcs.keylen = klen; 1585f2bbc96eSHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1586f2bbc96eSHarald Freudenberger rc = -EFAULT; 1587f2bbc96eSHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1588f2bbc96eSHarald Freudenberger kfree(kkey); 1589f2bbc96eSHarald Freudenberger break; 1590f2bbc96eSHarald Freudenberger } 1591f2bbc96eSHarald Freudenberger case PKEY_VERIFYKEY2: { 1592f2bbc96eSHarald Freudenberger struct pkey_verifykey2 __user *uvk = (void __user *)arg; 1593f2bbc96eSHarald Freudenberger struct pkey_verifykey2 kvk; 1594f2bbc96eSHarald Freudenberger u8 *kkey; 1595f2bbc96eSHarald Freudenberger 1596f2bbc96eSHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1597f2bbc96eSHarald Freudenberger return -EFAULT; 1598f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kvk.key, kvk.keylen); 1599f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1600f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1601f2bbc96eSHarald Freudenberger rc = pkey_verifykey2(kkey, kvk.keylen, 1602f2bbc96eSHarald Freudenberger &kvk.cardnr, &kvk.domain, 1603f2bbc96eSHarald Freudenberger &kvk.type, &kvk.size, &kvk.flags); 1604f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 1605f2bbc96eSHarald Freudenberger kfree(kkey); 1606f2bbc96eSHarald Freudenberger if (rc) 1607f2bbc96eSHarald Freudenberger break; 1608f2bbc96eSHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1609f2bbc96eSHarald Freudenberger return -EFAULT; 1610f2bbc96eSHarald Freudenberger break; 1611f2bbc96eSHarald Freudenberger } 1612f2bbc96eSHarald Freudenberger case PKEY_KBLOB2PROTK2: { 1613f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 __user *utp = (void __user *)arg; 1614f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 161546a29b03SHarald Freudenberger struct pkey_kblob2pkey2 ktp; 1616f2bbc96eSHarald Freudenberger u8 *kkey; 1617f2bbc96eSHarald Freudenberger 1618f2bbc96eSHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1619f2bbc96eSHarald Freudenberger return -EFAULT; 1620f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1621f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1622f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1623f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1624f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1625f2bbc96eSHarald Freudenberger kfree(apqns); 1626f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1627f2bbc96eSHarald Freudenberger } 1628f370f45cSHarald Freudenberger ktp.protkey.len = sizeof(ktp.protkey.protkey); 1629f2bbc96eSHarald Freudenberger rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 1630f370f45cSHarald Freudenberger kkey, ktp.keylen, 1631f370f45cSHarald Freudenberger ktp.protkey.protkey, &ktp.protkey.len, 1632f370f45cSHarald Freudenberger &ktp.protkey.type); 1633f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 1634f2bbc96eSHarald Freudenberger kfree(apqns); 1635844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1636f2bbc96eSHarald Freudenberger kfree(kkey); 1637f2bbc96eSHarald Freudenberger if (rc) 1638f2bbc96eSHarald Freudenberger break; 1639f2bbc96eSHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1640f2bbc96eSHarald Freudenberger return -EFAULT; 1641f2bbc96eSHarald Freudenberger break; 1642f2bbc96eSHarald Freudenberger } 1643f2bbc96eSHarald Freudenberger case PKEY_APQNS4K: { 1644f2bbc96eSHarald Freudenberger struct pkey_apqns4key __user *uak = (void __user *)arg; 1645f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 164646a29b03SHarald Freudenberger struct pkey_apqns4key kak; 1647f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1648f2bbc96eSHarald Freudenberger u8 *kkey; 1649f2bbc96eSHarald Freudenberger 1650f2bbc96eSHarald Freudenberger if (copy_from_user(&kak, uak, sizeof(kak))) 1651f2bbc96eSHarald Freudenberger return -EFAULT; 1652f2bbc96eSHarald Freudenberger nr_apqns = kak.apqn_entries; 1653f2bbc96eSHarald Freudenberger if (nr_apqns) { 1654f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1655f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1656f2bbc96eSHarald Freudenberger GFP_KERNEL); 1657f2bbc96eSHarald Freudenberger if (!apqns) 1658f2bbc96eSHarald Freudenberger return -ENOMEM; 1659f2bbc96eSHarald Freudenberger } 1660f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kak.key, kak.keylen); 1661f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1662f2bbc96eSHarald Freudenberger kfree(apqns); 1663f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1664f2bbc96eSHarald Freudenberger } 1665f2bbc96eSHarald Freudenberger rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 1666f2bbc96eSHarald Freudenberger apqns, &nr_apqns); 1667f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 1668f2bbc96eSHarald Freudenberger kfree(kkey); 1669f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1670f2bbc96eSHarald Freudenberger kfree(apqns); 1671f2bbc96eSHarald Freudenberger break; 1672f2bbc96eSHarald Freudenberger } 1673f2bbc96eSHarald Freudenberger if (!rc && kak.apqns) { 1674f2bbc96eSHarald Freudenberger if (nr_apqns > kak.apqn_entries) { 1675f2bbc96eSHarald Freudenberger kfree(apqns); 1676f2bbc96eSHarald Freudenberger return -EINVAL; 1677f2bbc96eSHarald Freudenberger } 1678f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1679f2bbc96eSHarald Freudenberger if (len) { 1680f2bbc96eSHarald Freudenberger if (copy_to_user(kak.apqns, apqns, len)) { 1681f2bbc96eSHarald Freudenberger kfree(apqns); 1682f2bbc96eSHarald Freudenberger return -EFAULT; 1683f2bbc96eSHarald Freudenberger } 1684f2bbc96eSHarald Freudenberger } 1685f2bbc96eSHarald Freudenberger } 1686f2bbc96eSHarald Freudenberger kak.apqn_entries = nr_apqns; 1687f2bbc96eSHarald Freudenberger if (copy_to_user(uak, &kak, sizeof(kak))) 1688f2bbc96eSHarald Freudenberger rc = -EFAULT; 1689f2bbc96eSHarald Freudenberger kfree(apqns); 1690f2bbc96eSHarald Freudenberger break; 1691f2bbc96eSHarald Freudenberger } 1692f2bbc96eSHarald Freudenberger case PKEY_APQNS4KT: { 1693f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype __user *uat = (void __user *)arg; 1694f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 169546a29b03SHarald Freudenberger struct pkey_apqns4keytype kat; 1696f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1697f2bbc96eSHarald Freudenberger 1698f2bbc96eSHarald Freudenberger if (copy_from_user(&kat, uat, sizeof(kat))) 1699f2bbc96eSHarald Freudenberger return -EFAULT; 1700f2bbc96eSHarald Freudenberger nr_apqns = kat.apqn_entries; 1701f2bbc96eSHarald Freudenberger if (nr_apqns) { 1702f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1703f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1704f2bbc96eSHarald Freudenberger GFP_KERNEL); 1705f2bbc96eSHarald Freudenberger if (!apqns) 1706f2bbc96eSHarald Freudenberger return -ENOMEM; 1707f2bbc96eSHarald Freudenberger } 1708f2bbc96eSHarald Freudenberger rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 1709f2bbc96eSHarald Freudenberger kat.flags, apqns, &nr_apqns); 1710f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 1711f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1712f2bbc96eSHarald Freudenberger kfree(apqns); 1713f2bbc96eSHarald Freudenberger break; 1714f2bbc96eSHarald Freudenberger } 1715f2bbc96eSHarald Freudenberger if (!rc && kat.apqns) { 1716f2bbc96eSHarald Freudenberger if (nr_apqns > kat.apqn_entries) { 1717f2bbc96eSHarald Freudenberger kfree(apqns); 1718f2bbc96eSHarald Freudenberger return -EINVAL; 1719f2bbc96eSHarald Freudenberger } 1720f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1721f2bbc96eSHarald Freudenberger if (len) { 1722f2bbc96eSHarald Freudenberger if (copy_to_user(kat.apqns, apqns, len)) { 1723f2bbc96eSHarald Freudenberger kfree(apqns); 1724f2bbc96eSHarald Freudenberger return -EFAULT; 1725f2bbc96eSHarald Freudenberger } 1726f2bbc96eSHarald Freudenberger } 1727f2bbc96eSHarald Freudenberger } 1728f2bbc96eSHarald Freudenberger kat.apqn_entries = nr_apqns; 1729f2bbc96eSHarald Freudenberger if (copy_to_user(uat, &kat, sizeof(kat))) 1730f2bbc96eSHarald Freudenberger rc = -EFAULT; 1731f2bbc96eSHarald Freudenberger kfree(apqns); 1732f2bbc96eSHarald Freudenberger break; 1733f2bbc96eSHarald Freudenberger } 1734fa6999e3SHarald Freudenberger case PKEY_KBLOB2PROTK3: { 1735fa6999e3SHarald Freudenberger struct pkey_kblob2pkey3 __user *utp = (void __user *)arg; 1736fa6999e3SHarald Freudenberger u32 protkeylen = PROTKEYBLOBBUFSIZE; 173746a29b03SHarald Freudenberger struct pkey_apqn *apqns = NULL; 173846a29b03SHarald Freudenberger struct pkey_kblob2pkey3 ktp; 1739fa6999e3SHarald Freudenberger u8 *kkey, *protkey; 1740fa6999e3SHarald Freudenberger 1741fa6999e3SHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1742fa6999e3SHarald Freudenberger return -EFAULT; 1743fa6999e3SHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1744fa6999e3SHarald Freudenberger if (IS_ERR(apqns)) 1745fa6999e3SHarald Freudenberger return PTR_ERR(apqns); 1746fa6999e3SHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1747fa6999e3SHarald Freudenberger if (IS_ERR(kkey)) { 1748fa6999e3SHarald Freudenberger kfree(apqns); 1749fa6999e3SHarald Freudenberger return PTR_ERR(kkey); 1750fa6999e3SHarald Freudenberger } 1751fa6999e3SHarald Freudenberger protkey = kmalloc(protkeylen, GFP_KERNEL); 1752fa6999e3SHarald Freudenberger if (!protkey) { 1753fa6999e3SHarald Freudenberger kfree(apqns); 1754fa6999e3SHarald Freudenberger kfree(kkey); 1755fa6999e3SHarald Freudenberger return -ENOMEM; 1756fa6999e3SHarald Freudenberger } 1757f370f45cSHarald Freudenberger rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, 1758f370f45cSHarald Freudenberger kkey, ktp.keylen, 1759f370f45cSHarald Freudenberger protkey, &protkeylen, &ktp.pkeytype); 1760fa6999e3SHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); 1761fa6999e3SHarald Freudenberger kfree(apqns); 1762844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1763fa6999e3SHarald Freudenberger kfree(kkey); 1764fa6999e3SHarald Freudenberger if (rc) { 1765fa6999e3SHarald Freudenberger kfree(protkey); 1766fa6999e3SHarald Freudenberger break; 1767fa6999e3SHarald Freudenberger } 1768fa6999e3SHarald Freudenberger if (ktp.pkey && ktp.pkeylen) { 1769fa6999e3SHarald Freudenberger if (protkeylen > ktp.pkeylen) { 1770fa6999e3SHarald Freudenberger kfree(protkey); 1771fa6999e3SHarald Freudenberger return -EINVAL; 1772fa6999e3SHarald Freudenberger } 1773fa6999e3SHarald Freudenberger if (copy_to_user(ktp.pkey, protkey, protkeylen)) { 1774fa6999e3SHarald Freudenberger kfree(protkey); 1775fa6999e3SHarald Freudenberger return -EFAULT; 1776fa6999e3SHarald Freudenberger } 1777fa6999e3SHarald Freudenberger } 1778fa6999e3SHarald Freudenberger kfree(protkey); 1779fa6999e3SHarald Freudenberger ktp.pkeylen = protkeylen; 1780fa6999e3SHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1781fa6999e3SHarald Freudenberger return -EFAULT; 1782fa6999e3SHarald Freudenberger break; 1783fa6999e3SHarald Freudenberger } 1784e80d4af0SHarald Freudenberger default: 1785e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1786e80d4af0SHarald Freudenberger return -ENOTTY; 1787e80d4af0SHarald Freudenberger } 1788e80d4af0SHarald Freudenberger 1789e80d4af0SHarald Freudenberger return rc; 1790e80d4af0SHarald Freudenberger } 1791e80d4af0SHarald Freudenberger 1792e80d4af0SHarald Freudenberger /* 1793e80d4af0SHarald Freudenberger * Sysfs and file io operations 1794e80d4af0SHarald Freudenberger */ 1795d632c047SIngo Franzki 1796d632c047SIngo Franzki /* 1797d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1798d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1799d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1800d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1801d632c047SIngo Franzki */ 1802d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1803d632c047SIngo Franzki loff_t off, size_t count) 1804d632c047SIngo Franzki { 1805d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1806d632c047SIngo Franzki struct pkey_protkey protkey; 1807d632c047SIngo Franzki int rc; 1808d632c047SIngo Franzki 1809d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1810d632c047SIngo Franzki return -EINVAL; 1811d632c047SIngo Franzki if (is_xts) 1812d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1813d632c047SIngo Franzki return -EINVAL; 1814d632c047SIngo Franzki 1815d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1816d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1817d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1818d632c047SIngo Franzki protkeytoken.keytype = keytype; 1819d632c047SIngo Franzki 1820f370f45cSHarald Freudenberger protkey.len = sizeof(protkey.protkey); 1821f370f45cSHarald Freudenberger rc = pkey_genprotkey(protkeytoken.keytype, 1822f370f45cSHarald Freudenberger protkey.protkey, &protkey.len, &protkey.type); 1823d632c047SIngo Franzki if (rc) 1824d632c047SIngo Franzki return rc; 1825d632c047SIngo Franzki 1826d632c047SIngo Franzki protkeytoken.len = protkey.len; 1827d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1828d632c047SIngo Franzki 1829d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1830d632c047SIngo Franzki 1831d632c047SIngo Franzki if (is_xts) { 1832f370f45cSHarald Freudenberger /* xts needs a second protected key, reuse protkey struct */ 1833f370f45cSHarald Freudenberger protkey.len = sizeof(protkey.protkey); 1834f370f45cSHarald Freudenberger rc = pkey_genprotkey(protkeytoken.keytype, 1835f370f45cSHarald Freudenberger protkey.protkey, &protkey.len, &protkey.type); 1836d632c047SIngo Franzki if (rc) 1837d632c047SIngo Franzki return rc; 1838d632c047SIngo Franzki 1839d632c047SIngo Franzki protkeytoken.len = protkey.len; 1840d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1841d632c047SIngo Franzki 1842d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1843d632c047SIngo Franzki sizeof(protkeytoken)); 1844d632c047SIngo Franzki 1845d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1846d632c047SIngo Franzki } 1847d632c047SIngo Franzki 1848d632c047SIngo Franzki return sizeof(protkeytoken); 1849d632c047SIngo Franzki } 1850d632c047SIngo Franzki 1851d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1852d632c047SIngo Franzki struct kobject *kobj, 1853d632c047SIngo Franzki struct bin_attribute *attr, 1854d632c047SIngo Franzki char *buf, loff_t off, 1855d632c047SIngo Franzki size_t count) 1856d632c047SIngo Franzki { 1857d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1858d632c047SIngo Franzki off, count); 1859d632c047SIngo Franzki } 1860d632c047SIngo Franzki 1861d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1862d632c047SIngo Franzki struct kobject *kobj, 1863d632c047SIngo Franzki struct bin_attribute *attr, 1864d632c047SIngo Franzki char *buf, loff_t off, 1865d632c047SIngo Franzki size_t count) 1866d632c047SIngo Franzki { 1867d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1868d632c047SIngo Franzki off, count); 1869d632c047SIngo Franzki } 1870d632c047SIngo Franzki 1871d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1872d632c047SIngo Franzki struct kobject *kobj, 1873d632c047SIngo Franzki struct bin_attribute *attr, 1874d632c047SIngo Franzki char *buf, loff_t off, 1875d632c047SIngo Franzki size_t count) 1876d632c047SIngo Franzki { 1877d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1878d632c047SIngo Franzki off, count); 1879d632c047SIngo Franzki } 1880d632c047SIngo Franzki 1881d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1882d632c047SIngo Franzki struct kobject *kobj, 1883d632c047SIngo Franzki struct bin_attribute *attr, 1884d632c047SIngo Franzki char *buf, loff_t off, 1885d632c047SIngo Franzki size_t count) 1886d632c047SIngo Franzki { 1887d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1888d632c047SIngo Franzki off, count); 1889d632c047SIngo Franzki } 1890d632c047SIngo Franzki 1891d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1892d632c047SIngo Franzki struct kobject *kobj, 1893d632c047SIngo Franzki struct bin_attribute *attr, 1894d632c047SIngo Franzki char *buf, loff_t off, 1895d632c047SIngo Franzki size_t count) 1896d632c047SIngo Franzki { 1897d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1898d632c047SIngo Franzki off, count); 1899d632c047SIngo Franzki } 1900d632c047SIngo Franzki 1901d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1902d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1903d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1904d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1905d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1906d632c047SIngo Franzki 1907d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1908d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1909d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1910d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1911d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1912d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1913d632c047SIngo Franzki NULL 1914d632c047SIngo Franzki }; 1915d632c047SIngo Franzki 1916d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1917d632c047SIngo Franzki .name = "protkey", 1918d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1919d632c047SIngo Franzki }; 1920d632c047SIngo Franzki 1921af504452SIngo Franzki /* 1922af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1923af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1924af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1925af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1926af504452SIngo Franzki */ 1927af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1928af504452SIngo Franzki loff_t off, size_t count) 1929af504452SIngo Franzki { 1930efc598e6SHarald Freudenberger struct pkey_seckey *seckey = (struct pkey_seckey *)buf; 193146a29b03SHarald Freudenberger int rc; 1932af504452SIngo Franzki 1933af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1934af504452SIngo Franzki return -EINVAL; 1935af504452SIngo Franzki if (is_xts) 1936af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1937af504452SIngo Franzki return -EINVAL; 1938af504452SIngo Franzki 1939efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1940af504452SIngo Franzki if (rc) 1941af504452SIngo Franzki return rc; 1942af504452SIngo Franzki 1943af504452SIngo Franzki if (is_xts) { 1944efc598e6SHarald Freudenberger seckey++; 1945efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1946af504452SIngo Franzki if (rc) 1947af504452SIngo Franzki return rc; 1948af504452SIngo Franzki 1949af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1950af504452SIngo Franzki } 1951af504452SIngo Franzki 1952af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1953af504452SIngo Franzki } 1954af504452SIngo Franzki 1955af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1956af504452SIngo Franzki struct kobject *kobj, 1957af504452SIngo Franzki struct bin_attribute *attr, 1958af504452SIngo Franzki char *buf, loff_t off, 1959af504452SIngo Franzki size_t count) 1960af504452SIngo Franzki { 1961af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1962af504452SIngo Franzki off, count); 1963af504452SIngo Franzki } 1964af504452SIngo Franzki 1965af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1966af504452SIngo Franzki struct kobject *kobj, 1967af504452SIngo Franzki struct bin_attribute *attr, 1968af504452SIngo Franzki char *buf, loff_t off, 1969af504452SIngo Franzki size_t count) 1970af504452SIngo Franzki { 1971af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1972af504452SIngo Franzki off, count); 1973af504452SIngo Franzki } 1974af504452SIngo Franzki 1975af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1976af504452SIngo Franzki struct kobject *kobj, 1977af504452SIngo Franzki struct bin_attribute *attr, 1978af504452SIngo Franzki char *buf, loff_t off, 1979af504452SIngo Franzki size_t count) 1980af504452SIngo Franzki { 1981af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1982af504452SIngo Franzki off, count); 1983af504452SIngo Franzki } 1984af504452SIngo Franzki 1985af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1986af504452SIngo Franzki struct kobject *kobj, 1987af504452SIngo Franzki struct bin_attribute *attr, 1988af504452SIngo Franzki char *buf, loff_t off, 1989af504452SIngo Franzki size_t count) 1990af504452SIngo Franzki { 1991af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1992af504452SIngo Franzki off, count); 1993af504452SIngo Franzki } 1994af504452SIngo Franzki 1995af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1996af504452SIngo Franzki struct kobject *kobj, 1997af504452SIngo Franzki struct bin_attribute *attr, 1998af504452SIngo Franzki char *buf, loff_t off, 1999af504452SIngo Franzki size_t count) 2000af504452SIngo Franzki { 2001af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 2002af504452SIngo Franzki off, count); 2003af504452SIngo Franzki } 2004af504452SIngo Franzki 2005af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 2006af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 2007af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 2008af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 2009af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 2010af504452SIngo Franzki 2011af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 2012af504452SIngo Franzki &bin_attr_ccadata_aes_128, 2013af504452SIngo Franzki &bin_attr_ccadata_aes_192, 2014af504452SIngo Franzki &bin_attr_ccadata_aes_256, 2015af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 2016af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 2017af504452SIngo Franzki NULL 2018af504452SIngo Franzki }; 2019af504452SIngo Franzki 2020af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 2021af504452SIngo Franzki .name = "ccadata", 2022af504452SIngo Franzki .bin_attrs = ccadata_attrs, 2023af504452SIngo Franzki }; 2024af504452SIngo Franzki 2025f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) 2026f71fee27SIngo Franzki 2027f71fee27SIngo Franzki /* 2028f71fee27SIngo Franzki * Sysfs attribute read function for all secure key ccacipher binary attributes. 2029f71fee27SIngo Franzki * The implementation can not deal with partial reads, because a new random 2030f71fee27SIngo Franzki * secure key blob is generated with each read. In case of partial reads 2031f71fee27SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 2032f71fee27SIngo Franzki */ 2033f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, 2034f71fee27SIngo Franzki bool is_xts, char *buf, loff_t off, 2035f71fee27SIngo Franzki size_t count) 2036f71fee27SIngo Franzki { 203755d0a513SHarald Freudenberger size_t keysize = CCACIPHERTOKENSIZE; 203846a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 203946a29b03SHarald Freudenberger int i, rc, card, dom; 2040f71fee27SIngo Franzki 2041f71fee27SIngo Franzki if (off != 0 || count < CCACIPHERTOKENSIZE) 2042f71fee27SIngo Franzki return -EINVAL; 2043f71fee27SIngo Franzki if (is_xts) 2044f71fee27SIngo Franzki if (count < 2 * CCACIPHERTOKENSIZE) 2045f71fee27SIngo Franzki return -EINVAL; 2046f71fee27SIngo Franzki 204755d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 204855d0a513SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 204932ca04bbSHarald Freudenberger ZCRYPT_CEX6, 0, 0, 0, 0); 2050f71fee27SIngo Franzki if (rc) 2051f71fee27SIngo Franzki return rc; 205255d0a513SHarald Freudenberger 205355d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 205455d0a513SHarald Freudenberger 205555d0a513SHarald Freudenberger /* simple try all apqns from the list */ 205655d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 205755d0a513SHarald Freudenberger card = apqns[i] >> 16; 205855d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 205955d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 206055d0a513SHarald Freudenberger if (rc == 0) 206155d0a513SHarald Freudenberger break; 206255d0a513SHarald Freudenberger } 206355d0a513SHarald Freudenberger if (rc) 206455d0a513SHarald Freudenberger return rc; 2065f71fee27SIngo Franzki 2066f71fee27SIngo Franzki if (is_xts) { 2067f71fee27SIngo Franzki keysize = CCACIPHERTOKENSIZE; 206855d0a513SHarald Freudenberger buf += CCACIPHERTOKENSIZE; 206955d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 207055d0a513SHarald Freudenberger if (rc == 0) 2071f71fee27SIngo Franzki return 2 * CCACIPHERTOKENSIZE; 2072f71fee27SIngo Franzki } 2073f71fee27SIngo Franzki 2074f71fee27SIngo Franzki return CCACIPHERTOKENSIZE; 2075f71fee27SIngo Franzki } 2076f71fee27SIngo Franzki 2077f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp, 2078f71fee27SIngo Franzki struct kobject *kobj, 2079f71fee27SIngo Franzki struct bin_attribute *attr, 2080f71fee27SIngo Franzki char *buf, loff_t off, 2081f71fee27SIngo Franzki size_t count) 2082f71fee27SIngo Franzki { 2083f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 2084f71fee27SIngo Franzki off, count); 2085f71fee27SIngo Franzki } 2086f71fee27SIngo Franzki 2087f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp, 2088f71fee27SIngo Franzki struct kobject *kobj, 2089f71fee27SIngo Franzki struct bin_attribute *attr, 2090f71fee27SIngo Franzki char *buf, loff_t off, 2091f71fee27SIngo Franzki size_t count) 2092f71fee27SIngo Franzki { 2093f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 2094f71fee27SIngo Franzki off, count); 2095f71fee27SIngo Franzki } 2096f71fee27SIngo Franzki 2097f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp, 2098f71fee27SIngo Franzki struct kobject *kobj, 2099f71fee27SIngo Franzki struct bin_attribute *attr, 2100f71fee27SIngo Franzki char *buf, loff_t off, 2101f71fee27SIngo Franzki size_t count) 2102f71fee27SIngo Franzki { 2103f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 2104f71fee27SIngo Franzki off, count); 2105f71fee27SIngo Franzki } 2106f71fee27SIngo Franzki 2107f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp, 2108f71fee27SIngo Franzki struct kobject *kobj, 2109f71fee27SIngo Franzki struct bin_attribute *attr, 2110f71fee27SIngo Franzki char *buf, loff_t off, 2111f71fee27SIngo Franzki size_t count) 2112f71fee27SIngo Franzki { 2113f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 2114f71fee27SIngo Franzki off, count); 2115f71fee27SIngo Franzki } 2116f71fee27SIngo Franzki 2117f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp, 2118f71fee27SIngo Franzki struct kobject *kobj, 2119f71fee27SIngo Franzki struct bin_attribute *attr, 2120f71fee27SIngo Franzki char *buf, loff_t off, 2121f71fee27SIngo Franzki size_t count) 2122f71fee27SIngo Franzki { 2123f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 2124f71fee27SIngo Franzki off, count); 2125f71fee27SIngo Franzki } 2126f71fee27SIngo Franzki 2127f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); 2128f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); 2129f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); 2130f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); 2131f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); 2132f71fee27SIngo Franzki 2133f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = { 2134f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128, 2135f71fee27SIngo Franzki &bin_attr_ccacipher_aes_192, 2136f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256, 2137f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128_xts, 2138f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256_xts, 2139f71fee27SIngo Franzki NULL 2140f71fee27SIngo Franzki }; 2141f71fee27SIngo Franzki 2142f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = { 2143f71fee27SIngo Franzki .name = "ccacipher", 2144f71fee27SIngo Franzki .bin_attrs = ccacipher_attrs, 2145f71fee27SIngo Franzki }; 2146f71fee27SIngo Franzki 214755d0a513SHarald Freudenberger /* 214855d0a513SHarald Freudenberger * Sysfs attribute read function for all ep11 aes key binary attributes. 214955d0a513SHarald Freudenberger * The implementation can not deal with partial reads, because a new random 215055d0a513SHarald Freudenberger * secure key blob is generated with each read. In case of partial reads 215155d0a513SHarald Freudenberger * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 215255d0a513SHarald Freudenberger * This function and the sysfs attributes using it provide EP11 key blobs 215355d0a513SHarald Freudenberger * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently 2154b9352e4bSHolger Dengler * 336 bytes. 215555d0a513SHarald Freudenberger */ 215655d0a513SHarald Freudenberger static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, 215755d0a513SHarald Freudenberger bool is_xts, char *buf, loff_t off, 215855d0a513SHarald Freudenberger size_t count) 215955d0a513SHarald Freudenberger { 216055d0a513SHarald Freudenberger size_t keysize = MAXEP11AESKEYBLOBSIZE; 216146a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 216246a29b03SHarald Freudenberger int i, rc, card, dom; 216355d0a513SHarald Freudenberger 216455d0a513SHarald Freudenberger if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) 216555d0a513SHarald Freudenberger return -EINVAL; 216655d0a513SHarald Freudenberger if (is_xts) 216755d0a513SHarald Freudenberger if (count < 2 * MAXEP11AESKEYBLOBSIZE) 216855d0a513SHarald Freudenberger return -EINVAL; 216955d0a513SHarald Freudenberger 217055d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 217155d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 2172*386cb81eSHolger Dengler ZCRYPT_CEX7, 2173*386cb81eSHolger Dengler ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, 2174*386cb81eSHolger Dengler NULL); 217555d0a513SHarald Freudenberger if (rc) 217655d0a513SHarald Freudenberger return rc; 217755d0a513SHarald Freudenberger 217855d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 217955d0a513SHarald Freudenberger 218055d0a513SHarald Freudenberger /* simple try all apqns from the list */ 218155d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 218255d0a513SHarald Freudenberger card = apqns[i] >> 16; 218355d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 2184fb249ce7SHolger Dengler rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize, 2185b9352e4bSHolger Dengler PKEY_TYPE_EP11_AES); 218655d0a513SHarald Freudenberger if (rc == 0) 218755d0a513SHarald Freudenberger break; 218855d0a513SHarald Freudenberger } 218955d0a513SHarald Freudenberger if (rc) 219055d0a513SHarald Freudenberger return rc; 219155d0a513SHarald Freudenberger 219255d0a513SHarald Freudenberger if (is_xts) { 219355d0a513SHarald Freudenberger keysize = MAXEP11AESKEYBLOBSIZE; 219455d0a513SHarald Freudenberger buf += MAXEP11AESKEYBLOBSIZE; 2195fb249ce7SHolger Dengler rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize, 2196b9352e4bSHolger Dengler PKEY_TYPE_EP11_AES); 219755d0a513SHarald Freudenberger if (rc == 0) 219855d0a513SHarald Freudenberger return 2 * MAXEP11AESKEYBLOBSIZE; 219955d0a513SHarald Freudenberger } 220055d0a513SHarald Freudenberger 220155d0a513SHarald Freudenberger return MAXEP11AESKEYBLOBSIZE; 220255d0a513SHarald Freudenberger } 220355d0a513SHarald Freudenberger 220455d0a513SHarald Freudenberger static ssize_t ep11_aes_128_read(struct file *filp, 220555d0a513SHarald Freudenberger struct kobject *kobj, 220655d0a513SHarald Freudenberger struct bin_attribute *attr, 220755d0a513SHarald Freudenberger char *buf, loff_t off, 220855d0a513SHarald Freudenberger size_t count) 220955d0a513SHarald Freudenberger { 221055d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 221155d0a513SHarald Freudenberger off, count); 221255d0a513SHarald Freudenberger } 221355d0a513SHarald Freudenberger 221455d0a513SHarald Freudenberger static ssize_t ep11_aes_192_read(struct file *filp, 221555d0a513SHarald Freudenberger struct kobject *kobj, 221655d0a513SHarald Freudenberger struct bin_attribute *attr, 221755d0a513SHarald Freudenberger char *buf, loff_t off, 221855d0a513SHarald Freudenberger size_t count) 221955d0a513SHarald Freudenberger { 222055d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 222155d0a513SHarald Freudenberger off, count); 222255d0a513SHarald Freudenberger } 222355d0a513SHarald Freudenberger 222455d0a513SHarald Freudenberger static ssize_t ep11_aes_256_read(struct file *filp, 222555d0a513SHarald Freudenberger struct kobject *kobj, 222655d0a513SHarald Freudenberger struct bin_attribute *attr, 222755d0a513SHarald Freudenberger char *buf, loff_t off, 222855d0a513SHarald Freudenberger size_t count) 222955d0a513SHarald Freudenberger { 223055d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 223155d0a513SHarald Freudenberger off, count); 223255d0a513SHarald Freudenberger } 223355d0a513SHarald Freudenberger 223455d0a513SHarald Freudenberger static ssize_t ep11_aes_128_xts_read(struct file *filp, 223555d0a513SHarald Freudenberger struct kobject *kobj, 223655d0a513SHarald Freudenberger struct bin_attribute *attr, 223755d0a513SHarald Freudenberger char *buf, loff_t off, 223855d0a513SHarald Freudenberger size_t count) 223955d0a513SHarald Freudenberger { 224055d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 224155d0a513SHarald Freudenberger off, count); 224255d0a513SHarald Freudenberger } 224355d0a513SHarald Freudenberger 224455d0a513SHarald Freudenberger static ssize_t ep11_aes_256_xts_read(struct file *filp, 224555d0a513SHarald Freudenberger struct kobject *kobj, 224655d0a513SHarald Freudenberger struct bin_attribute *attr, 224755d0a513SHarald Freudenberger char *buf, loff_t off, 224855d0a513SHarald Freudenberger size_t count) 224955d0a513SHarald Freudenberger { 225055d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 225155d0a513SHarald Freudenberger off, count); 225255d0a513SHarald Freudenberger } 225355d0a513SHarald Freudenberger 225455d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE); 225555d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE); 225655d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE); 225755d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE); 225855d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE); 225955d0a513SHarald Freudenberger 226055d0a513SHarald Freudenberger static struct bin_attribute *ep11_attrs[] = { 226155d0a513SHarald Freudenberger &bin_attr_ep11_aes_128, 226255d0a513SHarald Freudenberger &bin_attr_ep11_aes_192, 226355d0a513SHarald Freudenberger &bin_attr_ep11_aes_256, 226455d0a513SHarald Freudenberger &bin_attr_ep11_aes_128_xts, 226555d0a513SHarald Freudenberger &bin_attr_ep11_aes_256_xts, 226655d0a513SHarald Freudenberger NULL 226755d0a513SHarald Freudenberger }; 226855d0a513SHarald Freudenberger 226955d0a513SHarald Freudenberger static struct attribute_group ep11_attr_group = { 227055d0a513SHarald Freudenberger .name = "ep11", 227155d0a513SHarald Freudenberger .bin_attrs = ep11_attrs, 227255d0a513SHarald Freudenberger }; 227355d0a513SHarald Freudenberger 2274d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 2275d632c047SIngo Franzki &protkey_attr_group, 2276af504452SIngo Franzki &ccadata_attr_group, 2277f71fee27SIngo Franzki &ccacipher_attr_group, 227855d0a513SHarald Freudenberger &ep11_attr_group, 2279d632c047SIngo Franzki NULL, 2280d632c047SIngo Franzki }; 2281d632c047SIngo Franzki 2282e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 2283e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 2284e80d4af0SHarald Freudenberger .open = nonseekable_open, 2285e80d4af0SHarald Freudenberger .llseek = no_llseek, 2286e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 2287e80d4af0SHarald Freudenberger }; 2288e80d4af0SHarald Freudenberger 2289e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 2290e80d4af0SHarald Freudenberger .name = "pkey", 2291e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 2292e80d4af0SHarald Freudenberger .mode = 0666, 2293e80d4af0SHarald Freudenberger .fops = &pkey_fops, 2294d632c047SIngo Franzki .groups = pkey_attr_groups, 2295e80d4af0SHarald Freudenberger }; 2296e80d4af0SHarald Freudenberger 2297e80d4af0SHarald Freudenberger /* 2298e80d4af0SHarald Freudenberger * Module init 2299e80d4af0SHarald Freudenberger */ 2300cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 2301e80d4af0SHarald Freudenberger { 23025b35047eSHarald Freudenberger cpacf_mask_t func_mask; 2303e80d4af0SHarald Freudenberger 2304f822ad2cSHarald Freudenberger /* 2305f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 2306f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 2307f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 2308f822ad2cSHarald Freudenberger * are able to work with protected keys. 2309f822ad2cSHarald Freudenberger */ 23105b35047eSHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &func_mask)) 231158443b67SDavid Hildenbrand return -ENODEV; 2312e80d4af0SHarald Freudenberger 2313cb26b9ffSIngo Franzki /* check for kmc instructions available */ 23145b35047eSHarald Freudenberger if (!cpacf_query(CPACF_KMC, &func_mask)) 231558443b67SDavid Hildenbrand return -ENODEV; 23165b35047eSHarald Freudenberger if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) || 23175b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) || 23185b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256)) 231958443b67SDavid Hildenbrand return -ENODEV; 2320cb26b9ffSIngo Franzki 2321e80d4af0SHarald Freudenberger pkey_debug_init(); 2322e80d4af0SHarald Freudenberger 2323e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 2324e80d4af0SHarald Freudenberger } 2325e80d4af0SHarald Freudenberger 2326e80d4af0SHarald Freudenberger /* 2327e80d4af0SHarald Freudenberger * Module exit 2328e80d4af0SHarald Freudenberger */ 2329e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 2330e80d4af0SHarald Freudenberger { 2331e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 2332e80d4af0SHarald Freudenberger pkey_debug_exit(); 2333e80d4af0SHarald Freudenberger } 2334e80d4af0SHarald Freudenberger 23350a5f9b38SHeiko Carstens module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init); 2336e80d4af0SHarald Freudenberger module_exit(pkey_exit); 2337