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, 26655d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 26755d0a513SHarald Freudenberger if (rc) 26855d0a513SHarald Freudenberger goto out; 26955d0a513SHarald Freudenberger 27055d0a513SHarald Freudenberger /* go through the list of apqns and try to bild an ep11 key */ 27155d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 27255d0a513SHarald Freudenberger card = apqns[i] >> 16; 27355d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 27455d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, clrkeylen * 8, 27555d0a513SHarald Freudenberger 0, clrkey, keybuf, keybuflen); 27655d0a513SHarald Freudenberger if (rc == 0) 27755d0a513SHarald Freudenberger break; 27855d0a513SHarald Freudenberger } 27955d0a513SHarald Freudenberger 28055d0a513SHarald Freudenberger out: 28155d0a513SHarald Freudenberger kfree(apqns); 28255d0a513SHarald Freudenberger if (rc) 28355d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 28455d0a513SHarald Freudenberger return rc; 28555d0a513SHarald Freudenberger } 28655d0a513SHarald Freudenberger 28755d0a513SHarald Freudenberger /* 28855d0a513SHarald Freudenberger * Find card and transform EP11 secure key into protected key. 28955d0a513SHarald Freudenberger */ 290f370f45cSHarald Freudenberger static int pkey_ep11key2pkey(const u8 *key, u8 *protkey, 291f370f45cSHarald Freudenberger u32 *protkeylen, u32 *protkeytype) 29255d0a513SHarald Freudenberger { 29355d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 29446a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 29546a29b03SHarald Freudenberger u16 card, dom; 29646a29b03SHarald Freudenberger int i, rc; 29755d0a513SHarald Freudenberger 29843cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 29943cb5a7cSHarald Freudenberger 30055d0a513SHarald Freudenberger /* build a list of apqns suitable for this key */ 30155d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 30255d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 30355d0a513SHarald Freudenberger if (rc) 30455d0a513SHarald Freudenberger goto out; 30555d0a513SHarald Freudenberger 30655d0a513SHarald Freudenberger /* go through the list of apqns and try to derive an pkey */ 30755d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 30855d0a513SHarald Freudenberger card = apqns[i] >> 16; 30955d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 310fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 311f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 31255d0a513SHarald Freudenberger if (rc == 0) 31355d0a513SHarald Freudenberger break; 31455d0a513SHarald Freudenberger } 31555d0a513SHarald Freudenberger 31655d0a513SHarald Freudenberger out: 31755d0a513SHarald Freudenberger kfree(apqns); 31855d0a513SHarald Freudenberger if (rc) 31955d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 32055d0a513SHarald Freudenberger return rc; 32155d0a513SHarald Freudenberger } 32255d0a513SHarald Freudenberger 32355d0a513SHarald Freudenberger /* 324e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 325e61a6134SHarald Freudenberger */ 326183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey, 327e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 328e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 329e61a6134SHarald Freudenberger { 330e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)seckey; 331e61a6134SHarald Freudenberger u16 cardnr, domain; 332e61a6134SHarald Freudenberger int rc; 333e61a6134SHarald Freudenberger 334e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 335efc598e6SHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *)seckey, 0); 336e61a6134SHarald Freudenberger if (rc) 337e61a6134SHarald Freudenberger goto out; 338e61a6134SHarald Freudenberger if (pattributes) 339e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 340e61a6134SHarald Freudenberger if (pkeysize) 341e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 342e61a6134SHarald Freudenberger 343e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 344efc598e6SHarald Freudenberger rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); 345efc598e6SHarald Freudenberger if (rc < 0) 346e61a6134SHarald Freudenberger goto out; 347e61a6134SHarald Freudenberger 348efc598e6SHarald Freudenberger if (rc > 0) { 349efc598e6SHarald Freudenberger /* key mkvp matches to old master key mkvp */ 350ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 351e61a6134SHarald Freudenberger if (pattributes) 352e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 353efc598e6SHarald Freudenberger rc = 0; 354e61a6134SHarald Freudenberger } 355e61a6134SHarald Freudenberger 356e61a6134SHarald Freudenberger if (pcardnr) 357e61a6134SHarald Freudenberger *pcardnr = cardnr; 358e61a6134SHarald Freudenberger if (pdomain) 359e61a6134SHarald Freudenberger *pdomain = domain; 360e61a6134SHarald Freudenberger 361e61a6134SHarald Freudenberger out: 362ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 363e61a6134SHarald Freudenberger return rc; 364e61a6134SHarald Freudenberger } 365e61a6134SHarald Freudenberger 366e61a6134SHarald Freudenberger /* 367a45a5c7dSIngo Franzki * Generate a random protected key 368a45a5c7dSIngo Franzki */ 369f370f45cSHarald Freudenberger static int pkey_genprotkey(u32 keytype, u8 *protkey, 370f370f45cSHarald Freudenberger u32 *protkeylen, u32 *protkeytype) 371a45a5c7dSIngo Franzki { 372f370f45cSHarald Freudenberger u8 clrkey[32]; 373a45a5c7dSIngo Franzki int keysize; 374a45a5c7dSIngo Franzki int rc; 375a45a5c7dSIngo Franzki 3769e436c19SHarald Freudenberger keysize = pkey_keytype_aes_to_size(keytype); 3779e436c19SHarald Freudenberger if (!keysize) { 378a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 379a45a5c7dSIngo Franzki keytype); 380a45a5c7dSIngo Franzki return -EINVAL; 381a45a5c7dSIngo Franzki } 382a45a5c7dSIngo Franzki 383a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 384f370f45cSHarald Freudenberger get_random_bytes(clrkey, keysize); 385a45a5c7dSIngo Franzki 386a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 387f370f45cSHarald Freudenberger rc = pkey_clr2protkey(keytype, clrkey, 388f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 389a45a5c7dSIngo Franzki if (rc) 390a45a5c7dSIngo Franzki return rc; 391a45a5c7dSIngo Franzki 392a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 393f370f45cSHarald Freudenberger get_random_bytes(protkey, keysize); 394a45a5c7dSIngo Franzki 395a45a5c7dSIngo Franzki return 0; 396a45a5c7dSIngo Franzki } 397a45a5c7dSIngo Franzki 398a45a5c7dSIngo Franzki /* 399cb26b9ffSIngo Franzki * Verify if a protected key is still valid 400cb26b9ffSIngo Franzki */ 401f370f45cSHarald Freudenberger static int pkey_verifyprotkey(const u8 *protkey, u32 protkeylen, 402f370f45cSHarald Freudenberger u32 protkeytype) 403cb26b9ffSIngo Franzki { 404cb26b9ffSIngo Franzki struct { 405cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 406cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 407cb26b9ffSIngo Franzki } param; 408cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 409cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 410f370f45cSHarald Freudenberger unsigned int k, pkeylen; 41146a29b03SHarald Freudenberger unsigned long fc; 412cb26b9ffSIngo Franzki 413f370f45cSHarald Freudenberger switch (protkeytype) { 414cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 415f370f45cSHarald Freudenberger pkeylen = 16 + AES_WK_VP_SIZE; 416cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 417cb26b9ffSIngo Franzki break; 418cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 419f370f45cSHarald Freudenberger pkeylen = 24 + AES_WK_VP_SIZE; 420cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 421cb26b9ffSIngo Franzki break; 422cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 423f370f45cSHarald Freudenberger pkeylen = 32 + AES_WK_VP_SIZE; 424cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 425cb26b9ffSIngo Franzki break; 426cb26b9ffSIngo Franzki default: 427f370f45cSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", __func__, 428f370f45cSHarald Freudenberger protkeytype); 429f370f45cSHarald Freudenberger return -EINVAL; 430f370f45cSHarald Freudenberger } 431f370f45cSHarald Freudenberger if (protkeylen != pkeylen) { 432f370f45cSHarald Freudenberger DEBUG_ERR("%s invalid protected key size %u for keytype %u\n", 433f370f45cSHarald Freudenberger __func__, protkeylen, protkeytype); 434cb26b9ffSIngo Franzki return -EINVAL; 435cb26b9ffSIngo Franzki } 436cb26b9ffSIngo Franzki 437cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 438cb26b9ffSIngo Franzki 439cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 440f370f45cSHarald Freudenberger memcpy(param.key, protkey, protkeylen); 441cb26b9ffSIngo Franzki 442cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 443cb26b9ffSIngo Franzki sizeof(null_msg)); 444cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 445cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 446cb26b9ffSIngo Franzki return -EKEYREJECTED; 447cb26b9ffSIngo Franzki } 448cb26b9ffSIngo Franzki 449cb26b9ffSIngo Franzki return 0; 450cb26b9ffSIngo Franzki } 451cb26b9ffSIngo Franzki 4529e436c19SHarald Freudenberger /* Helper for pkey_nonccatok2pkey, handles aes clear key token */ 4539e436c19SHarald Freudenberger static int nonccatokaes2pkey(const struct clearkeytoken *t, 4549e436c19SHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 4559e436c19SHarald Freudenberger { 4569e436c19SHarald Freudenberger size_t tmpbuflen = max_t(size_t, SECKEYBLOBSIZE, MAXEP11AESKEYBLOBSIZE); 4579e436c19SHarald Freudenberger u8 *tmpbuf = NULL; 4589e436c19SHarald Freudenberger u32 keysize; 4599e436c19SHarald Freudenberger int rc; 4609e436c19SHarald Freudenberger 4619e436c19SHarald Freudenberger keysize = pkey_keytype_aes_to_size(t->keytype); 4629e436c19SHarald Freudenberger if (!keysize) { 4639e436c19SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", 4649e436c19SHarald Freudenberger __func__, t->keytype); 4659e436c19SHarald Freudenberger return -EINVAL; 4669e436c19SHarald Freudenberger } 4679e436c19SHarald Freudenberger if (t->len != keysize) { 4689e436c19SHarald Freudenberger DEBUG_ERR("%s non clear key aes token: invalid key len %u\n", 4699e436c19SHarald Freudenberger __func__, t->len); 4709e436c19SHarald Freudenberger return -EINVAL; 4719e436c19SHarald Freudenberger } 4729e436c19SHarald Freudenberger 4739e436c19SHarald Freudenberger /* try direct way with the PCKMO instruction */ 4749e436c19SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, t->clearkey, 4759e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 4769e436c19SHarald Freudenberger if (!rc) 4779e436c19SHarald Freudenberger goto out; 4789e436c19SHarald Freudenberger 4799e436c19SHarald Freudenberger /* PCKMO failed, so try the CCA secure key way */ 4809e436c19SHarald Freudenberger tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 4819e436c19SHarald Freudenberger if (!tmpbuf) 4829e436c19SHarald Freudenberger return -ENOMEM; 4839e436c19SHarald Freudenberger zcrypt_wait_api_operational(); 4849e436c19SHarald Freudenberger rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, t->clearkey, tmpbuf); 4859e436c19SHarald Freudenberger if (rc) 4869e436c19SHarald Freudenberger goto try_via_ep11; 4879e436c19SHarald Freudenberger rc = pkey_skey2pkey(tmpbuf, 4889e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 4899e436c19SHarald Freudenberger if (!rc) 4909e436c19SHarald Freudenberger goto out; 4919e436c19SHarald Freudenberger 4929e436c19SHarald Freudenberger try_via_ep11: 4939e436c19SHarald Freudenberger /* if the CCA way also failed, let's try via EP11 */ 4949e436c19SHarald Freudenberger rc = pkey_clr2ep11key(t->clearkey, t->len, 4959e436c19SHarald Freudenberger tmpbuf, &tmpbuflen); 4969e436c19SHarald Freudenberger if (rc) 4979e436c19SHarald Freudenberger goto failure; 4989e436c19SHarald Freudenberger rc = pkey_ep11key2pkey(tmpbuf, 4999e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 5009e436c19SHarald Freudenberger if (!rc) 5019e436c19SHarald Freudenberger goto out; 5029e436c19SHarald Freudenberger 5039e436c19SHarald Freudenberger failure: 5049e436c19SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", __func__); 5059e436c19SHarald Freudenberger 5069e436c19SHarald Freudenberger out: 5079e436c19SHarald Freudenberger kfree(tmpbuf); 5089e436c19SHarald Freudenberger return rc; 5099e436c19SHarald Freudenberger } 5109e436c19SHarald Freudenberger 5119e436c19SHarald Freudenberger /* Helper for pkey_nonccatok2pkey, handles ecc clear key token */ 5129e436c19SHarald Freudenberger static int nonccatokecc2pkey(const struct clearkeytoken *t, 5139e436c19SHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 5149e436c19SHarald Freudenberger { 5159e436c19SHarald Freudenberger u32 keylen; 5169e436c19SHarald Freudenberger int rc; 5179e436c19SHarald Freudenberger 5189e436c19SHarald Freudenberger switch (t->keytype) { 5199e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P256: 5209e436c19SHarald Freudenberger keylen = 32; 5219e436c19SHarald Freudenberger break; 5229e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P384: 5239e436c19SHarald Freudenberger keylen = 48; 5249e436c19SHarald Freudenberger break; 5259e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P521: 5269e436c19SHarald Freudenberger keylen = 80; 5279e436c19SHarald Freudenberger break; 5289e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED25519: 5299e436c19SHarald Freudenberger keylen = 32; 5309e436c19SHarald Freudenberger break; 5319e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED448: 5329e436c19SHarald Freudenberger keylen = 64; 5339e436c19SHarald Freudenberger break; 5349e436c19SHarald Freudenberger default: 5359e436c19SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", 5369e436c19SHarald Freudenberger __func__, t->keytype); 5379e436c19SHarald Freudenberger return -EINVAL; 5389e436c19SHarald Freudenberger } 5399e436c19SHarald Freudenberger 5409e436c19SHarald Freudenberger if (t->len != keylen) { 5419e436c19SHarald Freudenberger DEBUG_ERR("%s non clear key ecc token: invalid key len %u\n", 5429e436c19SHarald Freudenberger __func__, t->len); 5439e436c19SHarald Freudenberger return -EINVAL; 5449e436c19SHarald Freudenberger } 5459e436c19SHarald Freudenberger 5469e436c19SHarald Freudenberger /* only one path possible: via PCKMO instruction */ 5479e436c19SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, t->clearkey, 5489e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 5499e436c19SHarald Freudenberger if (rc) { 5509e436c19SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", 5519e436c19SHarald Freudenberger __func__); 5529e436c19SHarald Freudenberger } 5539e436c19SHarald Freudenberger 5549e436c19SHarald Freudenberger return rc; 5559e436c19SHarald Freudenberger } 5569e436c19SHarald Freudenberger 557cb26b9ffSIngo Franzki /* 558fb1136d6SIngo Franzki * Transform a non-CCA key token into a protected key 559fb1136d6SIngo Franzki */ 560183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, 561f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 562fb1136d6SIngo Franzki { 563fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 56446a29b03SHarald Freudenberger int rc = -EINVAL; 565fb1136d6SIngo Franzki 566fb1136d6SIngo Franzki switch (hdr->version) { 567888edbc4SHarald Freudenberger case TOKVER_PROTECTED_KEY: { 568888edbc4SHarald Freudenberger struct protaeskeytoken *t; 569fb1136d6SIngo Franzki 570888edbc4SHarald Freudenberger if (keylen != sizeof(struct protaeskeytoken)) 571888edbc4SHarald Freudenberger goto out; 572fb1136d6SIngo Franzki t = (struct protaeskeytoken *)key; 573f370f45cSHarald Freudenberger rc = pkey_verifyprotkey(t->protkey, t->len, t->keytype); 574f370f45cSHarald Freudenberger if (rc) 575f370f45cSHarald Freudenberger goto out; 576f370f45cSHarald Freudenberger memcpy(protkey, t->protkey, t->len); 577f370f45cSHarald Freudenberger *protkeylen = t->len; 578f370f45cSHarald Freudenberger *protkeytype = t->keytype; 579888edbc4SHarald Freudenberger break; 580888edbc4SHarald Freudenberger } 581888edbc4SHarald Freudenberger case TOKVER_CLEAR_KEY: { 5829e436c19SHarald Freudenberger struct clearkeytoken *t = (struct clearkeytoken *)key; 583fb1136d6SIngo Franzki 5849e436c19SHarald Freudenberger if (keylen < sizeof(struct clearkeytoken) || 5859e436c19SHarald Freudenberger keylen != sizeof(*t) + t->len) 586888edbc4SHarald Freudenberger goto out; 5879e436c19SHarald Freudenberger switch (t->keytype) { 5889e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 5899e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 5909e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 5919e436c19SHarald Freudenberger rc = nonccatokaes2pkey(t, protkey, 5929e436c19SHarald Freudenberger protkeylen, protkeytype); 5939e436c19SHarald Freudenberger break; 5949e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P256: 5959e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P384: 5969e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P521: 5979e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED25519: 5989e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED448: 5999e436c19SHarald Freudenberger rc = nonccatokecc2pkey(t, protkey, 6009e436c19SHarald Freudenberger protkeylen, protkeytype); 6019e436c19SHarald Freudenberger break; 6029e436c19SHarald Freudenberger default: 6039e436c19SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported non cca clear key type %u\n", 6049e436c19SHarald Freudenberger __func__, t->keytype); 6059e436c19SHarald Freudenberger return -EINVAL; 60655d0a513SHarald Freudenberger } 607888edbc4SHarald Freudenberger break; 608888edbc4SHarald Freudenberger } 60955d0a513SHarald Freudenberger case TOKVER_EP11_AES: { 61055d0a513SHarald Freudenberger /* check ep11 key for exportable as protected key */ 611fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 61255d0a513SHarald Freudenberger if (rc) 61355d0a513SHarald Freudenberger goto out; 614f370f45cSHarald Freudenberger rc = pkey_ep11key2pkey(key, 615f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 61655d0a513SHarald Freudenberger break; 61755d0a513SHarald Freudenberger } 618fa6999e3SHarald Freudenberger case TOKVER_EP11_AES_WITH_HEADER: 619fa6999e3SHarald Freudenberger /* check ep11 key with header for exportable as protected key */ 620fa6999e3SHarald Freudenberger rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1); 621fa6999e3SHarald Freudenberger if (rc) 622fa6999e3SHarald Freudenberger goto out; 623fa6999e3SHarald Freudenberger rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header), 624f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 625fa6999e3SHarald Freudenberger break; 626fb1136d6SIngo Franzki default: 627fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 628fb1136d6SIngo Franzki __func__, hdr->version); 629fb1136d6SIngo Franzki } 630888edbc4SHarald Freudenberger 631888edbc4SHarald Freudenberger out: 632888edbc4SHarald Freudenberger return rc; 633fb1136d6SIngo Franzki } 634fb1136d6SIngo Franzki 635fb1136d6SIngo Franzki /* 636fb1136d6SIngo Franzki * Transform a CCA internal key token into a protected key 637fb1136d6SIngo Franzki */ 638183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, 639f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 640fb1136d6SIngo Franzki { 641fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 642fb1136d6SIngo Franzki 643fb1136d6SIngo Franzki switch (hdr->version) { 644fb1136d6SIngo Franzki case TOKVER_CCA_AES: 645fb1136d6SIngo Franzki if (keylen != sizeof(struct secaeskeytoken)) 646fb1136d6SIngo Franzki return -EINVAL; 647f2bbc96eSHarald Freudenberger break; 648f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 649f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 650f2bbc96eSHarald Freudenberger return -EINVAL; 651f2bbc96eSHarald Freudenberger break; 652fb1136d6SIngo Franzki default: 653fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 654fb1136d6SIngo Franzki __func__, hdr->version); 655fb1136d6SIngo Franzki return -EINVAL; 656fb1136d6SIngo Franzki } 657f2bbc96eSHarald Freudenberger 658f370f45cSHarald Freudenberger return pkey_skey2pkey(key, protkey, protkeylen, protkeytype); 659fb1136d6SIngo Franzki } 660fb1136d6SIngo Franzki 661fb1136d6SIngo Franzki /* 662fb1136d6SIngo Franzki * Transform a key blob (of any type) into a protected key 663fb1136d6SIngo Franzki */ 664183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen, 665f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 666fb1136d6SIngo Franzki { 667fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 66846a29b03SHarald Freudenberger int rc; 669fb1136d6SIngo Franzki 670f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) { 671f2bbc96eSHarald Freudenberger DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); 672f2bbc96eSHarald Freudenberger return -EINVAL; 673f2bbc96eSHarald Freudenberger } 674f2bbc96eSHarald Freudenberger 675f2bbc96eSHarald Freudenberger switch (hdr->type) { 676f2bbc96eSHarald Freudenberger case TOKTYPE_NON_CCA: 677f370f45cSHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, 678f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 679f2bbc96eSHarald Freudenberger break; 680f2bbc96eSHarald Freudenberger case TOKTYPE_CCA_INTERNAL: 681f370f45cSHarald Freudenberger rc = pkey_ccainttok2pkey(key, keylen, 682f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 683f2bbc96eSHarald Freudenberger break; 684f2bbc96eSHarald Freudenberger default: 685f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 686f2bbc96eSHarald Freudenberger __func__, hdr->type); 687f2bbc96eSHarald Freudenberger return -EINVAL; 688f2bbc96eSHarald Freudenberger } 689f2bbc96eSHarald Freudenberger 690f2bbc96eSHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 691f2bbc96eSHarald Freudenberger return rc; 692f2bbc96eSHarald Freudenberger } 693f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey); 694f2bbc96eSHarald Freudenberger 695f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 696f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 697f2bbc96eSHarald Freudenberger u32 kflags, u8 *keybuf, size_t *keybufsize) 698f2bbc96eSHarald Freudenberger { 699f2bbc96eSHarald Freudenberger int i, card, dom, rc; 700f2bbc96eSHarald Freudenberger 701f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 702f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 703f2bbc96eSHarald Freudenberger return -EINVAL; 704f2bbc96eSHarald Freudenberger 705f2bbc96eSHarald Freudenberger /* check key type and size */ 706f2bbc96eSHarald Freudenberger switch (ktype) { 707f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 708f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 709f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 710f2bbc96eSHarald Freudenberger return -EINVAL; 711f2bbc96eSHarald Freudenberger break; 71255d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 71355d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 71455d0a513SHarald Freudenberger return -EINVAL; 71555d0a513SHarald Freudenberger break; 716*fb249ce7SHolger Dengler case PKEY_TYPE_EP11_AES: 717*fb249ce7SHolger Dengler if (*keybufsize < (sizeof(struct ep11kblob_header) + 718*fb249ce7SHolger Dengler MINEP11AESKEYBLOBSIZE)) 719*fb249ce7SHolger Dengler return -EINVAL; 720*fb249ce7SHolger Dengler break; 721f2bbc96eSHarald Freudenberger default: 722f2bbc96eSHarald Freudenberger return -EINVAL; 723f2bbc96eSHarald Freudenberger } 724f2bbc96eSHarald Freudenberger switch (ksize) { 725f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 726f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 727f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 728f2bbc96eSHarald Freudenberger break; 729f2bbc96eSHarald Freudenberger default: 730f2bbc96eSHarald Freudenberger return -EINVAL; 731f2bbc96eSHarald Freudenberger } 732f2bbc96eSHarald Freudenberger 733f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 734f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 735f2bbc96eSHarald Freudenberger card = apqns[i].card; 736f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 737*fb249ce7SHolger Dengler if (ktype == PKEY_TYPE_EP11 || 738*fb249ce7SHolger Dengler ktype == PKEY_TYPE_EP11_AES) { 73955d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, ksize, kflags, 740*fb249ce7SHolger Dengler keybuf, keybufsize, ktype); 74155d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 742f2bbc96eSHarald Freudenberger rc = cca_genseckey(card, dom, ksize, keybuf); 743f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 7442004b57cSHarald Freudenberger } else { 7452004b57cSHarald Freudenberger /* TOKVER_CCA_VLSC */ 746f2bbc96eSHarald Freudenberger rc = cca_gencipherkey(card, dom, ksize, kflags, 747f2bbc96eSHarald Freudenberger keybuf, keybufsize); 7482004b57cSHarald Freudenberger } 749f2bbc96eSHarald Freudenberger if (rc == 0) 750f2bbc96eSHarald Freudenberger break; 751f2bbc96eSHarald Freudenberger } 752f2bbc96eSHarald Freudenberger 753f2bbc96eSHarald Freudenberger return rc; 754f2bbc96eSHarald Freudenberger } 755f2bbc96eSHarald Freudenberger 756f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 757f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 758f2bbc96eSHarald Freudenberger u32 kflags, const u8 *clrkey, 759f2bbc96eSHarald Freudenberger u8 *keybuf, size_t *keybufsize) 760f2bbc96eSHarald Freudenberger { 761f2bbc96eSHarald Freudenberger int i, card, dom, rc; 762f2bbc96eSHarald Freudenberger 763f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 764f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 765f2bbc96eSHarald Freudenberger return -EINVAL; 766f2bbc96eSHarald Freudenberger 767f2bbc96eSHarald Freudenberger /* check key type and size */ 768f2bbc96eSHarald Freudenberger switch (ktype) { 769f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 770f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 771f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 772f2bbc96eSHarald Freudenberger return -EINVAL; 773f2bbc96eSHarald Freudenberger break; 77455d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 77555d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 77655d0a513SHarald Freudenberger return -EINVAL; 77755d0a513SHarald Freudenberger break; 778f2bbc96eSHarald Freudenberger default: 779f2bbc96eSHarald Freudenberger return -EINVAL; 780f2bbc96eSHarald Freudenberger } 781f2bbc96eSHarald Freudenberger switch (ksize) { 782f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 783f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 784f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 785f2bbc96eSHarald Freudenberger break; 786f2bbc96eSHarald Freudenberger default: 787f2bbc96eSHarald Freudenberger return -EINVAL; 788f2bbc96eSHarald Freudenberger } 789f2bbc96eSHarald Freudenberger 79043cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 79143cb5a7cSHarald Freudenberger 792f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 793f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 794f2bbc96eSHarald Freudenberger card = apqns[i].card; 795f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 79655d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 79755d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, ksize, kflags, 79855d0a513SHarald Freudenberger clrkey, keybuf, keybufsize); 79955d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 800f2bbc96eSHarald Freudenberger rc = cca_clr2seckey(card, dom, ksize, 801f2bbc96eSHarald Freudenberger clrkey, keybuf); 802f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 8032004b57cSHarald Freudenberger } else { 8042004b57cSHarald Freudenberger /* TOKVER_CCA_VLSC */ 805f2bbc96eSHarald Freudenberger rc = cca_clr2cipherkey(card, dom, ksize, kflags, 806f2bbc96eSHarald Freudenberger clrkey, keybuf, keybufsize); 8072004b57cSHarald Freudenberger } 808f2bbc96eSHarald Freudenberger if (rc == 0) 809f2bbc96eSHarald Freudenberger break; 810f2bbc96eSHarald Freudenberger } 811f2bbc96eSHarald Freudenberger 812f2bbc96eSHarald Freudenberger return rc; 813f2bbc96eSHarald Freudenberger } 814f2bbc96eSHarald Freudenberger 815f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen, 816f2bbc96eSHarald Freudenberger u16 *cardnr, u16 *domain, 817f2bbc96eSHarald Freudenberger enum pkey_key_type *ktype, 818f2bbc96eSHarald Freudenberger enum pkey_key_size *ksize, u32 *flags) 819f2bbc96eSHarald Freudenberger { 820f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 82146a29b03SHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 82246a29b03SHarald Freudenberger int rc; 823f2bbc96eSHarald Freudenberger 82455d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 825f2bbc96eSHarald Freudenberger return -EINVAL; 826f2bbc96eSHarald Freudenberger 8272004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 8282004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 829f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 830f2bbc96eSHarald Freudenberger 831f2bbc96eSHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 832f2bbc96eSHarald Freudenberger if (rc) 833f2bbc96eSHarald Freudenberger goto out; 834f2bbc96eSHarald Freudenberger if (ktype) 835f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_DATA; 836f2bbc96eSHarald Freudenberger if (ksize) 837f2bbc96eSHarald Freudenberger *ksize = (enum pkey_key_size)t->bitsize; 838f2bbc96eSHarald Freudenberger 839f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 84032ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); 841f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 842f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 843f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 844f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 845f2bbc96eSHarald Freudenberger *cardnr, *domain, 84632ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, 84732ca04bbSHarald Freudenberger 0, t->mkvp, 1); 848f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 849f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 850f2bbc96eSHarald Freudenberger } 851f2bbc96eSHarald Freudenberger if (rc) 852f2bbc96eSHarald Freudenberger goto out; 853f2bbc96eSHarald Freudenberger 854f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 855f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 856f2bbc96eSHarald Freudenberger 8572004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 8582004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 859f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 860f2bbc96eSHarald Freudenberger 861f2bbc96eSHarald Freudenberger rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 862f2bbc96eSHarald Freudenberger if (rc) 863f2bbc96eSHarald Freudenberger goto out; 864f2bbc96eSHarald Freudenberger if (ktype) 865f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_CIPHER; 866f2bbc96eSHarald Freudenberger if (ksize) { 867f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_UNKNOWN; 868f2bbc96eSHarald Freudenberger if (!t->plfver && t->wpllen == 512) 869f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_128; 870f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 871f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_192; 872f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 873f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_256; 874f2bbc96eSHarald Freudenberger } 875f2bbc96eSHarald Freudenberger 876f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 87732ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); 878f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 879f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 880f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 881f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 882f2bbc96eSHarald Freudenberger *cardnr, *domain, 88332ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, 88432ca04bbSHarald Freudenberger 0, t->mkvp0, 1); 885f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 886f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 887f2bbc96eSHarald Freudenberger } 888f2bbc96eSHarald Freudenberger if (rc) 889f2bbc96eSHarald Freudenberger goto out; 890f2bbc96eSHarald Freudenberger 891f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 892f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 893f2bbc96eSHarald Freudenberger 8942004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 8952004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES) { 89655d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 89755d0a513SHarald Freudenberger 898fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 89955d0a513SHarald Freudenberger if (rc) 90055d0a513SHarald Freudenberger goto out; 90155d0a513SHarald Freudenberger if (ktype) 90255d0a513SHarald Freudenberger *ktype = PKEY_TYPE_EP11; 90355d0a513SHarald Freudenberger if (ksize) 90437a08f01SHolger Dengler *ksize = kb->head.bitlen; 90555d0a513SHarald Freudenberger 90655d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 90755d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 90855d0a513SHarald Freudenberger if (rc) 90955d0a513SHarald Freudenberger goto out; 91055d0a513SHarald Freudenberger 91155d0a513SHarald Freudenberger if (flags) 91255d0a513SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 91355d0a513SHarald Freudenberger 91455d0a513SHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 91555d0a513SHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 91655d0a513SHarald Freudenberger 9172004b57cSHarald Freudenberger } else { 918f2bbc96eSHarald Freudenberger rc = -EINVAL; 9192004b57cSHarald Freudenberger } 920f2bbc96eSHarald Freudenberger 921f2bbc96eSHarald Freudenberger out: 922f2bbc96eSHarald Freudenberger kfree(_apqns); 923f2bbc96eSHarald Freudenberger return rc; 924f2bbc96eSHarald Freudenberger } 925f2bbc96eSHarald Freudenberger 926f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 927f2bbc96eSHarald Freudenberger const u8 *key, size_t keylen, 928f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 929f2bbc96eSHarald Freudenberger { 930f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 93146a29b03SHarald Freudenberger int i, card, dom, rc; 932f2bbc96eSHarald Freudenberger 933f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 934f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 935f2bbc96eSHarald Freudenberger return -EINVAL; 936f2bbc96eSHarald Freudenberger 937fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 938fb1136d6SIngo Franzki return -EINVAL; 939fb1136d6SIngo Franzki 94055d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL) { 94155d0a513SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 942f2bbc96eSHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 943f2bbc96eSHarald Freudenberger return -EINVAL; 944f2bbc96eSHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 945f2bbc96eSHarald Freudenberger return -EINVAL; 94655d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 947f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 948f2bbc96eSHarald Freudenberger return -EINVAL; 949f2bbc96eSHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 950f2bbc96eSHarald Freudenberger return -EINVAL; 95155d0a513SHarald Freudenberger } else { 952f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 953f2bbc96eSHarald Freudenberger __func__, hdr->version); 954fb1136d6SIngo Franzki return -EINVAL; 955fb1136d6SIngo Franzki } 95655d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 95755d0a513SHarald Freudenberger if (hdr->version == TOKVER_EP11_AES) { 95855d0a513SHarald Freudenberger if (keylen < sizeof(struct ep11keyblob)) 95955d0a513SHarald Freudenberger return -EINVAL; 960fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 96155d0a513SHarald Freudenberger return -EINVAL; 96255d0a513SHarald Freudenberger } else { 963f370f45cSHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, 964f370f45cSHarald Freudenberger protkey, protkeylen, 965f370f45cSHarald Freudenberger protkeytype); 96655d0a513SHarald Freudenberger } 96755d0a513SHarald Freudenberger } else { 968f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 969f2bbc96eSHarald Freudenberger __func__, hdr->type); 970f2bbc96eSHarald Freudenberger return -EINVAL; 971fb1136d6SIngo Franzki } 972f2bbc96eSHarald Freudenberger 97343cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 97443cb5a7cSHarald Freudenberger 975f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 976f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 977f2bbc96eSHarald Freudenberger card = apqns[i].card; 978f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 9792004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 9802004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 981f370f45cSHarald Freudenberger rc = cca_sec2protkey(card, dom, key, 982f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 9832004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 9842004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 985f370f45cSHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, 986f370f45cSHarald Freudenberger protkey, protkeylen, 987f370f45cSHarald Freudenberger protkeytype); 9882004b57cSHarald Freudenberger } else { 9892004b57cSHarald Freudenberger /* EP11 AES secure key blob */ 99055d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 99155d0a513SHarald Freudenberger 992fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 993f370f45cSHarald Freudenberger protkey, protkeylen, 994f370f45cSHarald Freudenberger protkeytype); 99555d0a513SHarald Freudenberger } 996f2bbc96eSHarald Freudenberger if (rc == 0) 997f2bbc96eSHarald Freudenberger break; 998f2bbc96eSHarald Freudenberger } 999f2bbc96eSHarald Freudenberger 1000f2bbc96eSHarald Freudenberger return rc; 1001f2bbc96eSHarald Freudenberger } 1002f2bbc96eSHarald Freudenberger 1003f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 1004f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 1005f2bbc96eSHarald Freudenberger { 1006f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 100746a29b03SHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 100846a29b03SHarald Freudenberger int rc; 1009f2bbc96eSHarald Freudenberger 101055d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || flags == 0) 1011f2bbc96eSHarald Freudenberger return -EINVAL; 1012f2bbc96eSHarald Freudenberger 101343cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 101443cb5a7cSHarald Freudenberger 10152004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 10162004b57cSHarald Freudenberger (hdr->version == TOKVER_EP11_AES_WITH_HEADER || 10172004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && 10182004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1019fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) 1020fa6999e3SHarald Freudenberger (key + sizeof(struct ep11kblob_header)); 102146a29b03SHarald Freudenberger int minhwtype = 0, api = 0; 1022fa6999e3SHarald Freudenberger 1023fa6999e3SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 1024fa6999e3SHarald Freudenberger return -EINVAL; 1025fa6999e3SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 1026fa6999e3SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 1027fa6999e3SHarald Freudenberger api = EP11_API_V; 1028fa6999e3SHarald Freudenberger } 1029fa6999e3SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1030fa6999e3SHarald Freudenberger minhwtype, api, kb->wkvp); 1031fa6999e3SHarald Freudenberger if (rc) 1032fa6999e3SHarald Freudenberger goto out; 10332004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 10342004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 10352004b57cSHarald Freudenberger is_ep11_keyblob(key)) { 103655d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 103746a29b03SHarald Freudenberger int minhwtype = 0, api = 0; 103855d0a513SHarald Freudenberger 103955d0a513SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 104055d0a513SHarald Freudenberger return -EINVAL; 104155d0a513SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 104255d0a513SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 104355d0a513SHarald Freudenberger api = EP11_API_V; 104455d0a513SHarald Freudenberger } 104555d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 104655d0a513SHarald Freudenberger minhwtype, api, kb->wkvp); 104755d0a513SHarald Freudenberger if (rc) 104855d0a513SHarald Freudenberger goto out; 104955d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 1050f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 105146a29b03SHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 1052f2bbc96eSHarald Freudenberger 1053f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 1054f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 1055f2bbc96eSHarald Freudenberger 1056f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1057f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp; 1058f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1059f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp; 106055d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1061f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 1062f2bbc96eSHarald Freudenberger 1063f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 1064f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1065f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp0; 1066f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1067f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp0; 106855d0a513SHarald Freudenberger } else { 106955d0a513SHarald Freudenberger /* unknown cca internal token type */ 107055d0a513SHarald Freudenberger return -EINVAL; 1071f2bbc96eSHarald Freudenberger } 1072f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 107332ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 107432ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1075f2bbc96eSHarald Freudenberger if (rc) 1076f2bbc96eSHarald Freudenberger goto out; 1077fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1078fa6999e3SHarald Freudenberger struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; 107946a29b03SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1080fa6999e3SHarald Freudenberger 1081fa6999e3SHarald Freudenberger if (t->secid == 0x20) { 1082fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1083fa6999e3SHarald Freudenberger cur_mkvp = t->mkvp; 1084fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1085fa6999e3SHarald Freudenberger old_mkvp = t->mkvp; 1086fa6999e3SHarald Freudenberger } else { 1087fa6999e3SHarald Freudenberger /* unknown cca internal 2 token type */ 1088fa6999e3SHarald Freudenberger return -EINVAL; 1089fa6999e3SHarald Freudenberger } 1090fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1091fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 1092fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 1093fa6999e3SHarald Freudenberger if (rc) 1094fa6999e3SHarald Freudenberger goto out; 10952004b57cSHarald Freudenberger } else { 109655d0a513SHarald Freudenberger return -EINVAL; 10972004b57cSHarald Freudenberger } 109855d0a513SHarald Freudenberger 1099f2bbc96eSHarald Freudenberger if (apqns) { 1100f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 1101f2bbc96eSHarald Freudenberger rc = -ENOSPC; 1102f2bbc96eSHarald Freudenberger else 1103f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 1104f2bbc96eSHarald Freudenberger } 1105f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 1106f2bbc96eSHarald Freudenberger 1107f2bbc96eSHarald Freudenberger out: 1108f2bbc96eSHarald Freudenberger kfree(_apqns); 1109f2bbc96eSHarald Freudenberger return rc; 1110f2bbc96eSHarald Freudenberger } 1111f2bbc96eSHarald Freudenberger 1112f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype, 1113f2bbc96eSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 1114f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 1115f2bbc96eSHarald Freudenberger { 1116f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 111746a29b03SHarald Freudenberger int rc; 1118f2bbc96eSHarald Freudenberger 111943cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 112043cb5a7cSHarald Freudenberger 1121f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 1122f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1123f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 1124f2bbc96eSHarald Freudenberger 1125f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1126f2bbc96eSHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 1127f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1128f2bbc96eSHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 1129f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 1130f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 1131f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 113232ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 113332ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1134f2bbc96eSHarald Freudenberger if (rc) 1135f2bbc96eSHarald Freudenberger goto out; 1136fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_ECC) { 1137fa6999e3SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1138fa6999e3SHarald Freudenberger 1139fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1140fa6999e3SHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 1141fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1142fa6999e3SHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 1143fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1144fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 1145fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 1146fa6999e3SHarald Freudenberger if (rc) 1147fa6999e3SHarald Freudenberger goto out; 1148fa6999e3SHarald Freudenberger 1149fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_EP11 || 1150fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_AES || 1151fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_ECC) { 115255d0a513SHarald Freudenberger u8 *wkvp = NULL; 115355d0a513SHarald Freudenberger 115455d0a513SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 115555d0a513SHarald Freudenberger wkvp = cur_mkvp; 115655d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 115755d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, wkvp); 115855d0a513SHarald Freudenberger if (rc) 115955d0a513SHarald Freudenberger goto out; 116055d0a513SHarald Freudenberger 11612004b57cSHarald Freudenberger } else { 116255d0a513SHarald Freudenberger return -EINVAL; 11632004b57cSHarald Freudenberger } 116455d0a513SHarald Freudenberger 1165f2bbc96eSHarald Freudenberger if (apqns) { 1166f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 1167f2bbc96eSHarald Freudenberger rc = -ENOSPC; 1168f2bbc96eSHarald Freudenberger else 1169f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 1170f2bbc96eSHarald Freudenberger } 1171f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 1172f2bbc96eSHarald Freudenberger 1173f2bbc96eSHarald Freudenberger out: 1174f2bbc96eSHarald Freudenberger kfree(_apqns); 1175f2bbc96eSHarald Freudenberger return rc; 1176f2bbc96eSHarald Freudenberger } 1177fb1136d6SIngo Franzki 1178fa6999e3SHarald Freudenberger static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, 1179f370f45cSHarald Freudenberger const u8 *key, size_t keylen, 1180f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 1181fa6999e3SHarald Freudenberger { 1182fa6999e3SHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 118346a29b03SHarald Freudenberger int i, card, dom, rc; 1184fa6999e3SHarald Freudenberger 1185fa6999e3SHarald Freudenberger /* check for at least one apqn given */ 1186fa6999e3SHarald Freudenberger if (!apqns || !nr_apqns) 1187fa6999e3SHarald Freudenberger return -EINVAL; 1188fa6999e3SHarald Freudenberger 1189fa6999e3SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 1190fa6999e3SHarald Freudenberger return -EINVAL; 1191fa6999e3SHarald Freudenberger 11922004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 11932004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES_WITH_HEADER && 11942004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1195fa6999e3SHarald Freudenberger /* EP11 AES key blob with header */ 1196fa6999e3SHarald Freudenberger if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1)) 1197fa6999e3SHarald Freudenberger return -EINVAL; 11982004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 11992004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER && 12002004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1201fa6999e3SHarald Freudenberger /* EP11 ECC key blob with header */ 1202fa6999e3SHarald Freudenberger if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1)) 1203fa6999e3SHarald Freudenberger return -EINVAL; 12042004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 12052004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 12062004b57cSHarald Freudenberger is_ep11_keyblob(key)) { 1207fa6999e3SHarald Freudenberger /* EP11 AES key blob with header in session field */ 1208fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 1209fa6999e3SHarald Freudenberger return -EINVAL; 1210fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 1211fa6999e3SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 1212fa6999e3SHarald Freudenberger /* CCA AES data key */ 1213fa6999e3SHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 1214fa6999e3SHarald Freudenberger return -EINVAL; 1215fa6999e3SHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 1216fa6999e3SHarald Freudenberger return -EINVAL; 1217fa6999e3SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1218fa6999e3SHarald Freudenberger /* CCA AES cipher key */ 1219fa6999e3SHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 1220fa6999e3SHarald Freudenberger return -EINVAL; 1221fa6999e3SHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 1222fa6999e3SHarald Freudenberger return -EINVAL; 1223fa6999e3SHarald Freudenberger } else { 1224fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 1225fa6999e3SHarald Freudenberger __func__, hdr->version); 1226fa6999e3SHarald Freudenberger return -EINVAL; 1227fa6999e3SHarald Freudenberger } 1228fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1229fa6999e3SHarald Freudenberger /* CCA ECC (private) key */ 1230fa6999e3SHarald Freudenberger if (keylen < sizeof(struct eccprivkeytoken)) 1231fa6999e3SHarald Freudenberger return -EINVAL; 1232fa6999e3SHarald Freudenberger if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) 1233fa6999e3SHarald Freudenberger return -EINVAL; 1234fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 1235f370f45cSHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, 1236f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 1237fa6999e3SHarald Freudenberger } else { 1238fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 1239fa6999e3SHarald Freudenberger __func__, hdr->type); 1240fa6999e3SHarald Freudenberger return -EINVAL; 1241fa6999e3SHarald Freudenberger } 1242fa6999e3SHarald Freudenberger 1243fa6999e3SHarald Freudenberger /* simple try all apqns from the list */ 1244fa6999e3SHarald Freudenberger for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 1245fa6999e3SHarald Freudenberger card = apqns[i].card; 1246fa6999e3SHarald Freudenberger dom = apqns[i].domain; 12472004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 12482004b57cSHarald Freudenberger (hdr->version == TOKVER_EP11_AES_WITH_HEADER || 12492004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && 12502004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) 1251fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1252fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 12532004b57cSHarald Freudenberger else if (hdr->type == TOKTYPE_NON_CCA && 12542004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 12552004b57cSHarald Freudenberger is_ep11_keyblob(key)) 1256fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1257fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 1258fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1259fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_AES) 1260fa6999e3SHarald Freudenberger rc = cca_sec2protkey(card, dom, key, protkey, 1261fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1262fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1263fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) 1264fa6999e3SHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, protkey, 1265fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1266fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) 1267fa6999e3SHarald Freudenberger rc = cca_ecc2protkey(card, dom, key, protkey, 1268fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1269fa6999e3SHarald Freudenberger else 1270fa6999e3SHarald Freudenberger return -EINVAL; 1271fa6999e3SHarald Freudenberger } 1272fa6999e3SHarald Freudenberger 1273fa6999e3SHarald Freudenberger return rc; 1274fa6999e3SHarald Freudenberger } 1275fa6999e3SHarald Freudenberger 1276fb1136d6SIngo Franzki /* 1277e80d4af0SHarald Freudenberger * File io functions 1278e80d4af0SHarald Freudenberger */ 1279e80d4af0SHarald Freudenberger 1280f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen) 1281f2bbc96eSHarald Freudenberger { 12829e436c19SHarald Freudenberger if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE) 1283f2bbc96eSHarald Freudenberger return ERR_PTR(-EINVAL); 1284f2bbc96eSHarald Freudenberger 12858b57e7c8SMarkus Elfring return memdup_user(ukey, keylen); 1286f2bbc96eSHarald Freudenberger } 1287f2bbc96eSHarald Freudenberger 1288f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 1289f2bbc96eSHarald Freudenberger { 12908b57e7c8SMarkus Elfring if (!uapqns || nr_apqns == 0) 12918b57e7c8SMarkus Elfring return NULL; 1292f2bbc96eSHarald Freudenberger 12938b57e7c8SMarkus Elfring return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); 1294f2bbc96eSHarald Freudenberger } 1295f2bbc96eSHarald Freudenberger 1296e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 1297e80d4af0SHarald Freudenberger unsigned long arg) 1298e80d4af0SHarald Freudenberger { 1299e80d4af0SHarald Freudenberger int rc; 1300e80d4af0SHarald Freudenberger 1301e80d4af0SHarald Freudenberger switch (cmd) { 1302e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1303e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *)arg; 1304e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1305e80d4af0SHarald Freudenberger 1306e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1307e80d4af0SHarald Freudenberger return -EFAULT; 1308efc598e6SHarald Freudenberger rc = cca_genseckey(kgs.cardnr, kgs.domain, 1309efc598e6SHarald Freudenberger kgs.keytype, kgs.seckey.seckey); 1310efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 1311e80d4af0SHarald Freudenberger if (rc) 1312e80d4af0SHarald Freudenberger break; 1313e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1314e80d4af0SHarald Freudenberger return -EFAULT; 1315e80d4af0SHarald Freudenberger break; 1316e80d4af0SHarald Freudenberger } 1317e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1318e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *)arg; 1319e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1320e80d4af0SHarald Freudenberger 1321e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1322e80d4af0SHarald Freudenberger return -EFAULT; 1323efc598e6SHarald Freudenberger rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1324efc598e6SHarald Freudenberger kcs.clrkey.clrkey, kcs.seckey.seckey); 1325efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 1326e80d4af0SHarald Freudenberger if (rc) 1327e80d4af0SHarald Freudenberger break; 1328e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1329e80d4af0SHarald Freudenberger return -EFAULT; 1330e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1331e80d4af0SHarald Freudenberger break; 1332e80d4af0SHarald Freudenberger } 1333e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1334e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *)arg; 1335e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1336e80d4af0SHarald Freudenberger 1337e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1338e80d4af0SHarald Freudenberger return -EFAULT; 1339f370f45cSHarald Freudenberger ksp.protkey.len = sizeof(ksp.protkey.protkey); 1340efc598e6SHarald Freudenberger rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 1341efc598e6SHarald Freudenberger ksp.seckey.seckey, ksp.protkey.protkey, 1342aab73d27SHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1343efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 1344e80d4af0SHarald Freudenberger if (rc) 1345e80d4af0SHarald Freudenberger break; 1346e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1347e80d4af0SHarald Freudenberger return -EFAULT; 1348e80d4af0SHarald Freudenberger break; 1349e80d4af0SHarald Freudenberger } 1350e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1351e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *)arg; 1352e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1353e80d4af0SHarald Freudenberger 1354e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1355e80d4af0SHarald Freudenberger return -EFAULT; 1356f370f45cSHarald Freudenberger kcp.protkey.len = sizeof(kcp.protkey.protkey); 1357f370f45cSHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey, 1358f370f45cSHarald Freudenberger kcp.protkey.protkey, 1359f370f45cSHarald Freudenberger &kcp.protkey.len, &kcp.protkey.type); 1360ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1361e80d4af0SHarald Freudenberger if (rc) 1362e80d4af0SHarald Freudenberger break; 1363e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1364e80d4af0SHarald Freudenberger return -EFAULT; 1365e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1366e80d4af0SHarald Freudenberger break; 1367e80d4af0SHarald Freudenberger } 1368e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1369e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *)arg; 1370e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1371e80d4af0SHarald Freudenberger 1372e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1373e80d4af0SHarald Freudenberger return -EFAULT; 1374efc598e6SHarald Freudenberger rc = cca_findcard(kfc.seckey.seckey, 1375e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1376efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 1377efc598e6SHarald Freudenberger if (rc < 0) 1378e80d4af0SHarald Freudenberger break; 1379e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1380e80d4af0SHarald Freudenberger return -EFAULT; 1381e80d4af0SHarald Freudenberger break; 1382e80d4af0SHarald Freudenberger } 1383e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1384e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *)arg; 1385e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1386e80d4af0SHarald Freudenberger 1387e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1388e80d4af0SHarald Freudenberger return -EFAULT; 1389f370f45cSHarald Freudenberger ksp.protkey.len = sizeof(ksp.protkey.protkey); 1390f370f45cSHarald Freudenberger rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey, 1391f370f45cSHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1392ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1393e80d4af0SHarald Freudenberger if (rc) 1394e80d4af0SHarald Freudenberger break; 1395e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1396e80d4af0SHarald Freudenberger return -EFAULT; 1397e80d4af0SHarald Freudenberger break; 1398e80d4af0SHarald Freudenberger } 1399e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1400e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *)arg; 1401e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1402e61a6134SHarald Freudenberger 1403e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1404e61a6134SHarald Freudenberger return -EFAULT; 1405e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1406e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1407ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1408e61a6134SHarald Freudenberger if (rc) 1409e61a6134SHarald Freudenberger break; 1410e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1411e61a6134SHarald Freudenberger return -EFAULT; 1412e61a6134SHarald Freudenberger break; 1413e61a6134SHarald Freudenberger } 1414a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1415a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *)arg; 1416a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1417a45a5c7dSIngo Franzki 1418a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1419a45a5c7dSIngo Franzki return -EFAULT; 1420f370f45cSHarald Freudenberger kgp.protkey.len = sizeof(kgp.protkey.protkey); 1421f370f45cSHarald Freudenberger rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey, 1422f370f45cSHarald Freudenberger &kgp.protkey.len, &kgp.protkey.type); 1423a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1424a45a5c7dSIngo Franzki if (rc) 1425a45a5c7dSIngo Franzki break; 1426a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1427a45a5c7dSIngo Franzki return -EFAULT; 1428a45a5c7dSIngo Franzki break; 1429a45a5c7dSIngo Franzki } 1430cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 1431cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *)arg; 1432cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 1433cb26b9ffSIngo Franzki 1434cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 1435cb26b9ffSIngo Franzki return -EFAULT; 1436f370f45cSHarald Freudenberger rc = pkey_verifyprotkey(kvp.protkey.protkey, 1437f370f45cSHarald Freudenberger kvp.protkey.len, kvp.protkey.type); 1438cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 1439cb26b9ffSIngo Franzki break; 1440cb26b9ffSIngo Franzki } 1441fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 1442fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *)arg; 1443fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 1444183cb469SHarald Freudenberger u8 *kkey; 1445fb1136d6SIngo Franzki 1446fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 1447fb1136d6SIngo Franzki return -EFAULT; 1448f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1449f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1450f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1451f370f45cSHarald Freudenberger ktp.protkey.len = sizeof(ktp.protkey.protkey); 1452f370f45cSHarald Freudenberger rc = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey, 1453f370f45cSHarald Freudenberger &ktp.protkey.len, &ktp.protkey.type); 1454fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 1455844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1456fb1136d6SIngo Franzki kfree(kkey); 1457fb1136d6SIngo Franzki if (rc) 1458fb1136d6SIngo Franzki break; 1459fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 1460fb1136d6SIngo Franzki return -EFAULT; 1461fb1136d6SIngo Franzki break; 1462fb1136d6SIngo Franzki } 1463f2bbc96eSHarald Freudenberger case PKEY_GENSECK2: { 1464f2bbc96eSHarald Freudenberger struct pkey_genseck2 __user *ugs = (void __user *)arg; 146546a29b03SHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1466f2bbc96eSHarald Freudenberger struct pkey_genseck2 kgs; 1467f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1468f2bbc96eSHarald Freudenberger u8 *kkey; 1469f2bbc96eSHarald Freudenberger 1470f2bbc96eSHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1471f2bbc96eSHarald Freudenberger return -EFAULT; 1472f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 1473f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1474f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1475*fb249ce7SHolger Dengler kkey = kzalloc(klen, GFP_KERNEL); 1476f2bbc96eSHarald Freudenberger if (!kkey) { 1477f2bbc96eSHarald Freudenberger kfree(apqns); 1478f2bbc96eSHarald Freudenberger return -ENOMEM; 1479f2bbc96eSHarald Freudenberger } 1480f2bbc96eSHarald Freudenberger rc = pkey_genseckey2(apqns, kgs.apqn_entries, 1481f2bbc96eSHarald Freudenberger kgs.type, kgs.size, kgs.keygenflags, 1482f2bbc96eSHarald Freudenberger kkey, &klen); 1483f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 1484f2bbc96eSHarald Freudenberger kfree(apqns); 1485f2bbc96eSHarald Freudenberger if (rc) { 1486f2bbc96eSHarald Freudenberger kfree(kkey); 1487f2bbc96eSHarald Freudenberger break; 1488f2bbc96eSHarald Freudenberger } 1489f2bbc96eSHarald Freudenberger if (kgs.key) { 1490f2bbc96eSHarald Freudenberger if (kgs.keylen < klen) { 1491f2bbc96eSHarald Freudenberger kfree(kkey); 1492f2bbc96eSHarald Freudenberger return -EINVAL; 1493f2bbc96eSHarald Freudenberger } 1494f2bbc96eSHarald Freudenberger if (copy_to_user(kgs.key, kkey, klen)) { 1495f2bbc96eSHarald Freudenberger kfree(kkey); 1496f2bbc96eSHarald Freudenberger return -EFAULT; 1497f2bbc96eSHarald Freudenberger } 1498f2bbc96eSHarald Freudenberger } 1499f2bbc96eSHarald Freudenberger kgs.keylen = klen; 1500f2bbc96eSHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1501f2bbc96eSHarald Freudenberger rc = -EFAULT; 1502f2bbc96eSHarald Freudenberger kfree(kkey); 1503f2bbc96eSHarald Freudenberger break; 1504f2bbc96eSHarald Freudenberger } 1505f2bbc96eSHarald Freudenberger case PKEY_CLR2SECK2: { 1506f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 __user *ucs = (void __user *)arg; 150746a29b03SHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1508f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 kcs; 1509f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1510f2bbc96eSHarald Freudenberger u8 *kkey; 1511f2bbc96eSHarald Freudenberger 1512f2bbc96eSHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1513f2bbc96eSHarald Freudenberger return -EFAULT; 1514f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 1515f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1516f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1517f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1518f2bbc96eSHarald Freudenberger if (!kkey) { 1519f2bbc96eSHarald Freudenberger kfree(apqns); 1520f2bbc96eSHarald Freudenberger return -ENOMEM; 1521f2bbc96eSHarald Freudenberger } 1522f2bbc96eSHarald Freudenberger rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 1523f2bbc96eSHarald Freudenberger kcs.type, kcs.size, kcs.keygenflags, 1524f2bbc96eSHarald Freudenberger kcs.clrkey.clrkey, kkey, &klen); 1525f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 1526f2bbc96eSHarald Freudenberger kfree(apqns); 1527f2bbc96eSHarald Freudenberger if (rc) { 1528f2bbc96eSHarald Freudenberger kfree(kkey); 1529f2bbc96eSHarald Freudenberger break; 1530f2bbc96eSHarald Freudenberger } 1531f2bbc96eSHarald Freudenberger if (kcs.key) { 1532f2bbc96eSHarald Freudenberger if (kcs.keylen < klen) { 1533f2bbc96eSHarald Freudenberger kfree(kkey); 1534f2bbc96eSHarald Freudenberger return -EINVAL; 1535f2bbc96eSHarald Freudenberger } 1536f2bbc96eSHarald Freudenberger if (copy_to_user(kcs.key, kkey, klen)) { 1537f2bbc96eSHarald Freudenberger kfree(kkey); 1538f2bbc96eSHarald Freudenberger return -EFAULT; 1539f2bbc96eSHarald Freudenberger } 1540f2bbc96eSHarald Freudenberger } 1541f2bbc96eSHarald Freudenberger kcs.keylen = klen; 1542f2bbc96eSHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1543f2bbc96eSHarald Freudenberger rc = -EFAULT; 1544f2bbc96eSHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1545f2bbc96eSHarald Freudenberger kfree(kkey); 1546f2bbc96eSHarald Freudenberger break; 1547f2bbc96eSHarald Freudenberger } 1548f2bbc96eSHarald Freudenberger case PKEY_VERIFYKEY2: { 1549f2bbc96eSHarald Freudenberger struct pkey_verifykey2 __user *uvk = (void __user *)arg; 1550f2bbc96eSHarald Freudenberger struct pkey_verifykey2 kvk; 1551f2bbc96eSHarald Freudenberger u8 *kkey; 1552f2bbc96eSHarald Freudenberger 1553f2bbc96eSHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1554f2bbc96eSHarald Freudenberger return -EFAULT; 1555f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kvk.key, kvk.keylen); 1556f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1557f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1558f2bbc96eSHarald Freudenberger rc = pkey_verifykey2(kkey, kvk.keylen, 1559f2bbc96eSHarald Freudenberger &kvk.cardnr, &kvk.domain, 1560f2bbc96eSHarald Freudenberger &kvk.type, &kvk.size, &kvk.flags); 1561f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 1562f2bbc96eSHarald Freudenberger kfree(kkey); 1563f2bbc96eSHarald Freudenberger if (rc) 1564f2bbc96eSHarald Freudenberger break; 1565f2bbc96eSHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1566f2bbc96eSHarald Freudenberger return -EFAULT; 1567f2bbc96eSHarald Freudenberger break; 1568f2bbc96eSHarald Freudenberger } 1569f2bbc96eSHarald Freudenberger case PKEY_KBLOB2PROTK2: { 1570f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 __user *utp = (void __user *)arg; 1571f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 157246a29b03SHarald Freudenberger struct pkey_kblob2pkey2 ktp; 1573f2bbc96eSHarald Freudenberger u8 *kkey; 1574f2bbc96eSHarald Freudenberger 1575f2bbc96eSHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1576f2bbc96eSHarald Freudenberger return -EFAULT; 1577f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1578f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1579f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1580f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1581f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1582f2bbc96eSHarald Freudenberger kfree(apqns); 1583f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1584f2bbc96eSHarald Freudenberger } 1585f370f45cSHarald Freudenberger ktp.protkey.len = sizeof(ktp.protkey.protkey); 1586f2bbc96eSHarald Freudenberger rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 1587f370f45cSHarald Freudenberger kkey, ktp.keylen, 1588f370f45cSHarald Freudenberger ktp.protkey.protkey, &ktp.protkey.len, 1589f370f45cSHarald Freudenberger &ktp.protkey.type); 1590f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 1591f2bbc96eSHarald Freudenberger kfree(apqns); 1592844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1593f2bbc96eSHarald Freudenberger kfree(kkey); 1594f2bbc96eSHarald Freudenberger if (rc) 1595f2bbc96eSHarald Freudenberger break; 1596f2bbc96eSHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1597f2bbc96eSHarald Freudenberger return -EFAULT; 1598f2bbc96eSHarald Freudenberger break; 1599f2bbc96eSHarald Freudenberger } 1600f2bbc96eSHarald Freudenberger case PKEY_APQNS4K: { 1601f2bbc96eSHarald Freudenberger struct pkey_apqns4key __user *uak = (void __user *)arg; 1602f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 160346a29b03SHarald Freudenberger struct pkey_apqns4key kak; 1604f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1605f2bbc96eSHarald Freudenberger u8 *kkey; 1606f2bbc96eSHarald Freudenberger 1607f2bbc96eSHarald Freudenberger if (copy_from_user(&kak, uak, sizeof(kak))) 1608f2bbc96eSHarald Freudenberger return -EFAULT; 1609f2bbc96eSHarald Freudenberger nr_apqns = kak.apqn_entries; 1610f2bbc96eSHarald Freudenberger if (nr_apqns) { 1611f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1612f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1613f2bbc96eSHarald Freudenberger GFP_KERNEL); 1614f2bbc96eSHarald Freudenberger if (!apqns) 1615f2bbc96eSHarald Freudenberger return -ENOMEM; 1616f2bbc96eSHarald Freudenberger } 1617f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kak.key, kak.keylen); 1618f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1619f2bbc96eSHarald Freudenberger kfree(apqns); 1620f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1621f2bbc96eSHarald Freudenberger } 1622f2bbc96eSHarald Freudenberger rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 1623f2bbc96eSHarald Freudenberger apqns, &nr_apqns); 1624f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 1625f2bbc96eSHarald Freudenberger kfree(kkey); 1626f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1627f2bbc96eSHarald Freudenberger kfree(apqns); 1628f2bbc96eSHarald Freudenberger break; 1629f2bbc96eSHarald Freudenberger } 1630f2bbc96eSHarald Freudenberger if (!rc && kak.apqns) { 1631f2bbc96eSHarald Freudenberger if (nr_apqns > kak.apqn_entries) { 1632f2bbc96eSHarald Freudenberger kfree(apqns); 1633f2bbc96eSHarald Freudenberger return -EINVAL; 1634f2bbc96eSHarald Freudenberger } 1635f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1636f2bbc96eSHarald Freudenberger if (len) { 1637f2bbc96eSHarald Freudenberger if (copy_to_user(kak.apqns, apqns, len)) { 1638f2bbc96eSHarald Freudenberger kfree(apqns); 1639f2bbc96eSHarald Freudenberger return -EFAULT; 1640f2bbc96eSHarald Freudenberger } 1641f2bbc96eSHarald Freudenberger } 1642f2bbc96eSHarald Freudenberger } 1643f2bbc96eSHarald Freudenberger kak.apqn_entries = nr_apqns; 1644f2bbc96eSHarald Freudenberger if (copy_to_user(uak, &kak, sizeof(kak))) 1645f2bbc96eSHarald Freudenberger rc = -EFAULT; 1646f2bbc96eSHarald Freudenberger kfree(apqns); 1647f2bbc96eSHarald Freudenberger break; 1648f2bbc96eSHarald Freudenberger } 1649f2bbc96eSHarald Freudenberger case PKEY_APQNS4KT: { 1650f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype __user *uat = (void __user *)arg; 1651f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 165246a29b03SHarald Freudenberger struct pkey_apqns4keytype kat; 1653f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1654f2bbc96eSHarald Freudenberger 1655f2bbc96eSHarald Freudenberger if (copy_from_user(&kat, uat, sizeof(kat))) 1656f2bbc96eSHarald Freudenberger return -EFAULT; 1657f2bbc96eSHarald Freudenberger nr_apqns = kat.apqn_entries; 1658f2bbc96eSHarald Freudenberger if (nr_apqns) { 1659f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1660f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1661f2bbc96eSHarald Freudenberger GFP_KERNEL); 1662f2bbc96eSHarald Freudenberger if (!apqns) 1663f2bbc96eSHarald Freudenberger return -ENOMEM; 1664f2bbc96eSHarald Freudenberger } 1665f2bbc96eSHarald Freudenberger rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 1666f2bbc96eSHarald Freudenberger kat.flags, apqns, &nr_apqns); 1667f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 1668f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1669f2bbc96eSHarald Freudenberger kfree(apqns); 1670f2bbc96eSHarald Freudenberger break; 1671f2bbc96eSHarald Freudenberger } 1672f2bbc96eSHarald Freudenberger if (!rc && kat.apqns) { 1673f2bbc96eSHarald Freudenberger if (nr_apqns > kat.apqn_entries) { 1674f2bbc96eSHarald Freudenberger kfree(apqns); 1675f2bbc96eSHarald Freudenberger return -EINVAL; 1676f2bbc96eSHarald Freudenberger } 1677f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1678f2bbc96eSHarald Freudenberger if (len) { 1679f2bbc96eSHarald Freudenberger if (copy_to_user(kat.apqns, apqns, len)) { 1680f2bbc96eSHarald Freudenberger kfree(apqns); 1681f2bbc96eSHarald Freudenberger return -EFAULT; 1682f2bbc96eSHarald Freudenberger } 1683f2bbc96eSHarald Freudenberger } 1684f2bbc96eSHarald Freudenberger } 1685f2bbc96eSHarald Freudenberger kat.apqn_entries = nr_apqns; 1686f2bbc96eSHarald Freudenberger if (copy_to_user(uat, &kat, sizeof(kat))) 1687f2bbc96eSHarald Freudenberger rc = -EFAULT; 1688f2bbc96eSHarald Freudenberger kfree(apqns); 1689f2bbc96eSHarald Freudenberger break; 1690f2bbc96eSHarald Freudenberger } 1691fa6999e3SHarald Freudenberger case PKEY_KBLOB2PROTK3: { 1692fa6999e3SHarald Freudenberger struct pkey_kblob2pkey3 __user *utp = (void __user *)arg; 1693fa6999e3SHarald Freudenberger u32 protkeylen = PROTKEYBLOBBUFSIZE; 169446a29b03SHarald Freudenberger struct pkey_apqn *apqns = NULL; 169546a29b03SHarald Freudenberger struct pkey_kblob2pkey3 ktp; 1696fa6999e3SHarald Freudenberger u8 *kkey, *protkey; 1697fa6999e3SHarald Freudenberger 1698fa6999e3SHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1699fa6999e3SHarald Freudenberger return -EFAULT; 1700fa6999e3SHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1701fa6999e3SHarald Freudenberger if (IS_ERR(apqns)) 1702fa6999e3SHarald Freudenberger return PTR_ERR(apqns); 1703fa6999e3SHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1704fa6999e3SHarald Freudenberger if (IS_ERR(kkey)) { 1705fa6999e3SHarald Freudenberger kfree(apqns); 1706fa6999e3SHarald Freudenberger return PTR_ERR(kkey); 1707fa6999e3SHarald Freudenberger } 1708fa6999e3SHarald Freudenberger protkey = kmalloc(protkeylen, GFP_KERNEL); 1709fa6999e3SHarald Freudenberger if (!protkey) { 1710fa6999e3SHarald Freudenberger kfree(apqns); 1711fa6999e3SHarald Freudenberger kfree(kkey); 1712fa6999e3SHarald Freudenberger return -ENOMEM; 1713fa6999e3SHarald Freudenberger } 1714f370f45cSHarald Freudenberger rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, 1715f370f45cSHarald Freudenberger kkey, ktp.keylen, 1716f370f45cSHarald Freudenberger protkey, &protkeylen, &ktp.pkeytype); 1717fa6999e3SHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); 1718fa6999e3SHarald Freudenberger kfree(apqns); 1719844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1720fa6999e3SHarald Freudenberger kfree(kkey); 1721fa6999e3SHarald Freudenberger if (rc) { 1722fa6999e3SHarald Freudenberger kfree(protkey); 1723fa6999e3SHarald Freudenberger break; 1724fa6999e3SHarald Freudenberger } 1725fa6999e3SHarald Freudenberger if (ktp.pkey && ktp.pkeylen) { 1726fa6999e3SHarald Freudenberger if (protkeylen > ktp.pkeylen) { 1727fa6999e3SHarald Freudenberger kfree(protkey); 1728fa6999e3SHarald Freudenberger return -EINVAL; 1729fa6999e3SHarald Freudenberger } 1730fa6999e3SHarald Freudenberger if (copy_to_user(ktp.pkey, protkey, protkeylen)) { 1731fa6999e3SHarald Freudenberger kfree(protkey); 1732fa6999e3SHarald Freudenberger return -EFAULT; 1733fa6999e3SHarald Freudenberger } 1734fa6999e3SHarald Freudenberger } 1735fa6999e3SHarald Freudenberger kfree(protkey); 1736fa6999e3SHarald Freudenberger ktp.pkeylen = protkeylen; 1737fa6999e3SHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1738fa6999e3SHarald Freudenberger return -EFAULT; 1739fa6999e3SHarald Freudenberger break; 1740fa6999e3SHarald Freudenberger } 1741e80d4af0SHarald Freudenberger default: 1742e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1743e80d4af0SHarald Freudenberger return -ENOTTY; 1744e80d4af0SHarald Freudenberger } 1745e80d4af0SHarald Freudenberger 1746e80d4af0SHarald Freudenberger return rc; 1747e80d4af0SHarald Freudenberger } 1748e80d4af0SHarald Freudenberger 1749e80d4af0SHarald Freudenberger /* 1750e80d4af0SHarald Freudenberger * Sysfs and file io operations 1751e80d4af0SHarald Freudenberger */ 1752d632c047SIngo Franzki 1753d632c047SIngo Franzki /* 1754d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1755d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1756d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1757d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1758d632c047SIngo Franzki */ 1759d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1760d632c047SIngo Franzki loff_t off, size_t count) 1761d632c047SIngo Franzki { 1762d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1763d632c047SIngo Franzki struct pkey_protkey protkey; 1764d632c047SIngo Franzki int rc; 1765d632c047SIngo Franzki 1766d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1767d632c047SIngo Franzki return -EINVAL; 1768d632c047SIngo Franzki if (is_xts) 1769d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1770d632c047SIngo Franzki return -EINVAL; 1771d632c047SIngo Franzki 1772d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1773d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1774d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1775d632c047SIngo Franzki protkeytoken.keytype = keytype; 1776d632c047SIngo Franzki 1777f370f45cSHarald Freudenberger protkey.len = sizeof(protkey.protkey); 1778f370f45cSHarald Freudenberger rc = pkey_genprotkey(protkeytoken.keytype, 1779f370f45cSHarald Freudenberger protkey.protkey, &protkey.len, &protkey.type); 1780d632c047SIngo Franzki if (rc) 1781d632c047SIngo Franzki return rc; 1782d632c047SIngo Franzki 1783d632c047SIngo Franzki protkeytoken.len = protkey.len; 1784d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1785d632c047SIngo Franzki 1786d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1787d632c047SIngo Franzki 1788d632c047SIngo Franzki if (is_xts) { 1789f370f45cSHarald Freudenberger /* xts needs a second protected key, reuse protkey struct */ 1790f370f45cSHarald Freudenberger protkey.len = sizeof(protkey.protkey); 1791f370f45cSHarald Freudenberger rc = pkey_genprotkey(protkeytoken.keytype, 1792f370f45cSHarald Freudenberger protkey.protkey, &protkey.len, &protkey.type); 1793d632c047SIngo Franzki if (rc) 1794d632c047SIngo Franzki return rc; 1795d632c047SIngo Franzki 1796d632c047SIngo Franzki protkeytoken.len = protkey.len; 1797d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1798d632c047SIngo Franzki 1799d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1800d632c047SIngo Franzki sizeof(protkeytoken)); 1801d632c047SIngo Franzki 1802d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1803d632c047SIngo Franzki } 1804d632c047SIngo Franzki 1805d632c047SIngo Franzki return sizeof(protkeytoken); 1806d632c047SIngo Franzki } 1807d632c047SIngo Franzki 1808d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1809d632c047SIngo Franzki struct kobject *kobj, 1810d632c047SIngo Franzki struct bin_attribute *attr, 1811d632c047SIngo Franzki char *buf, loff_t off, 1812d632c047SIngo Franzki size_t count) 1813d632c047SIngo Franzki { 1814d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1815d632c047SIngo Franzki off, count); 1816d632c047SIngo Franzki } 1817d632c047SIngo Franzki 1818d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1819d632c047SIngo Franzki struct kobject *kobj, 1820d632c047SIngo Franzki struct bin_attribute *attr, 1821d632c047SIngo Franzki char *buf, loff_t off, 1822d632c047SIngo Franzki size_t count) 1823d632c047SIngo Franzki { 1824d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1825d632c047SIngo Franzki off, count); 1826d632c047SIngo Franzki } 1827d632c047SIngo Franzki 1828d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1829d632c047SIngo Franzki struct kobject *kobj, 1830d632c047SIngo Franzki struct bin_attribute *attr, 1831d632c047SIngo Franzki char *buf, loff_t off, 1832d632c047SIngo Franzki size_t count) 1833d632c047SIngo Franzki { 1834d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1835d632c047SIngo Franzki off, count); 1836d632c047SIngo Franzki } 1837d632c047SIngo Franzki 1838d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1839d632c047SIngo Franzki struct kobject *kobj, 1840d632c047SIngo Franzki struct bin_attribute *attr, 1841d632c047SIngo Franzki char *buf, loff_t off, 1842d632c047SIngo Franzki size_t count) 1843d632c047SIngo Franzki { 1844d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1845d632c047SIngo Franzki off, count); 1846d632c047SIngo Franzki } 1847d632c047SIngo Franzki 1848d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1849d632c047SIngo Franzki struct kobject *kobj, 1850d632c047SIngo Franzki struct bin_attribute *attr, 1851d632c047SIngo Franzki char *buf, loff_t off, 1852d632c047SIngo Franzki size_t count) 1853d632c047SIngo Franzki { 1854d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1855d632c047SIngo Franzki off, count); 1856d632c047SIngo Franzki } 1857d632c047SIngo Franzki 1858d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1859d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1860d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1861d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1862d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1863d632c047SIngo Franzki 1864d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1865d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1866d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1867d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1868d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1869d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1870d632c047SIngo Franzki NULL 1871d632c047SIngo Franzki }; 1872d632c047SIngo Franzki 1873d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1874d632c047SIngo Franzki .name = "protkey", 1875d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1876d632c047SIngo Franzki }; 1877d632c047SIngo Franzki 1878af504452SIngo Franzki /* 1879af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1880af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1881af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1882af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1883af504452SIngo Franzki */ 1884af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1885af504452SIngo Franzki loff_t off, size_t count) 1886af504452SIngo Franzki { 1887efc598e6SHarald Freudenberger struct pkey_seckey *seckey = (struct pkey_seckey *)buf; 188846a29b03SHarald Freudenberger int rc; 1889af504452SIngo Franzki 1890af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1891af504452SIngo Franzki return -EINVAL; 1892af504452SIngo Franzki if (is_xts) 1893af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1894af504452SIngo Franzki return -EINVAL; 1895af504452SIngo Franzki 1896efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1897af504452SIngo Franzki if (rc) 1898af504452SIngo Franzki return rc; 1899af504452SIngo Franzki 1900af504452SIngo Franzki if (is_xts) { 1901efc598e6SHarald Freudenberger seckey++; 1902efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1903af504452SIngo Franzki if (rc) 1904af504452SIngo Franzki return rc; 1905af504452SIngo Franzki 1906af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1907af504452SIngo Franzki } 1908af504452SIngo Franzki 1909af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1910af504452SIngo Franzki } 1911af504452SIngo Franzki 1912af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1913af504452SIngo Franzki struct kobject *kobj, 1914af504452SIngo Franzki struct bin_attribute *attr, 1915af504452SIngo Franzki char *buf, loff_t off, 1916af504452SIngo Franzki size_t count) 1917af504452SIngo Franzki { 1918af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1919af504452SIngo Franzki off, count); 1920af504452SIngo Franzki } 1921af504452SIngo Franzki 1922af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1923af504452SIngo Franzki struct kobject *kobj, 1924af504452SIngo Franzki struct bin_attribute *attr, 1925af504452SIngo Franzki char *buf, loff_t off, 1926af504452SIngo Franzki size_t count) 1927af504452SIngo Franzki { 1928af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1929af504452SIngo Franzki off, count); 1930af504452SIngo Franzki } 1931af504452SIngo Franzki 1932af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1933af504452SIngo Franzki struct kobject *kobj, 1934af504452SIngo Franzki struct bin_attribute *attr, 1935af504452SIngo Franzki char *buf, loff_t off, 1936af504452SIngo Franzki size_t count) 1937af504452SIngo Franzki { 1938af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1939af504452SIngo Franzki off, count); 1940af504452SIngo Franzki } 1941af504452SIngo Franzki 1942af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1943af504452SIngo Franzki struct kobject *kobj, 1944af504452SIngo Franzki struct bin_attribute *attr, 1945af504452SIngo Franzki char *buf, loff_t off, 1946af504452SIngo Franzki size_t count) 1947af504452SIngo Franzki { 1948af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1949af504452SIngo Franzki off, count); 1950af504452SIngo Franzki } 1951af504452SIngo Franzki 1952af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1953af504452SIngo Franzki struct kobject *kobj, 1954af504452SIngo Franzki struct bin_attribute *attr, 1955af504452SIngo Franzki char *buf, loff_t off, 1956af504452SIngo Franzki size_t count) 1957af504452SIngo Franzki { 1958af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1959af504452SIngo Franzki off, count); 1960af504452SIngo Franzki } 1961af504452SIngo Franzki 1962af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1963af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1964af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1965af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1966af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1967af504452SIngo Franzki 1968af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1969af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1970af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1971af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1972af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1973af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1974af504452SIngo Franzki NULL 1975af504452SIngo Franzki }; 1976af504452SIngo Franzki 1977af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1978af504452SIngo Franzki .name = "ccadata", 1979af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1980af504452SIngo Franzki }; 1981af504452SIngo Franzki 1982f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) 1983f71fee27SIngo Franzki 1984f71fee27SIngo Franzki /* 1985f71fee27SIngo Franzki * Sysfs attribute read function for all secure key ccacipher binary attributes. 1986f71fee27SIngo Franzki * The implementation can not deal with partial reads, because a new random 1987f71fee27SIngo Franzki * secure key blob is generated with each read. In case of partial reads 1988f71fee27SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1989f71fee27SIngo Franzki */ 1990f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, 1991f71fee27SIngo Franzki bool is_xts, char *buf, loff_t off, 1992f71fee27SIngo Franzki size_t count) 1993f71fee27SIngo Franzki { 199455d0a513SHarald Freudenberger size_t keysize = CCACIPHERTOKENSIZE; 199546a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 199646a29b03SHarald Freudenberger int i, rc, card, dom; 1997f71fee27SIngo Franzki 1998f71fee27SIngo Franzki if (off != 0 || count < CCACIPHERTOKENSIZE) 1999f71fee27SIngo Franzki return -EINVAL; 2000f71fee27SIngo Franzki if (is_xts) 2001f71fee27SIngo Franzki if (count < 2 * CCACIPHERTOKENSIZE) 2002f71fee27SIngo Franzki return -EINVAL; 2003f71fee27SIngo Franzki 200455d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 200555d0a513SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 200632ca04bbSHarald Freudenberger ZCRYPT_CEX6, 0, 0, 0, 0); 2007f71fee27SIngo Franzki if (rc) 2008f71fee27SIngo Franzki return rc; 200955d0a513SHarald Freudenberger 201055d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 201155d0a513SHarald Freudenberger 201255d0a513SHarald Freudenberger /* simple try all apqns from the list */ 201355d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 201455d0a513SHarald Freudenberger card = apqns[i] >> 16; 201555d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 201655d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 201755d0a513SHarald Freudenberger if (rc == 0) 201855d0a513SHarald Freudenberger break; 201955d0a513SHarald Freudenberger } 202055d0a513SHarald Freudenberger if (rc) 202155d0a513SHarald Freudenberger return rc; 2022f71fee27SIngo Franzki 2023f71fee27SIngo Franzki if (is_xts) { 2024f71fee27SIngo Franzki keysize = CCACIPHERTOKENSIZE; 202555d0a513SHarald Freudenberger buf += CCACIPHERTOKENSIZE; 202655d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 202755d0a513SHarald Freudenberger if (rc == 0) 2028f71fee27SIngo Franzki return 2 * CCACIPHERTOKENSIZE; 2029f71fee27SIngo Franzki } 2030f71fee27SIngo Franzki 2031f71fee27SIngo Franzki return CCACIPHERTOKENSIZE; 2032f71fee27SIngo Franzki } 2033f71fee27SIngo Franzki 2034f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp, 2035f71fee27SIngo Franzki struct kobject *kobj, 2036f71fee27SIngo Franzki struct bin_attribute *attr, 2037f71fee27SIngo Franzki char *buf, loff_t off, 2038f71fee27SIngo Franzki size_t count) 2039f71fee27SIngo Franzki { 2040f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 2041f71fee27SIngo Franzki off, count); 2042f71fee27SIngo Franzki } 2043f71fee27SIngo Franzki 2044f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp, 2045f71fee27SIngo Franzki struct kobject *kobj, 2046f71fee27SIngo Franzki struct bin_attribute *attr, 2047f71fee27SIngo Franzki char *buf, loff_t off, 2048f71fee27SIngo Franzki size_t count) 2049f71fee27SIngo Franzki { 2050f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 2051f71fee27SIngo Franzki off, count); 2052f71fee27SIngo Franzki } 2053f71fee27SIngo Franzki 2054f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp, 2055f71fee27SIngo Franzki struct kobject *kobj, 2056f71fee27SIngo Franzki struct bin_attribute *attr, 2057f71fee27SIngo Franzki char *buf, loff_t off, 2058f71fee27SIngo Franzki size_t count) 2059f71fee27SIngo Franzki { 2060f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 2061f71fee27SIngo Franzki off, count); 2062f71fee27SIngo Franzki } 2063f71fee27SIngo Franzki 2064f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp, 2065f71fee27SIngo Franzki struct kobject *kobj, 2066f71fee27SIngo Franzki struct bin_attribute *attr, 2067f71fee27SIngo Franzki char *buf, loff_t off, 2068f71fee27SIngo Franzki size_t count) 2069f71fee27SIngo Franzki { 2070f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 2071f71fee27SIngo Franzki off, count); 2072f71fee27SIngo Franzki } 2073f71fee27SIngo Franzki 2074f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp, 2075f71fee27SIngo Franzki struct kobject *kobj, 2076f71fee27SIngo Franzki struct bin_attribute *attr, 2077f71fee27SIngo Franzki char *buf, loff_t off, 2078f71fee27SIngo Franzki size_t count) 2079f71fee27SIngo Franzki { 2080f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 2081f71fee27SIngo Franzki off, count); 2082f71fee27SIngo Franzki } 2083f71fee27SIngo Franzki 2084f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); 2085f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); 2086f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); 2087f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); 2088f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); 2089f71fee27SIngo Franzki 2090f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = { 2091f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128, 2092f71fee27SIngo Franzki &bin_attr_ccacipher_aes_192, 2093f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256, 2094f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128_xts, 2095f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256_xts, 2096f71fee27SIngo Franzki NULL 2097f71fee27SIngo Franzki }; 2098f71fee27SIngo Franzki 2099f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = { 2100f71fee27SIngo Franzki .name = "ccacipher", 2101f71fee27SIngo Franzki .bin_attrs = ccacipher_attrs, 2102f71fee27SIngo Franzki }; 2103f71fee27SIngo Franzki 210455d0a513SHarald Freudenberger /* 210555d0a513SHarald Freudenberger * Sysfs attribute read function for all ep11 aes key binary attributes. 210655d0a513SHarald Freudenberger * The implementation can not deal with partial reads, because a new random 210755d0a513SHarald Freudenberger * secure key blob is generated with each read. In case of partial reads 210855d0a513SHarald Freudenberger * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 210955d0a513SHarald Freudenberger * This function and the sysfs attributes using it provide EP11 key blobs 211055d0a513SHarald Freudenberger * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently 211155d0a513SHarald Freudenberger * 320 bytes. 211255d0a513SHarald Freudenberger */ 211355d0a513SHarald Freudenberger static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, 211455d0a513SHarald Freudenberger bool is_xts, char *buf, loff_t off, 211555d0a513SHarald Freudenberger size_t count) 211655d0a513SHarald Freudenberger { 211755d0a513SHarald Freudenberger size_t keysize = MAXEP11AESKEYBLOBSIZE; 211846a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 211946a29b03SHarald Freudenberger int i, rc, card, dom; 212055d0a513SHarald Freudenberger 212155d0a513SHarald Freudenberger if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) 212255d0a513SHarald Freudenberger return -EINVAL; 212355d0a513SHarald Freudenberger if (is_xts) 212455d0a513SHarald Freudenberger if (count < 2 * MAXEP11AESKEYBLOBSIZE) 212555d0a513SHarald Freudenberger return -EINVAL; 212655d0a513SHarald Freudenberger 212755d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 212855d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 212955d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 213055d0a513SHarald Freudenberger if (rc) 213155d0a513SHarald Freudenberger return rc; 213255d0a513SHarald Freudenberger 213355d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 213455d0a513SHarald Freudenberger 213555d0a513SHarald Freudenberger /* simple try all apqns from the list */ 213655d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 213755d0a513SHarald Freudenberger card = apqns[i] >> 16; 213855d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 2139*fb249ce7SHolger Dengler rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize, 2140*fb249ce7SHolger Dengler PKEY_TYPE_EP11); 214155d0a513SHarald Freudenberger if (rc == 0) 214255d0a513SHarald Freudenberger break; 214355d0a513SHarald Freudenberger } 214455d0a513SHarald Freudenberger if (rc) 214555d0a513SHarald Freudenberger return rc; 214655d0a513SHarald Freudenberger 214755d0a513SHarald Freudenberger if (is_xts) { 214855d0a513SHarald Freudenberger keysize = MAXEP11AESKEYBLOBSIZE; 214955d0a513SHarald Freudenberger buf += MAXEP11AESKEYBLOBSIZE; 2150*fb249ce7SHolger Dengler rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize, 2151*fb249ce7SHolger Dengler PKEY_TYPE_EP11); 215255d0a513SHarald Freudenberger if (rc == 0) 215355d0a513SHarald Freudenberger return 2 * MAXEP11AESKEYBLOBSIZE; 215455d0a513SHarald Freudenberger } 215555d0a513SHarald Freudenberger 215655d0a513SHarald Freudenberger return MAXEP11AESKEYBLOBSIZE; 215755d0a513SHarald Freudenberger } 215855d0a513SHarald Freudenberger 215955d0a513SHarald Freudenberger static ssize_t ep11_aes_128_read(struct file *filp, 216055d0a513SHarald Freudenberger struct kobject *kobj, 216155d0a513SHarald Freudenberger struct bin_attribute *attr, 216255d0a513SHarald Freudenberger char *buf, loff_t off, 216355d0a513SHarald Freudenberger size_t count) 216455d0a513SHarald Freudenberger { 216555d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 216655d0a513SHarald Freudenberger off, count); 216755d0a513SHarald Freudenberger } 216855d0a513SHarald Freudenberger 216955d0a513SHarald Freudenberger static ssize_t ep11_aes_192_read(struct file *filp, 217055d0a513SHarald Freudenberger struct kobject *kobj, 217155d0a513SHarald Freudenberger struct bin_attribute *attr, 217255d0a513SHarald Freudenberger char *buf, loff_t off, 217355d0a513SHarald Freudenberger size_t count) 217455d0a513SHarald Freudenberger { 217555d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 217655d0a513SHarald Freudenberger off, count); 217755d0a513SHarald Freudenberger } 217855d0a513SHarald Freudenberger 217955d0a513SHarald Freudenberger static ssize_t ep11_aes_256_read(struct file *filp, 218055d0a513SHarald Freudenberger struct kobject *kobj, 218155d0a513SHarald Freudenberger struct bin_attribute *attr, 218255d0a513SHarald Freudenberger char *buf, loff_t off, 218355d0a513SHarald Freudenberger size_t count) 218455d0a513SHarald Freudenberger { 218555d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 218655d0a513SHarald Freudenberger off, count); 218755d0a513SHarald Freudenberger } 218855d0a513SHarald Freudenberger 218955d0a513SHarald Freudenberger static ssize_t ep11_aes_128_xts_read(struct file *filp, 219055d0a513SHarald Freudenberger struct kobject *kobj, 219155d0a513SHarald Freudenberger struct bin_attribute *attr, 219255d0a513SHarald Freudenberger char *buf, loff_t off, 219355d0a513SHarald Freudenberger size_t count) 219455d0a513SHarald Freudenberger { 219555d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 219655d0a513SHarald Freudenberger off, count); 219755d0a513SHarald Freudenberger } 219855d0a513SHarald Freudenberger 219955d0a513SHarald Freudenberger static ssize_t ep11_aes_256_xts_read(struct file *filp, 220055d0a513SHarald Freudenberger struct kobject *kobj, 220155d0a513SHarald Freudenberger struct bin_attribute *attr, 220255d0a513SHarald Freudenberger char *buf, loff_t off, 220355d0a513SHarald Freudenberger size_t count) 220455d0a513SHarald Freudenberger { 220555d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 220655d0a513SHarald Freudenberger off, count); 220755d0a513SHarald Freudenberger } 220855d0a513SHarald Freudenberger 220955d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE); 221055d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE); 221155d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE); 221255d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE); 221355d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE); 221455d0a513SHarald Freudenberger 221555d0a513SHarald Freudenberger static struct bin_attribute *ep11_attrs[] = { 221655d0a513SHarald Freudenberger &bin_attr_ep11_aes_128, 221755d0a513SHarald Freudenberger &bin_attr_ep11_aes_192, 221855d0a513SHarald Freudenberger &bin_attr_ep11_aes_256, 221955d0a513SHarald Freudenberger &bin_attr_ep11_aes_128_xts, 222055d0a513SHarald Freudenberger &bin_attr_ep11_aes_256_xts, 222155d0a513SHarald Freudenberger NULL 222255d0a513SHarald Freudenberger }; 222355d0a513SHarald Freudenberger 222455d0a513SHarald Freudenberger static struct attribute_group ep11_attr_group = { 222555d0a513SHarald Freudenberger .name = "ep11", 222655d0a513SHarald Freudenberger .bin_attrs = ep11_attrs, 222755d0a513SHarald Freudenberger }; 222855d0a513SHarald Freudenberger 2229d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 2230d632c047SIngo Franzki &protkey_attr_group, 2231af504452SIngo Franzki &ccadata_attr_group, 2232f71fee27SIngo Franzki &ccacipher_attr_group, 223355d0a513SHarald Freudenberger &ep11_attr_group, 2234d632c047SIngo Franzki NULL, 2235d632c047SIngo Franzki }; 2236d632c047SIngo Franzki 2237e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 2238e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 2239e80d4af0SHarald Freudenberger .open = nonseekable_open, 2240e80d4af0SHarald Freudenberger .llseek = no_llseek, 2241e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 2242e80d4af0SHarald Freudenberger }; 2243e80d4af0SHarald Freudenberger 2244e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 2245e80d4af0SHarald Freudenberger .name = "pkey", 2246e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 2247e80d4af0SHarald Freudenberger .mode = 0666, 2248e80d4af0SHarald Freudenberger .fops = &pkey_fops, 2249d632c047SIngo Franzki .groups = pkey_attr_groups, 2250e80d4af0SHarald Freudenberger }; 2251e80d4af0SHarald Freudenberger 2252e80d4af0SHarald Freudenberger /* 2253e80d4af0SHarald Freudenberger * Module init 2254e80d4af0SHarald Freudenberger */ 2255cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 2256e80d4af0SHarald Freudenberger { 22575b35047eSHarald Freudenberger cpacf_mask_t func_mask; 2258e80d4af0SHarald Freudenberger 2259f822ad2cSHarald Freudenberger /* 2260f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 2261f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 2262f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 2263f822ad2cSHarald Freudenberger * are able to work with protected keys. 2264f822ad2cSHarald Freudenberger */ 22655b35047eSHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &func_mask)) 226658443b67SDavid Hildenbrand return -ENODEV; 2267e80d4af0SHarald Freudenberger 2268cb26b9ffSIngo Franzki /* check for kmc instructions available */ 22695b35047eSHarald Freudenberger if (!cpacf_query(CPACF_KMC, &func_mask)) 227058443b67SDavid Hildenbrand return -ENODEV; 22715b35047eSHarald Freudenberger if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) || 22725b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) || 22735b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256)) 227458443b67SDavid Hildenbrand return -ENODEV; 2275cb26b9ffSIngo Franzki 2276e80d4af0SHarald Freudenberger pkey_debug_init(); 2277e80d4af0SHarald Freudenberger 2278e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 2279e80d4af0SHarald Freudenberger } 2280e80d4af0SHarald Freudenberger 2281e80d4af0SHarald Freudenberger /* 2282e80d4af0SHarald Freudenberger * Module exit 2283e80d4af0SHarald Freudenberger */ 2284e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 2285e80d4af0SHarald Freudenberger { 2286e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 2287e80d4af0SHarald Freudenberger pkey_debug_exit(); 2288e80d4af0SHarald Freudenberger } 2289e80d4af0SHarald Freudenberger 22900a5f9b38SHeiko Carstens module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init); 2291e80d4af0SHarald Freudenberger module_exit(pkey_exit); 2292