1812141a9SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2e80d4af0SHarald Freudenberger /* 3e80d4af0SHarald Freudenberger * pkey device driver 4e80d4af0SHarald Freudenberger * 5*9e436c19SHarald Freudenberger * Copyright IBM Corp. 2017, 2023 6*9e436c19SHarald 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 */ 36*9e436c19SHarald 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) */ 77*9e436c19SHarald Freudenberger struct clearkeytoken { 78888edbc4SHarald Freudenberger u8 type; /* 0x00 for PAES specific key tokens */ 79888edbc4SHarald Freudenberger u8 res0[3]; 80*9e436c19SHarald Freudenberger u8 version; /* 0x02 for clear key token */ 81888edbc4SHarald Freudenberger u8 res1[3]; 82*9e436c19SHarald 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 87*9e436c19SHarald Freudenberger /* helper function which translates the PKEY_KEYTYPE_AES_* to their keysize */ 88*9e436c19SHarald Freudenberger static inline u32 pkey_keytype_aes_to_size(u32 keytype) 89*9e436c19SHarald Freudenberger { 90*9e436c19SHarald Freudenberger switch (keytype) { 91*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 92*9e436c19SHarald Freudenberger return 16; 93*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 94*9e436c19SHarald Freudenberger return 24; 95*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 96*9e436c19SHarald Freudenberger return 32; 97*9e436c19SHarald Freudenberger default: 98*9e436c19SHarald Freudenberger return 0; 99*9e436c19SHarald Freudenberger } 100*9e436c19SHarald Freudenberger } 101*9e436c19SHarald 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 111*9e436c19SHarald Freudenberger u8 paramblock[112]; 112*9e436c19SHarald Freudenberger u32 pkeytype; 11346a29b03SHarald Freudenberger int keysize; 11446a29b03SHarald Freudenberger long fc; 115e80d4af0SHarald Freudenberger 116e80d4af0SHarald Freudenberger switch (keytype) { 117e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 118*9e436c19SHarald Freudenberger /* 16 byte key, 32 byte aes wkvp, total 48 bytes */ 119e80d4af0SHarald Freudenberger keysize = 16; 120*9e436c19SHarald Freudenberger pkeytype = keytype; 121e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 122e80d4af0SHarald Freudenberger break; 123e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 124*9e436c19SHarald Freudenberger /* 24 byte key, 32 byte aes wkvp, total 56 bytes */ 125e80d4af0SHarald Freudenberger keysize = 24; 126*9e436c19SHarald Freudenberger pkeytype = keytype; 127e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 128e80d4af0SHarald Freudenberger break; 129e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 130*9e436c19SHarald Freudenberger /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ 131e80d4af0SHarald Freudenberger keysize = 32; 132*9e436c19SHarald Freudenberger pkeytype = keytype; 133e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 134e80d4af0SHarald Freudenberger break; 135*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P256: 136*9e436c19SHarald Freudenberger /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ 137*9e436c19SHarald Freudenberger keysize = 32; 138*9e436c19SHarald Freudenberger pkeytype = PKEY_KEYTYPE_ECC; 139*9e436c19SHarald Freudenberger fc = CPACF_PCKMO_ENC_ECC_P256_KEY; 140*9e436c19SHarald Freudenberger break; 141*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P384: 142*9e436c19SHarald Freudenberger /* 48 byte key, 32 byte aes wkvp, total 80 bytes */ 143*9e436c19SHarald Freudenberger keysize = 48; 144*9e436c19SHarald Freudenberger pkeytype = PKEY_KEYTYPE_ECC; 145*9e436c19SHarald Freudenberger fc = CPACF_PCKMO_ENC_ECC_P384_KEY; 146*9e436c19SHarald Freudenberger break; 147*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P521: 148*9e436c19SHarald Freudenberger /* 80 byte key, 32 byte aes wkvp, total 112 bytes */ 149*9e436c19SHarald Freudenberger keysize = 80; 150*9e436c19SHarald Freudenberger pkeytype = PKEY_KEYTYPE_ECC; 151*9e436c19SHarald Freudenberger fc = CPACF_PCKMO_ENC_ECC_P521_KEY; 152*9e436c19SHarald Freudenberger break; 153*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED25519: 154*9e436c19SHarald Freudenberger /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ 155*9e436c19SHarald Freudenberger keysize = 32; 156*9e436c19SHarald Freudenberger pkeytype = PKEY_KEYTYPE_ECC; 157*9e436c19SHarald Freudenberger fc = CPACF_PCKMO_ENC_ECC_ED25519_KEY; 158*9e436c19SHarald Freudenberger break; 159*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED448: 160*9e436c19SHarald Freudenberger /* 64 byte key, 32 byte aes wkvp, total 96 bytes */ 161*9e436c19SHarald Freudenberger keysize = 64; 162*9e436c19SHarald Freudenberger pkeytype = PKEY_KEYTYPE_ECC; 163*9e436c19SHarald Freudenberger fc = CPACF_PCKMO_ENC_ECC_ED448_KEY; 164*9e436c19SHarald 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); 199*9e436c19SHarald 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 376*9e436c19SHarald Freudenberger keysize = pkey_keytype_aes_to_size(keytype); 377*9e436c19SHarald 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 452*9e436c19SHarald Freudenberger /* Helper for pkey_nonccatok2pkey, handles aes clear key token */ 453*9e436c19SHarald Freudenberger static int nonccatokaes2pkey(const struct clearkeytoken *t, 454*9e436c19SHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 455*9e436c19SHarald Freudenberger { 456*9e436c19SHarald Freudenberger size_t tmpbuflen = max_t(size_t, SECKEYBLOBSIZE, MAXEP11AESKEYBLOBSIZE); 457*9e436c19SHarald Freudenberger u8 *tmpbuf = NULL; 458*9e436c19SHarald Freudenberger u32 keysize; 459*9e436c19SHarald Freudenberger int rc; 460*9e436c19SHarald Freudenberger 461*9e436c19SHarald Freudenberger keysize = pkey_keytype_aes_to_size(t->keytype); 462*9e436c19SHarald Freudenberger if (!keysize) { 463*9e436c19SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", 464*9e436c19SHarald Freudenberger __func__, t->keytype); 465*9e436c19SHarald Freudenberger return -EINVAL; 466*9e436c19SHarald Freudenberger } 467*9e436c19SHarald Freudenberger if (t->len != keysize) { 468*9e436c19SHarald Freudenberger DEBUG_ERR("%s non clear key aes token: invalid key len %u\n", 469*9e436c19SHarald Freudenberger __func__, t->len); 470*9e436c19SHarald Freudenberger return -EINVAL; 471*9e436c19SHarald Freudenberger } 472*9e436c19SHarald Freudenberger 473*9e436c19SHarald Freudenberger /* try direct way with the PCKMO instruction */ 474*9e436c19SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, t->clearkey, 475*9e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 476*9e436c19SHarald Freudenberger if (!rc) 477*9e436c19SHarald Freudenberger goto out; 478*9e436c19SHarald Freudenberger 479*9e436c19SHarald Freudenberger /* PCKMO failed, so try the CCA secure key way */ 480*9e436c19SHarald Freudenberger tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 481*9e436c19SHarald Freudenberger if (!tmpbuf) 482*9e436c19SHarald Freudenberger return -ENOMEM; 483*9e436c19SHarald Freudenberger zcrypt_wait_api_operational(); 484*9e436c19SHarald Freudenberger rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, t->clearkey, tmpbuf); 485*9e436c19SHarald Freudenberger if (rc) 486*9e436c19SHarald Freudenberger goto try_via_ep11; 487*9e436c19SHarald Freudenberger rc = pkey_skey2pkey(tmpbuf, 488*9e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 489*9e436c19SHarald Freudenberger if (!rc) 490*9e436c19SHarald Freudenberger goto out; 491*9e436c19SHarald Freudenberger 492*9e436c19SHarald Freudenberger try_via_ep11: 493*9e436c19SHarald Freudenberger /* if the CCA way also failed, let's try via EP11 */ 494*9e436c19SHarald Freudenberger rc = pkey_clr2ep11key(t->clearkey, t->len, 495*9e436c19SHarald Freudenberger tmpbuf, &tmpbuflen); 496*9e436c19SHarald Freudenberger if (rc) 497*9e436c19SHarald Freudenberger goto failure; 498*9e436c19SHarald Freudenberger rc = pkey_ep11key2pkey(tmpbuf, 499*9e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 500*9e436c19SHarald Freudenberger if (!rc) 501*9e436c19SHarald Freudenberger goto out; 502*9e436c19SHarald Freudenberger 503*9e436c19SHarald Freudenberger failure: 504*9e436c19SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", __func__); 505*9e436c19SHarald Freudenberger 506*9e436c19SHarald Freudenberger out: 507*9e436c19SHarald Freudenberger kfree(tmpbuf); 508*9e436c19SHarald Freudenberger return rc; 509*9e436c19SHarald Freudenberger } 510*9e436c19SHarald Freudenberger 511*9e436c19SHarald Freudenberger /* Helper for pkey_nonccatok2pkey, handles ecc clear key token */ 512*9e436c19SHarald Freudenberger static int nonccatokecc2pkey(const struct clearkeytoken *t, 513*9e436c19SHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 514*9e436c19SHarald Freudenberger { 515*9e436c19SHarald Freudenberger u32 keylen; 516*9e436c19SHarald Freudenberger int rc; 517*9e436c19SHarald Freudenberger 518*9e436c19SHarald Freudenberger switch (t->keytype) { 519*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P256: 520*9e436c19SHarald Freudenberger keylen = 32; 521*9e436c19SHarald Freudenberger break; 522*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P384: 523*9e436c19SHarald Freudenberger keylen = 48; 524*9e436c19SHarald Freudenberger break; 525*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P521: 526*9e436c19SHarald Freudenberger keylen = 80; 527*9e436c19SHarald Freudenberger break; 528*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED25519: 529*9e436c19SHarald Freudenberger keylen = 32; 530*9e436c19SHarald Freudenberger break; 531*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED448: 532*9e436c19SHarald Freudenberger keylen = 64; 533*9e436c19SHarald Freudenberger break; 534*9e436c19SHarald Freudenberger default: 535*9e436c19SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", 536*9e436c19SHarald Freudenberger __func__, t->keytype); 537*9e436c19SHarald Freudenberger return -EINVAL; 538*9e436c19SHarald Freudenberger } 539*9e436c19SHarald Freudenberger 540*9e436c19SHarald Freudenberger if (t->len != keylen) { 541*9e436c19SHarald Freudenberger DEBUG_ERR("%s non clear key ecc token: invalid key len %u\n", 542*9e436c19SHarald Freudenberger __func__, t->len); 543*9e436c19SHarald Freudenberger return -EINVAL; 544*9e436c19SHarald Freudenberger } 545*9e436c19SHarald Freudenberger 546*9e436c19SHarald Freudenberger /* only one path possible: via PCKMO instruction */ 547*9e436c19SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, t->clearkey, 548*9e436c19SHarald Freudenberger protkey, protkeylen, protkeytype); 549*9e436c19SHarald Freudenberger if (rc) { 550*9e436c19SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", 551*9e436c19SHarald Freudenberger __func__); 552*9e436c19SHarald Freudenberger } 553*9e436c19SHarald Freudenberger 554*9e436c19SHarald Freudenberger return rc; 555*9e436c19SHarald Freudenberger } 556*9e436c19SHarald 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: { 582*9e436c19SHarald Freudenberger struct clearkeytoken *t = (struct clearkeytoken *)key; 583fb1136d6SIngo Franzki 584*9e436c19SHarald Freudenberger if (keylen < sizeof(struct clearkeytoken) || 585*9e436c19SHarald Freudenberger keylen != sizeof(*t) + t->len) 586888edbc4SHarald Freudenberger goto out; 587*9e436c19SHarald Freudenberger switch (t->keytype) { 588*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 589*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 590*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 591*9e436c19SHarald Freudenberger rc = nonccatokaes2pkey(t, protkey, 592*9e436c19SHarald Freudenberger protkeylen, protkeytype); 593*9e436c19SHarald Freudenberger break; 594*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P256: 595*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P384: 596*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_P521: 597*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED25519: 598*9e436c19SHarald Freudenberger case PKEY_KEYTYPE_ECC_ED448: 599*9e436c19SHarald Freudenberger rc = nonccatokecc2pkey(t, protkey, 600*9e436c19SHarald Freudenberger protkeylen, protkeytype); 601*9e436c19SHarald Freudenberger break; 602*9e436c19SHarald Freudenberger default: 603*9e436c19SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported non cca clear key type %u\n", 604*9e436c19SHarald Freudenberger __func__, t->keytype); 605*9e436c19SHarald 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; 716f2bbc96eSHarald Freudenberger default: 717f2bbc96eSHarald Freudenberger return -EINVAL; 718f2bbc96eSHarald Freudenberger } 719f2bbc96eSHarald Freudenberger switch (ksize) { 720f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 721f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 722f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 723f2bbc96eSHarald Freudenberger break; 724f2bbc96eSHarald Freudenberger default: 725f2bbc96eSHarald Freudenberger return -EINVAL; 726f2bbc96eSHarald Freudenberger } 727f2bbc96eSHarald Freudenberger 728f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 729f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 730f2bbc96eSHarald Freudenberger card = apqns[i].card; 731f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 73255d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 73355d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, ksize, kflags, 73455d0a513SHarald Freudenberger keybuf, keybufsize); 73555d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 736f2bbc96eSHarald Freudenberger rc = cca_genseckey(card, dom, ksize, keybuf); 737f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 7382004b57cSHarald Freudenberger } else { 7392004b57cSHarald Freudenberger /* TOKVER_CCA_VLSC */ 740f2bbc96eSHarald Freudenberger rc = cca_gencipherkey(card, dom, ksize, kflags, 741f2bbc96eSHarald Freudenberger keybuf, keybufsize); 7422004b57cSHarald Freudenberger } 743f2bbc96eSHarald Freudenberger if (rc == 0) 744f2bbc96eSHarald Freudenberger break; 745f2bbc96eSHarald Freudenberger } 746f2bbc96eSHarald Freudenberger 747f2bbc96eSHarald Freudenberger return rc; 748f2bbc96eSHarald Freudenberger } 749f2bbc96eSHarald Freudenberger 750f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 751f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 752f2bbc96eSHarald Freudenberger u32 kflags, const u8 *clrkey, 753f2bbc96eSHarald Freudenberger u8 *keybuf, size_t *keybufsize) 754f2bbc96eSHarald Freudenberger { 755f2bbc96eSHarald Freudenberger int i, card, dom, rc; 756f2bbc96eSHarald Freudenberger 757f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 758f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 759f2bbc96eSHarald Freudenberger return -EINVAL; 760f2bbc96eSHarald Freudenberger 761f2bbc96eSHarald Freudenberger /* check key type and size */ 762f2bbc96eSHarald Freudenberger switch (ktype) { 763f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 764f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 765f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 766f2bbc96eSHarald Freudenberger return -EINVAL; 767f2bbc96eSHarald Freudenberger break; 76855d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 76955d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 77055d0a513SHarald Freudenberger return -EINVAL; 77155d0a513SHarald Freudenberger break; 772f2bbc96eSHarald Freudenberger default: 773f2bbc96eSHarald Freudenberger return -EINVAL; 774f2bbc96eSHarald Freudenberger } 775f2bbc96eSHarald Freudenberger switch (ksize) { 776f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 777f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 778f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 779f2bbc96eSHarald Freudenberger break; 780f2bbc96eSHarald Freudenberger default: 781f2bbc96eSHarald Freudenberger return -EINVAL; 782f2bbc96eSHarald Freudenberger } 783f2bbc96eSHarald Freudenberger 78443cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 78543cb5a7cSHarald Freudenberger 786f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 787f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 788f2bbc96eSHarald Freudenberger card = apqns[i].card; 789f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 79055d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 79155d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, ksize, kflags, 79255d0a513SHarald Freudenberger clrkey, keybuf, keybufsize); 79355d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 794f2bbc96eSHarald Freudenberger rc = cca_clr2seckey(card, dom, ksize, 795f2bbc96eSHarald Freudenberger clrkey, keybuf); 796f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 7972004b57cSHarald Freudenberger } else { 7982004b57cSHarald Freudenberger /* TOKVER_CCA_VLSC */ 799f2bbc96eSHarald Freudenberger rc = cca_clr2cipherkey(card, dom, ksize, kflags, 800f2bbc96eSHarald Freudenberger clrkey, keybuf, keybufsize); 8012004b57cSHarald Freudenberger } 802f2bbc96eSHarald Freudenberger if (rc == 0) 803f2bbc96eSHarald Freudenberger break; 804f2bbc96eSHarald Freudenberger } 805f2bbc96eSHarald Freudenberger 806f2bbc96eSHarald Freudenberger return rc; 807f2bbc96eSHarald Freudenberger } 808f2bbc96eSHarald Freudenberger 809f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen, 810f2bbc96eSHarald Freudenberger u16 *cardnr, u16 *domain, 811f2bbc96eSHarald Freudenberger enum pkey_key_type *ktype, 812f2bbc96eSHarald Freudenberger enum pkey_key_size *ksize, u32 *flags) 813f2bbc96eSHarald Freudenberger { 814f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 81546a29b03SHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 81646a29b03SHarald Freudenberger int rc; 817f2bbc96eSHarald Freudenberger 81855d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 819f2bbc96eSHarald Freudenberger return -EINVAL; 820f2bbc96eSHarald Freudenberger 8212004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 8222004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 823f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 824f2bbc96eSHarald Freudenberger 825f2bbc96eSHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 826f2bbc96eSHarald Freudenberger if (rc) 827f2bbc96eSHarald Freudenberger goto out; 828f2bbc96eSHarald Freudenberger if (ktype) 829f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_DATA; 830f2bbc96eSHarald Freudenberger if (ksize) 831f2bbc96eSHarald Freudenberger *ksize = (enum pkey_key_size)t->bitsize; 832f2bbc96eSHarald Freudenberger 833f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 83432ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); 835f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 836f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 837f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 838f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 839f2bbc96eSHarald Freudenberger *cardnr, *domain, 84032ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, 84132ca04bbSHarald Freudenberger 0, t->mkvp, 1); 842f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 843f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 844f2bbc96eSHarald Freudenberger } 845f2bbc96eSHarald Freudenberger if (rc) 846f2bbc96eSHarald Freudenberger goto out; 847f2bbc96eSHarald Freudenberger 848f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 849f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 850f2bbc96eSHarald Freudenberger 8512004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 8522004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 853f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 854f2bbc96eSHarald Freudenberger 855f2bbc96eSHarald Freudenberger rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 856f2bbc96eSHarald Freudenberger if (rc) 857f2bbc96eSHarald Freudenberger goto out; 858f2bbc96eSHarald Freudenberger if (ktype) 859f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_CIPHER; 860f2bbc96eSHarald Freudenberger if (ksize) { 861f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_UNKNOWN; 862f2bbc96eSHarald Freudenberger if (!t->plfver && t->wpllen == 512) 863f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_128; 864f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 865f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_192; 866f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 867f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_256; 868f2bbc96eSHarald Freudenberger } 869f2bbc96eSHarald Freudenberger 870f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 87132ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); 872f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 873f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 874f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 875f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 876f2bbc96eSHarald Freudenberger *cardnr, *domain, 87732ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, 87832ca04bbSHarald Freudenberger 0, t->mkvp0, 1); 879f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 880f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 881f2bbc96eSHarald Freudenberger } 882f2bbc96eSHarald Freudenberger if (rc) 883f2bbc96eSHarald Freudenberger goto out; 884f2bbc96eSHarald Freudenberger 885f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 886f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 887f2bbc96eSHarald Freudenberger 8882004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 8892004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES) { 89055d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 89155d0a513SHarald Freudenberger 892fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 89355d0a513SHarald Freudenberger if (rc) 89455d0a513SHarald Freudenberger goto out; 89555d0a513SHarald Freudenberger if (ktype) 89655d0a513SHarald Freudenberger *ktype = PKEY_TYPE_EP11; 89755d0a513SHarald Freudenberger if (ksize) 89855d0a513SHarald Freudenberger *ksize = kb->head.keybitlen; 89955d0a513SHarald Freudenberger 90055d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 90155d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 90255d0a513SHarald Freudenberger if (rc) 90355d0a513SHarald Freudenberger goto out; 90455d0a513SHarald Freudenberger 90555d0a513SHarald Freudenberger if (flags) 90655d0a513SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 90755d0a513SHarald Freudenberger 90855d0a513SHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 90955d0a513SHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 91055d0a513SHarald Freudenberger 9112004b57cSHarald Freudenberger } else { 912f2bbc96eSHarald Freudenberger rc = -EINVAL; 9132004b57cSHarald Freudenberger } 914f2bbc96eSHarald Freudenberger 915f2bbc96eSHarald Freudenberger out: 916f2bbc96eSHarald Freudenberger kfree(_apqns); 917f2bbc96eSHarald Freudenberger return rc; 918f2bbc96eSHarald Freudenberger } 919f2bbc96eSHarald Freudenberger 920f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 921f2bbc96eSHarald Freudenberger const u8 *key, size_t keylen, 922f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 923f2bbc96eSHarald Freudenberger { 924f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 92546a29b03SHarald Freudenberger int i, card, dom, rc; 926f2bbc96eSHarald Freudenberger 927f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 928f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 929f2bbc96eSHarald Freudenberger return -EINVAL; 930f2bbc96eSHarald Freudenberger 931fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 932fb1136d6SIngo Franzki return -EINVAL; 933fb1136d6SIngo Franzki 93455d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL) { 93555d0a513SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 936f2bbc96eSHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 937f2bbc96eSHarald Freudenberger return -EINVAL; 938f2bbc96eSHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 939f2bbc96eSHarald Freudenberger return -EINVAL; 94055d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 941f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 942f2bbc96eSHarald Freudenberger return -EINVAL; 943f2bbc96eSHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 944f2bbc96eSHarald Freudenberger return -EINVAL; 94555d0a513SHarald Freudenberger } else { 946f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 947f2bbc96eSHarald Freudenberger __func__, hdr->version); 948fb1136d6SIngo Franzki return -EINVAL; 949fb1136d6SIngo Franzki } 95055d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 95155d0a513SHarald Freudenberger if (hdr->version == TOKVER_EP11_AES) { 95255d0a513SHarald Freudenberger if (keylen < sizeof(struct ep11keyblob)) 95355d0a513SHarald Freudenberger return -EINVAL; 954fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 95555d0a513SHarald Freudenberger return -EINVAL; 95655d0a513SHarald Freudenberger } else { 957f370f45cSHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, 958f370f45cSHarald Freudenberger protkey, protkeylen, 959f370f45cSHarald Freudenberger protkeytype); 96055d0a513SHarald Freudenberger } 96155d0a513SHarald Freudenberger } else { 962f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 963f2bbc96eSHarald Freudenberger __func__, hdr->type); 964f2bbc96eSHarald Freudenberger return -EINVAL; 965fb1136d6SIngo Franzki } 966f2bbc96eSHarald Freudenberger 96743cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 96843cb5a7cSHarald Freudenberger 969f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 970f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 971f2bbc96eSHarald Freudenberger card = apqns[i].card; 972f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 9732004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 9742004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 975f370f45cSHarald Freudenberger rc = cca_sec2protkey(card, dom, key, 976f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 9772004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 9782004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 979f370f45cSHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, 980f370f45cSHarald Freudenberger protkey, protkeylen, 981f370f45cSHarald Freudenberger protkeytype); 9822004b57cSHarald Freudenberger } else { 9832004b57cSHarald Freudenberger /* EP11 AES secure key blob */ 98455d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 98555d0a513SHarald Freudenberger 986fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 987f370f45cSHarald Freudenberger protkey, protkeylen, 988f370f45cSHarald Freudenberger protkeytype); 98955d0a513SHarald Freudenberger } 990f2bbc96eSHarald Freudenberger if (rc == 0) 991f2bbc96eSHarald Freudenberger break; 992f2bbc96eSHarald Freudenberger } 993f2bbc96eSHarald Freudenberger 994f2bbc96eSHarald Freudenberger return rc; 995f2bbc96eSHarald Freudenberger } 996f2bbc96eSHarald Freudenberger 997f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 998f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 999f2bbc96eSHarald Freudenberger { 1000f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 100146a29b03SHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 100246a29b03SHarald Freudenberger int rc; 1003f2bbc96eSHarald Freudenberger 100455d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || flags == 0) 1005f2bbc96eSHarald Freudenberger return -EINVAL; 1006f2bbc96eSHarald Freudenberger 100743cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 100843cb5a7cSHarald Freudenberger 10092004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 10102004b57cSHarald Freudenberger (hdr->version == TOKVER_EP11_AES_WITH_HEADER || 10112004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && 10122004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1013fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) 1014fa6999e3SHarald Freudenberger (key + sizeof(struct ep11kblob_header)); 101546a29b03SHarald Freudenberger int minhwtype = 0, api = 0; 1016fa6999e3SHarald Freudenberger 1017fa6999e3SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 1018fa6999e3SHarald Freudenberger return -EINVAL; 1019fa6999e3SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 1020fa6999e3SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 1021fa6999e3SHarald Freudenberger api = EP11_API_V; 1022fa6999e3SHarald Freudenberger } 1023fa6999e3SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1024fa6999e3SHarald Freudenberger minhwtype, api, kb->wkvp); 1025fa6999e3SHarald Freudenberger if (rc) 1026fa6999e3SHarald Freudenberger goto out; 10272004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 10282004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 10292004b57cSHarald Freudenberger is_ep11_keyblob(key)) { 103055d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 103146a29b03SHarald Freudenberger int minhwtype = 0, api = 0; 103255d0a513SHarald Freudenberger 103355d0a513SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 103455d0a513SHarald Freudenberger return -EINVAL; 103555d0a513SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 103655d0a513SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 103755d0a513SHarald Freudenberger api = EP11_API_V; 103855d0a513SHarald Freudenberger } 103955d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 104055d0a513SHarald Freudenberger minhwtype, api, kb->wkvp); 104155d0a513SHarald Freudenberger if (rc) 104255d0a513SHarald Freudenberger goto out; 104355d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 1044f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 104546a29b03SHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 1046f2bbc96eSHarald Freudenberger 1047f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 1048f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 1049f2bbc96eSHarald Freudenberger 1050f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1051f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp; 1052f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1053f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp; 105455d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1055f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 1056f2bbc96eSHarald Freudenberger 1057f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 1058f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1059f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp0; 1060f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1061f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp0; 106255d0a513SHarald Freudenberger } else { 106355d0a513SHarald Freudenberger /* unknown cca internal token type */ 106455d0a513SHarald Freudenberger return -EINVAL; 1065f2bbc96eSHarald Freudenberger } 1066f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 106732ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 106832ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1069f2bbc96eSHarald Freudenberger if (rc) 1070f2bbc96eSHarald Freudenberger goto out; 1071fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1072fa6999e3SHarald Freudenberger struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; 107346a29b03SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1074fa6999e3SHarald Freudenberger 1075fa6999e3SHarald Freudenberger if (t->secid == 0x20) { 1076fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1077fa6999e3SHarald Freudenberger cur_mkvp = t->mkvp; 1078fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1079fa6999e3SHarald Freudenberger old_mkvp = t->mkvp; 1080fa6999e3SHarald Freudenberger } else { 1081fa6999e3SHarald Freudenberger /* unknown cca internal 2 token type */ 1082fa6999e3SHarald Freudenberger return -EINVAL; 1083fa6999e3SHarald Freudenberger } 1084fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1085fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 1086fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 1087fa6999e3SHarald Freudenberger if (rc) 1088fa6999e3SHarald Freudenberger goto out; 10892004b57cSHarald Freudenberger } else { 109055d0a513SHarald Freudenberger return -EINVAL; 10912004b57cSHarald Freudenberger } 109255d0a513SHarald Freudenberger 1093f2bbc96eSHarald Freudenberger if (apqns) { 1094f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 1095f2bbc96eSHarald Freudenberger rc = -ENOSPC; 1096f2bbc96eSHarald Freudenberger else 1097f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 1098f2bbc96eSHarald Freudenberger } 1099f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 1100f2bbc96eSHarald Freudenberger 1101f2bbc96eSHarald Freudenberger out: 1102f2bbc96eSHarald Freudenberger kfree(_apqns); 1103f2bbc96eSHarald Freudenberger return rc; 1104f2bbc96eSHarald Freudenberger } 1105f2bbc96eSHarald Freudenberger 1106f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype, 1107f2bbc96eSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 1108f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 1109f2bbc96eSHarald Freudenberger { 1110f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 111146a29b03SHarald Freudenberger int rc; 1112f2bbc96eSHarald Freudenberger 111343cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 111443cb5a7cSHarald Freudenberger 1115f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 1116f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1117f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 1118f2bbc96eSHarald Freudenberger 1119f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1120f2bbc96eSHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 1121f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1122f2bbc96eSHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 1123f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 1124f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 1125f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 112632ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 112732ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1128f2bbc96eSHarald Freudenberger if (rc) 1129f2bbc96eSHarald Freudenberger goto out; 1130fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_ECC) { 1131fa6999e3SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1132fa6999e3SHarald Freudenberger 1133fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1134fa6999e3SHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 1135fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1136fa6999e3SHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 1137fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1138fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 1139fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 1140fa6999e3SHarald Freudenberger if (rc) 1141fa6999e3SHarald Freudenberger goto out; 1142fa6999e3SHarald Freudenberger 1143fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_EP11 || 1144fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_AES || 1145fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_ECC) { 114655d0a513SHarald Freudenberger u8 *wkvp = NULL; 114755d0a513SHarald Freudenberger 114855d0a513SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 114955d0a513SHarald Freudenberger wkvp = cur_mkvp; 115055d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 115155d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, wkvp); 115255d0a513SHarald Freudenberger if (rc) 115355d0a513SHarald Freudenberger goto out; 115455d0a513SHarald Freudenberger 11552004b57cSHarald Freudenberger } else { 115655d0a513SHarald Freudenberger return -EINVAL; 11572004b57cSHarald Freudenberger } 115855d0a513SHarald Freudenberger 1159f2bbc96eSHarald Freudenberger if (apqns) { 1160f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 1161f2bbc96eSHarald Freudenberger rc = -ENOSPC; 1162f2bbc96eSHarald Freudenberger else 1163f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 1164f2bbc96eSHarald Freudenberger } 1165f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 1166f2bbc96eSHarald Freudenberger 1167f2bbc96eSHarald Freudenberger out: 1168f2bbc96eSHarald Freudenberger kfree(_apqns); 1169f2bbc96eSHarald Freudenberger return rc; 1170f2bbc96eSHarald Freudenberger } 1171fb1136d6SIngo Franzki 1172fa6999e3SHarald Freudenberger static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, 1173f370f45cSHarald Freudenberger const u8 *key, size_t keylen, 1174f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 1175fa6999e3SHarald Freudenberger { 1176fa6999e3SHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 117746a29b03SHarald Freudenberger int i, card, dom, rc; 1178fa6999e3SHarald Freudenberger 1179fa6999e3SHarald Freudenberger /* check for at least one apqn given */ 1180fa6999e3SHarald Freudenberger if (!apqns || !nr_apqns) 1181fa6999e3SHarald Freudenberger return -EINVAL; 1182fa6999e3SHarald Freudenberger 1183fa6999e3SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 1184fa6999e3SHarald Freudenberger return -EINVAL; 1185fa6999e3SHarald Freudenberger 11862004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 11872004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES_WITH_HEADER && 11882004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1189fa6999e3SHarald Freudenberger /* EP11 AES key blob with header */ 1190fa6999e3SHarald Freudenberger if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1)) 1191fa6999e3SHarald Freudenberger return -EINVAL; 11922004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 11932004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER && 11942004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1195fa6999e3SHarald Freudenberger /* EP11 ECC key blob with header */ 1196fa6999e3SHarald Freudenberger if (ep11_check_ecc_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_AES && 12002004b57cSHarald Freudenberger is_ep11_keyblob(key)) { 1201fa6999e3SHarald Freudenberger /* EP11 AES key blob with header in session field */ 1202fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 1203fa6999e3SHarald Freudenberger return -EINVAL; 1204fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 1205fa6999e3SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 1206fa6999e3SHarald Freudenberger /* CCA AES data key */ 1207fa6999e3SHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 1208fa6999e3SHarald Freudenberger return -EINVAL; 1209fa6999e3SHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 1210fa6999e3SHarald Freudenberger return -EINVAL; 1211fa6999e3SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1212fa6999e3SHarald Freudenberger /* CCA AES cipher key */ 1213fa6999e3SHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 1214fa6999e3SHarald Freudenberger return -EINVAL; 1215fa6999e3SHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 1216fa6999e3SHarald Freudenberger return -EINVAL; 1217fa6999e3SHarald Freudenberger } else { 1218fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 1219fa6999e3SHarald Freudenberger __func__, hdr->version); 1220fa6999e3SHarald Freudenberger return -EINVAL; 1221fa6999e3SHarald Freudenberger } 1222fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1223fa6999e3SHarald Freudenberger /* CCA ECC (private) key */ 1224fa6999e3SHarald Freudenberger if (keylen < sizeof(struct eccprivkeytoken)) 1225fa6999e3SHarald Freudenberger return -EINVAL; 1226fa6999e3SHarald Freudenberger if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) 1227fa6999e3SHarald Freudenberger return -EINVAL; 1228fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 1229f370f45cSHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, 1230f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 1231fa6999e3SHarald Freudenberger } else { 1232fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 1233fa6999e3SHarald Freudenberger __func__, hdr->type); 1234fa6999e3SHarald Freudenberger return -EINVAL; 1235fa6999e3SHarald Freudenberger } 1236fa6999e3SHarald Freudenberger 1237fa6999e3SHarald Freudenberger /* simple try all apqns from the list */ 1238fa6999e3SHarald Freudenberger for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 1239fa6999e3SHarald Freudenberger card = apqns[i].card; 1240fa6999e3SHarald Freudenberger dom = apqns[i].domain; 12412004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 12422004b57cSHarald Freudenberger (hdr->version == TOKVER_EP11_AES_WITH_HEADER || 12432004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && 12442004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) 1245fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1246fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 12472004b57cSHarald Freudenberger else if (hdr->type == TOKTYPE_NON_CCA && 12482004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 12492004b57cSHarald Freudenberger is_ep11_keyblob(key)) 1250fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1251fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 1252fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1253fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_AES) 1254fa6999e3SHarald Freudenberger rc = cca_sec2protkey(card, dom, key, protkey, 1255fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1256fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1257fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) 1258fa6999e3SHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, protkey, 1259fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1260fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) 1261fa6999e3SHarald Freudenberger rc = cca_ecc2protkey(card, dom, key, protkey, 1262fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1263fa6999e3SHarald Freudenberger else 1264fa6999e3SHarald Freudenberger return -EINVAL; 1265fa6999e3SHarald Freudenberger } 1266fa6999e3SHarald Freudenberger 1267fa6999e3SHarald Freudenberger return rc; 1268fa6999e3SHarald Freudenberger } 1269fa6999e3SHarald Freudenberger 1270fb1136d6SIngo Franzki /* 1271e80d4af0SHarald Freudenberger * File io functions 1272e80d4af0SHarald Freudenberger */ 1273e80d4af0SHarald Freudenberger 1274f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen) 1275f2bbc96eSHarald Freudenberger { 1276*9e436c19SHarald Freudenberger if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE) 1277f2bbc96eSHarald Freudenberger return ERR_PTR(-EINVAL); 1278f2bbc96eSHarald Freudenberger 12798b57e7c8SMarkus Elfring return memdup_user(ukey, keylen); 1280f2bbc96eSHarald Freudenberger } 1281f2bbc96eSHarald Freudenberger 1282f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 1283f2bbc96eSHarald Freudenberger { 12848b57e7c8SMarkus Elfring if (!uapqns || nr_apqns == 0) 12858b57e7c8SMarkus Elfring return NULL; 1286f2bbc96eSHarald Freudenberger 12878b57e7c8SMarkus Elfring return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); 1288f2bbc96eSHarald Freudenberger } 1289f2bbc96eSHarald Freudenberger 1290e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 1291e80d4af0SHarald Freudenberger unsigned long arg) 1292e80d4af0SHarald Freudenberger { 1293e80d4af0SHarald Freudenberger int rc; 1294e80d4af0SHarald Freudenberger 1295e80d4af0SHarald Freudenberger switch (cmd) { 1296e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1297e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *)arg; 1298e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1299e80d4af0SHarald Freudenberger 1300e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1301e80d4af0SHarald Freudenberger return -EFAULT; 1302efc598e6SHarald Freudenberger rc = cca_genseckey(kgs.cardnr, kgs.domain, 1303efc598e6SHarald Freudenberger kgs.keytype, kgs.seckey.seckey); 1304efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 1305e80d4af0SHarald Freudenberger if (rc) 1306e80d4af0SHarald Freudenberger break; 1307e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1308e80d4af0SHarald Freudenberger return -EFAULT; 1309e80d4af0SHarald Freudenberger break; 1310e80d4af0SHarald Freudenberger } 1311e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1312e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *)arg; 1313e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1314e80d4af0SHarald Freudenberger 1315e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1316e80d4af0SHarald Freudenberger return -EFAULT; 1317efc598e6SHarald Freudenberger rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1318efc598e6SHarald Freudenberger kcs.clrkey.clrkey, kcs.seckey.seckey); 1319efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 1320e80d4af0SHarald Freudenberger if (rc) 1321e80d4af0SHarald Freudenberger break; 1322e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1323e80d4af0SHarald Freudenberger return -EFAULT; 1324e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1325e80d4af0SHarald Freudenberger break; 1326e80d4af0SHarald Freudenberger } 1327e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1328e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *)arg; 1329e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1330e80d4af0SHarald Freudenberger 1331e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1332e80d4af0SHarald Freudenberger return -EFAULT; 1333f370f45cSHarald Freudenberger ksp.protkey.len = sizeof(ksp.protkey.protkey); 1334efc598e6SHarald Freudenberger rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 1335efc598e6SHarald Freudenberger ksp.seckey.seckey, ksp.protkey.protkey, 1336aab73d27SHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1337efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 1338e80d4af0SHarald Freudenberger if (rc) 1339e80d4af0SHarald Freudenberger break; 1340e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1341e80d4af0SHarald Freudenberger return -EFAULT; 1342e80d4af0SHarald Freudenberger break; 1343e80d4af0SHarald Freudenberger } 1344e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1345e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *)arg; 1346e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1347e80d4af0SHarald Freudenberger 1348e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1349e80d4af0SHarald Freudenberger return -EFAULT; 1350f370f45cSHarald Freudenberger kcp.protkey.len = sizeof(kcp.protkey.protkey); 1351f370f45cSHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey, 1352f370f45cSHarald Freudenberger kcp.protkey.protkey, 1353f370f45cSHarald Freudenberger &kcp.protkey.len, &kcp.protkey.type); 1354ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1355e80d4af0SHarald Freudenberger if (rc) 1356e80d4af0SHarald Freudenberger break; 1357e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1358e80d4af0SHarald Freudenberger return -EFAULT; 1359e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1360e80d4af0SHarald Freudenberger break; 1361e80d4af0SHarald Freudenberger } 1362e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1363e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *)arg; 1364e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1365e80d4af0SHarald Freudenberger 1366e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1367e80d4af0SHarald Freudenberger return -EFAULT; 1368efc598e6SHarald Freudenberger rc = cca_findcard(kfc.seckey.seckey, 1369e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1370efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 1371efc598e6SHarald Freudenberger if (rc < 0) 1372e80d4af0SHarald Freudenberger break; 1373e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1374e80d4af0SHarald Freudenberger return -EFAULT; 1375e80d4af0SHarald Freudenberger break; 1376e80d4af0SHarald Freudenberger } 1377e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1378e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *)arg; 1379e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1380e80d4af0SHarald Freudenberger 1381e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1382e80d4af0SHarald Freudenberger return -EFAULT; 1383f370f45cSHarald Freudenberger ksp.protkey.len = sizeof(ksp.protkey.protkey); 1384f370f45cSHarald Freudenberger rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey, 1385f370f45cSHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1386ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1387e80d4af0SHarald Freudenberger if (rc) 1388e80d4af0SHarald Freudenberger break; 1389e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1390e80d4af0SHarald Freudenberger return -EFAULT; 1391e80d4af0SHarald Freudenberger break; 1392e80d4af0SHarald Freudenberger } 1393e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1394e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *)arg; 1395e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1396e61a6134SHarald Freudenberger 1397e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1398e61a6134SHarald Freudenberger return -EFAULT; 1399e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1400e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1401ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1402e61a6134SHarald Freudenberger if (rc) 1403e61a6134SHarald Freudenberger break; 1404e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1405e61a6134SHarald Freudenberger return -EFAULT; 1406e61a6134SHarald Freudenberger break; 1407e61a6134SHarald Freudenberger } 1408a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1409a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *)arg; 1410a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1411a45a5c7dSIngo Franzki 1412a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1413a45a5c7dSIngo Franzki return -EFAULT; 1414f370f45cSHarald Freudenberger kgp.protkey.len = sizeof(kgp.protkey.protkey); 1415f370f45cSHarald Freudenberger rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey, 1416f370f45cSHarald Freudenberger &kgp.protkey.len, &kgp.protkey.type); 1417a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1418a45a5c7dSIngo Franzki if (rc) 1419a45a5c7dSIngo Franzki break; 1420a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1421a45a5c7dSIngo Franzki return -EFAULT; 1422a45a5c7dSIngo Franzki break; 1423a45a5c7dSIngo Franzki } 1424cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 1425cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *)arg; 1426cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 1427cb26b9ffSIngo Franzki 1428cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 1429cb26b9ffSIngo Franzki return -EFAULT; 1430f370f45cSHarald Freudenberger rc = pkey_verifyprotkey(kvp.protkey.protkey, 1431f370f45cSHarald Freudenberger kvp.protkey.len, kvp.protkey.type); 1432cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 1433cb26b9ffSIngo Franzki break; 1434cb26b9ffSIngo Franzki } 1435fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 1436fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *)arg; 1437fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 1438183cb469SHarald Freudenberger u8 *kkey; 1439fb1136d6SIngo Franzki 1440fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 1441fb1136d6SIngo Franzki return -EFAULT; 1442f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1443f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1444f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1445f370f45cSHarald Freudenberger ktp.protkey.len = sizeof(ktp.protkey.protkey); 1446f370f45cSHarald Freudenberger rc = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey, 1447f370f45cSHarald Freudenberger &ktp.protkey.len, &ktp.protkey.type); 1448fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 1449844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1450fb1136d6SIngo Franzki kfree(kkey); 1451fb1136d6SIngo Franzki if (rc) 1452fb1136d6SIngo Franzki break; 1453fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 1454fb1136d6SIngo Franzki return -EFAULT; 1455fb1136d6SIngo Franzki break; 1456fb1136d6SIngo Franzki } 1457f2bbc96eSHarald Freudenberger case PKEY_GENSECK2: { 1458f2bbc96eSHarald Freudenberger struct pkey_genseck2 __user *ugs = (void __user *)arg; 145946a29b03SHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1460f2bbc96eSHarald Freudenberger struct pkey_genseck2 kgs; 1461f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1462f2bbc96eSHarald Freudenberger u8 *kkey; 1463f2bbc96eSHarald Freudenberger 1464f2bbc96eSHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1465f2bbc96eSHarald Freudenberger return -EFAULT; 1466f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 1467f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1468f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1469f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1470f2bbc96eSHarald Freudenberger if (!kkey) { 1471f2bbc96eSHarald Freudenberger kfree(apqns); 1472f2bbc96eSHarald Freudenberger return -ENOMEM; 1473f2bbc96eSHarald Freudenberger } 1474f2bbc96eSHarald Freudenberger rc = pkey_genseckey2(apqns, kgs.apqn_entries, 1475f2bbc96eSHarald Freudenberger kgs.type, kgs.size, kgs.keygenflags, 1476f2bbc96eSHarald Freudenberger kkey, &klen); 1477f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 1478f2bbc96eSHarald Freudenberger kfree(apqns); 1479f2bbc96eSHarald Freudenberger if (rc) { 1480f2bbc96eSHarald Freudenberger kfree(kkey); 1481f2bbc96eSHarald Freudenberger break; 1482f2bbc96eSHarald Freudenberger } 1483f2bbc96eSHarald Freudenberger if (kgs.key) { 1484f2bbc96eSHarald Freudenberger if (kgs.keylen < klen) { 1485f2bbc96eSHarald Freudenberger kfree(kkey); 1486f2bbc96eSHarald Freudenberger return -EINVAL; 1487f2bbc96eSHarald Freudenberger } 1488f2bbc96eSHarald Freudenberger if (copy_to_user(kgs.key, kkey, klen)) { 1489f2bbc96eSHarald Freudenberger kfree(kkey); 1490f2bbc96eSHarald Freudenberger return -EFAULT; 1491f2bbc96eSHarald Freudenberger } 1492f2bbc96eSHarald Freudenberger } 1493f2bbc96eSHarald Freudenberger kgs.keylen = klen; 1494f2bbc96eSHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1495f2bbc96eSHarald Freudenberger rc = -EFAULT; 1496f2bbc96eSHarald Freudenberger kfree(kkey); 1497f2bbc96eSHarald Freudenberger break; 1498f2bbc96eSHarald Freudenberger } 1499f2bbc96eSHarald Freudenberger case PKEY_CLR2SECK2: { 1500f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 __user *ucs = (void __user *)arg; 150146a29b03SHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1502f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 kcs; 1503f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1504f2bbc96eSHarald Freudenberger u8 *kkey; 1505f2bbc96eSHarald Freudenberger 1506f2bbc96eSHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1507f2bbc96eSHarald Freudenberger return -EFAULT; 1508f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 1509f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1510f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1511f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1512f2bbc96eSHarald Freudenberger if (!kkey) { 1513f2bbc96eSHarald Freudenberger kfree(apqns); 1514f2bbc96eSHarald Freudenberger return -ENOMEM; 1515f2bbc96eSHarald Freudenberger } 1516f2bbc96eSHarald Freudenberger rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 1517f2bbc96eSHarald Freudenberger kcs.type, kcs.size, kcs.keygenflags, 1518f2bbc96eSHarald Freudenberger kcs.clrkey.clrkey, kkey, &klen); 1519f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 1520f2bbc96eSHarald Freudenberger kfree(apqns); 1521f2bbc96eSHarald Freudenberger if (rc) { 1522f2bbc96eSHarald Freudenberger kfree(kkey); 1523f2bbc96eSHarald Freudenberger break; 1524f2bbc96eSHarald Freudenberger } 1525f2bbc96eSHarald Freudenberger if (kcs.key) { 1526f2bbc96eSHarald Freudenberger if (kcs.keylen < klen) { 1527f2bbc96eSHarald Freudenberger kfree(kkey); 1528f2bbc96eSHarald Freudenberger return -EINVAL; 1529f2bbc96eSHarald Freudenberger } 1530f2bbc96eSHarald Freudenberger if (copy_to_user(kcs.key, kkey, klen)) { 1531f2bbc96eSHarald Freudenberger kfree(kkey); 1532f2bbc96eSHarald Freudenberger return -EFAULT; 1533f2bbc96eSHarald Freudenberger } 1534f2bbc96eSHarald Freudenberger } 1535f2bbc96eSHarald Freudenberger kcs.keylen = klen; 1536f2bbc96eSHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1537f2bbc96eSHarald Freudenberger rc = -EFAULT; 1538f2bbc96eSHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1539f2bbc96eSHarald Freudenberger kfree(kkey); 1540f2bbc96eSHarald Freudenberger break; 1541f2bbc96eSHarald Freudenberger } 1542f2bbc96eSHarald Freudenberger case PKEY_VERIFYKEY2: { 1543f2bbc96eSHarald Freudenberger struct pkey_verifykey2 __user *uvk = (void __user *)arg; 1544f2bbc96eSHarald Freudenberger struct pkey_verifykey2 kvk; 1545f2bbc96eSHarald Freudenberger u8 *kkey; 1546f2bbc96eSHarald Freudenberger 1547f2bbc96eSHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1548f2bbc96eSHarald Freudenberger return -EFAULT; 1549f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kvk.key, kvk.keylen); 1550f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1551f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1552f2bbc96eSHarald Freudenberger rc = pkey_verifykey2(kkey, kvk.keylen, 1553f2bbc96eSHarald Freudenberger &kvk.cardnr, &kvk.domain, 1554f2bbc96eSHarald Freudenberger &kvk.type, &kvk.size, &kvk.flags); 1555f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 1556f2bbc96eSHarald Freudenberger kfree(kkey); 1557f2bbc96eSHarald Freudenberger if (rc) 1558f2bbc96eSHarald Freudenberger break; 1559f2bbc96eSHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1560f2bbc96eSHarald Freudenberger return -EFAULT; 1561f2bbc96eSHarald Freudenberger break; 1562f2bbc96eSHarald Freudenberger } 1563f2bbc96eSHarald Freudenberger case PKEY_KBLOB2PROTK2: { 1564f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 __user *utp = (void __user *)arg; 1565f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 156646a29b03SHarald Freudenberger struct pkey_kblob2pkey2 ktp; 1567f2bbc96eSHarald Freudenberger u8 *kkey; 1568f2bbc96eSHarald Freudenberger 1569f2bbc96eSHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1570f2bbc96eSHarald Freudenberger return -EFAULT; 1571f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1572f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1573f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1574f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1575f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1576f2bbc96eSHarald Freudenberger kfree(apqns); 1577f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1578f2bbc96eSHarald Freudenberger } 1579f370f45cSHarald Freudenberger ktp.protkey.len = sizeof(ktp.protkey.protkey); 1580f2bbc96eSHarald Freudenberger rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 1581f370f45cSHarald Freudenberger kkey, ktp.keylen, 1582f370f45cSHarald Freudenberger ktp.protkey.protkey, &ktp.protkey.len, 1583f370f45cSHarald Freudenberger &ktp.protkey.type); 1584f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 1585f2bbc96eSHarald Freudenberger kfree(apqns); 1586844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1587f2bbc96eSHarald Freudenberger kfree(kkey); 1588f2bbc96eSHarald Freudenberger if (rc) 1589f2bbc96eSHarald Freudenberger break; 1590f2bbc96eSHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1591f2bbc96eSHarald Freudenberger return -EFAULT; 1592f2bbc96eSHarald Freudenberger break; 1593f2bbc96eSHarald Freudenberger } 1594f2bbc96eSHarald Freudenberger case PKEY_APQNS4K: { 1595f2bbc96eSHarald Freudenberger struct pkey_apqns4key __user *uak = (void __user *)arg; 1596f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 159746a29b03SHarald Freudenberger struct pkey_apqns4key kak; 1598f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1599f2bbc96eSHarald Freudenberger u8 *kkey; 1600f2bbc96eSHarald Freudenberger 1601f2bbc96eSHarald Freudenberger if (copy_from_user(&kak, uak, sizeof(kak))) 1602f2bbc96eSHarald Freudenberger return -EFAULT; 1603f2bbc96eSHarald Freudenberger nr_apqns = kak.apqn_entries; 1604f2bbc96eSHarald Freudenberger if (nr_apqns) { 1605f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1606f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1607f2bbc96eSHarald Freudenberger GFP_KERNEL); 1608f2bbc96eSHarald Freudenberger if (!apqns) 1609f2bbc96eSHarald Freudenberger return -ENOMEM; 1610f2bbc96eSHarald Freudenberger } 1611f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kak.key, kak.keylen); 1612f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1613f2bbc96eSHarald Freudenberger kfree(apqns); 1614f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1615f2bbc96eSHarald Freudenberger } 1616f2bbc96eSHarald Freudenberger rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 1617f2bbc96eSHarald Freudenberger apqns, &nr_apqns); 1618f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 1619f2bbc96eSHarald Freudenberger kfree(kkey); 1620f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1621f2bbc96eSHarald Freudenberger kfree(apqns); 1622f2bbc96eSHarald Freudenberger break; 1623f2bbc96eSHarald Freudenberger } 1624f2bbc96eSHarald Freudenberger if (!rc && kak.apqns) { 1625f2bbc96eSHarald Freudenberger if (nr_apqns > kak.apqn_entries) { 1626f2bbc96eSHarald Freudenberger kfree(apqns); 1627f2bbc96eSHarald Freudenberger return -EINVAL; 1628f2bbc96eSHarald Freudenberger } 1629f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1630f2bbc96eSHarald Freudenberger if (len) { 1631f2bbc96eSHarald Freudenberger if (copy_to_user(kak.apqns, apqns, len)) { 1632f2bbc96eSHarald Freudenberger kfree(apqns); 1633f2bbc96eSHarald Freudenberger return -EFAULT; 1634f2bbc96eSHarald Freudenberger } 1635f2bbc96eSHarald Freudenberger } 1636f2bbc96eSHarald Freudenberger } 1637f2bbc96eSHarald Freudenberger kak.apqn_entries = nr_apqns; 1638f2bbc96eSHarald Freudenberger if (copy_to_user(uak, &kak, sizeof(kak))) 1639f2bbc96eSHarald Freudenberger rc = -EFAULT; 1640f2bbc96eSHarald Freudenberger kfree(apqns); 1641f2bbc96eSHarald Freudenberger break; 1642f2bbc96eSHarald Freudenberger } 1643f2bbc96eSHarald Freudenberger case PKEY_APQNS4KT: { 1644f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype __user *uat = (void __user *)arg; 1645f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 164646a29b03SHarald Freudenberger struct pkey_apqns4keytype kat; 1647f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1648f2bbc96eSHarald Freudenberger 1649f2bbc96eSHarald Freudenberger if (copy_from_user(&kat, uat, sizeof(kat))) 1650f2bbc96eSHarald Freudenberger return -EFAULT; 1651f2bbc96eSHarald Freudenberger nr_apqns = kat.apqn_entries; 1652f2bbc96eSHarald Freudenberger if (nr_apqns) { 1653f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1654f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1655f2bbc96eSHarald Freudenberger GFP_KERNEL); 1656f2bbc96eSHarald Freudenberger if (!apqns) 1657f2bbc96eSHarald Freudenberger return -ENOMEM; 1658f2bbc96eSHarald Freudenberger } 1659f2bbc96eSHarald Freudenberger rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 1660f2bbc96eSHarald Freudenberger kat.flags, apqns, &nr_apqns); 1661f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 1662f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1663f2bbc96eSHarald Freudenberger kfree(apqns); 1664f2bbc96eSHarald Freudenberger break; 1665f2bbc96eSHarald Freudenberger } 1666f2bbc96eSHarald Freudenberger if (!rc && kat.apqns) { 1667f2bbc96eSHarald Freudenberger if (nr_apqns > kat.apqn_entries) { 1668f2bbc96eSHarald Freudenberger kfree(apqns); 1669f2bbc96eSHarald Freudenberger return -EINVAL; 1670f2bbc96eSHarald Freudenberger } 1671f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1672f2bbc96eSHarald Freudenberger if (len) { 1673f2bbc96eSHarald Freudenberger if (copy_to_user(kat.apqns, apqns, len)) { 1674f2bbc96eSHarald Freudenberger kfree(apqns); 1675f2bbc96eSHarald Freudenberger return -EFAULT; 1676f2bbc96eSHarald Freudenberger } 1677f2bbc96eSHarald Freudenberger } 1678f2bbc96eSHarald Freudenberger } 1679f2bbc96eSHarald Freudenberger kat.apqn_entries = nr_apqns; 1680f2bbc96eSHarald Freudenberger if (copy_to_user(uat, &kat, sizeof(kat))) 1681f2bbc96eSHarald Freudenberger rc = -EFAULT; 1682f2bbc96eSHarald Freudenberger kfree(apqns); 1683f2bbc96eSHarald Freudenberger break; 1684f2bbc96eSHarald Freudenberger } 1685fa6999e3SHarald Freudenberger case PKEY_KBLOB2PROTK3: { 1686fa6999e3SHarald Freudenberger struct pkey_kblob2pkey3 __user *utp = (void __user *)arg; 1687fa6999e3SHarald Freudenberger u32 protkeylen = PROTKEYBLOBBUFSIZE; 168846a29b03SHarald Freudenberger struct pkey_apqn *apqns = NULL; 168946a29b03SHarald Freudenberger struct pkey_kblob2pkey3 ktp; 1690fa6999e3SHarald Freudenberger u8 *kkey, *protkey; 1691fa6999e3SHarald Freudenberger 1692fa6999e3SHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1693fa6999e3SHarald Freudenberger return -EFAULT; 1694fa6999e3SHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1695fa6999e3SHarald Freudenberger if (IS_ERR(apqns)) 1696fa6999e3SHarald Freudenberger return PTR_ERR(apqns); 1697fa6999e3SHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1698fa6999e3SHarald Freudenberger if (IS_ERR(kkey)) { 1699fa6999e3SHarald Freudenberger kfree(apqns); 1700fa6999e3SHarald Freudenberger return PTR_ERR(kkey); 1701fa6999e3SHarald Freudenberger } 1702fa6999e3SHarald Freudenberger protkey = kmalloc(protkeylen, GFP_KERNEL); 1703fa6999e3SHarald Freudenberger if (!protkey) { 1704fa6999e3SHarald Freudenberger kfree(apqns); 1705fa6999e3SHarald Freudenberger kfree(kkey); 1706fa6999e3SHarald Freudenberger return -ENOMEM; 1707fa6999e3SHarald Freudenberger } 1708f370f45cSHarald Freudenberger rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, 1709f370f45cSHarald Freudenberger kkey, ktp.keylen, 1710f370f45cSHarald Freudenberger protkey, &protkeylen, &ktp.pkeytype); 1711fa6999e3SHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); 1712fa6999e3SHarald Freudenberger kfree(apqns); 1713844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1714fa6999e3SHarald Freudenberger kfree(kkey); 1715fa6999e3SHarald Freudenberger if (rc) { 1716fa6999e3SHarald Freudenberger kfree(protkey); 1717fa6999e3SHarald Freudenberger break; 1718fa6999e3SHarald Freudenberger } 1719fa6999e3SHarald Freudenberger if (ktp.pkey && ktp.pkeylen) { 1720fa6999e3SHarald Freudenberger if (protkeylen > ktp.pkeylen) { 1721fa6999e3SHarald Freudenberger kfree(protkey); 1722fa6999e3SHarald Freudenberger return -EINVAL; 1723fa6999e3SHarald Freudenberger } 1724fa6999e3SHarald Freudenberger if (copy_to_user(ktp.pkey, protkey, protkeylen)) { 1725fa6999e3SHarald Freudenberger kfree(protkey); 1726fa6999e3SHarald Freudenberger return -EFAULT; 1727fa6999e3SHarald Freudenberger } 1728fa6999e3SHarald Freudenberger } 1729fa6999e3SHarald Freudenberger kfree(protkey); 1730fa6999e3SHarald Freudenberger ktp.pkeylen = protkeylen; 1731fa6999e3SHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1732fa6999e3SHarald Freudenberger return -EFAULT; 1733fa6999e3SHarald Freudenberger break; 1734fa6999e3SHarald Freudenberger } 1735e80d4af0SHarald Freudenberger default: 1736e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1737e80d4af0SHarald Freudenberger return -ENOTTY; 1738e80d4af0SHarald Freudenberger } 1739e80d4af0SHarald Freudenberger 1740e80d4af0SHarald Freudenberger return rc; 1741e80d4af0SHarald Freudenberger } 1742e80d4af0SHarald Freudenberger 1743e80d4af0SHarald Freudenberger /* 1744e80d4af0SHarald Freudenberger * Sysfs and file io operations 1745e80d4af0SHarald Freudenberger */ 1746d632c047SIngo Franzki 1747d632c047SIngo Franzki /* 1748d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1749d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1750d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1751d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1752d632c047SIngo Franzki */ 1753d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1754d632c047SIngo Franzki loff_t off, size_t count) 1755d632c047SIngo Franzki { 1756d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1757d632c047SIngo Franzki struct pkey_protkey protkey; 1758d632c047SIngo Franzki int rc; 1759d632c047SIngo Franzki 1760d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1761d632c047SIngo Franzki return -EINVAL; 1762d632c047SIngo Franzki if (is_xts) 1763d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1764d632c047SIngo Franzki return -EINVAL; 1765d632c047SIngo Franzki 1766d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1767d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1768d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1769d632c047SIngo Franzki protkeytoken.keytype = keytype; 1770d632c047SIngo Franzki 1771f370f45cSHarald Freudenberger protkey.len = sizeof(protkey.protkey); 1772f370f45cSHarald Freudenberger rc = pkey_genprotkey(protkeytoken.keytype, 1773f370f45cSHarald Freudenberger protkey.protkey, &protkey.len, &protkey.type); 1774d632c047SIngo Franzki if (rc) 1775d632c047SIngo Franzki return rc; 1776d632c047SIngo Franzki 1777d632c047SIngo Franzki protkeytoken.len = protkey.len; 1778d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1779d632c047SIngo Franzki 1780d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1781d632c047SIngo Franzki 1782d632c047SIngo Franzki if (is_xts) { 1783f370f45cSHarald Freudenberger /* xts needs a second protected key, reuse protkey struct */ 1784f370f45cSHarald Freudenberger protkey.len = sizeof(protkey.protkey); 1785f370f45cSHarald Freudenberger rc = pkey_genprotkey(protkeytoken.keytype, 1786f370f45cSHarald Freudenberger protkey.protkey, &protkey.len, &protkey.type); 1787d632c047SIngo Franzki if (rc) 1788d632c047SIngo Franzki return rc; 1789d632c047SIngo Franzki 1790d632c047SIngo Franzki protkeytoken.len = protkey.len; 1791d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1792d632c047SIngo Franzki 1793d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1794d632c047SIngo Franzki sizeof(protkeytoken)); 1795d632c047SIngo Franzki 1796d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1797d632c047SIngo Franzki } 1798d632c047SIngo Franzki 1799d632c047SIngo Franzki return sizeof(protkeytoken); 1800d632c047SIngo Franzki } 1801d632c047SIngo Franzki 1802d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1803d632c047SIngo Franzki struct kobject *kobj, 1804d632c047SIngo Franzki struct bin_attribute *attr, 1805d632c047SIngo Franzki char *buf, loff_t off, 1806d632c047SIngo Franzki size_t count) 1807d632c047SIngo Franzki { 1808d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1809d632c047SIngo Franzki off, count); 1810d632c047SIngo Franzki } 1811d632c047SIngo Franzki 1812d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1813d632c047SIngo Franzki struct kobject *kobj, 1814d632c047SIngo Franzki struct bin_attribute *attr, 1815d632c047SIngo Franzki char *buf, loff_t off, 1816d632c047SIngo Franzki size_t count) 1817d632c047SIngo Franzki { 1818d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1819d632c047SIngo Franzki off, count); 1820d632c047SIngo Franzki } 1821d632c047SIngo Franzki 1822d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1823d632c047SIngo Franzki struct kobject *kobj, 1824d632c047SIngo Franzki struct bin_attribute *attr, 1825d632c047SIngo Franzki char *buf, loff_t off, 1826d632c047SIngo Franzki size_t count) 1827d632c047SIngo Franzki { 1828d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1829d632c047SIngo Franzki off, count); 1830d632c047SIngo Franzki } 1831d632c047SIngo Franzki 1832d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1833d632c047SIngo Franzki struct kobject *kobj, 1834d632c047SIngo Franzki struct bin_attribute *attr, 1835d632c047SIngo Franzki char *buf, loff_t off, 1836d632c047SIngo Franzki size_t count) 1837d632c047SIngo Franzki { 1838d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1839d632c047SIngo Franzki off, count); 1840d632c047SIngo Franzki } 1841d632c047SIngo Franzki 1842d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1843d632c047SIngo Franzki struct kobject *kobj, 1844d632c047SIngo Franzki struct bin_attribute *attr, 1845d632c047SIngo Franzki char *buf, loff_t off, 1846d632c047SIngo Franzki size_t count) 1847d632c047SIngo Franzki { 1848d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1849d632c047SIngo Franzki off, count); 1850d632c047SIngo Franzki } 1851d632c047SIngo Franzki 1852d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1853d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1854d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1855d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1856d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1857d632c047SIngo Franzki 1858d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1859d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1860d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1861d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1862d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1863d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1864d632c047SIngo Franzki NULL 1865d632c047SIngo Franzki }; 1866d632c047SIngo Franzki 1867d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1868d632c047SIngo Franzki .name = "protkey", 1869d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1870d632c047SIngo Franzki }; 1871d632c047SIngo Franzki 1872af504452SIngo Franzki /* 1873af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1874af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1875af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1876af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1877af504452SIngo Franzki */ 1878af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1879af504452SIngo Franzki loff_t off, size_t count) 1880af504452SIngo Franzki { 1881efc598e6SHarald Freudenberger struct pkey_seckey *seckey = (struct pkey_seckey *)buf; 188246a29b03SHarald Freudenberger int rc; 1883af504452SIngo Franzki 1884af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1885af504452SIngo Franzki return -EINVAL; 1886af504452SIngo Franzki if (is_xts) 1887af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1888af504452SIngo Franzki return -EINVAL; 1889af504452SIngo Franzki 1890efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1891af504452SIngo Franzki if (rc) 1892af504452SIngo Franzki return rc; 1893af504452SIngo Franzki 1894af504452SIngo Franzki if (is_xts) { 1895efc598e6SHarald Freudenberger seckey++; 1896efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1897af504452SIngo Franzki if (rc) 1898af504452SIngo Franzki return rc; 1899af504452SIngo Franzki 1900af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1901af504452SIngo Franzki } 1902af504452SIngo Franzki 1903af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1904af504452SIngo Franzki } 1905af504452SIngo Franzki 1906af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1907af504452SIngo Franzki struct kobject *kobj, 1908af504452SIngo Franzki struct bin_attribute *attr, 1909af504452SIngo Franzki char *buf, loff_t off, 1910af504452SIngo Franzki size_t count) 1911af504452SIngo Franzki { 1912af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1913af504452SIngo Franzki off, count); 1914af504452SIngo Franzki } 1915af504452SIngo Franzki 1916af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1917af504452SIngo Franzki struct kobject *kobj, 1918af504452SIngo Franzki struct bin_attribute *attr, 1919af504452SIngo Franzki char *buf, loff_t off, 1920af504452SIngo Franzki size_t count) 1921af504452SIngo Franzki { 1922af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1923af504452SIngo Franzki off, count); 1924af504452SIngo Franzki } 1925af504452SIngo Franzki 1926af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1927af504452SIngo Franzki struct kobject *kobj, 1928af504452SIngo Franzki struct bin_attribute *attr, 1929af504452SIngo Franzki char *buf, loff_t off, 1930af504452SIngo Franzki size_t count) 1931af504452SIngo Franzki { 1932af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1933af504452SIngo Franzki off, count); 1934af504452SIngo Franzki } 1935af504452SIngo Franzki 1936af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1937af504452SIngo Franzki struct kobject *kobj, 1938af504452SIngo Franzki struct bin_attribute *attr, 1939af504452SIngo Franzki char *buf, loff_t off, 1940af504452SIngo Franzki size_t count) 1941af504452SIngo Franzki { 1942af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1943af504452SIngo Franzki off, count); 1944af504452SIngo Franzki } 1945af504452SIngo Franzki 1946af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1947af504452SIngo Franzki struct kobject *kobj, 1948af504452SIngo Franzki struct bin_attribute *attr, 1949af504452SIngo Franzki char *buf, loff_t off, 1950af504452SIngo Franzki size_t count) 1951af504452SIngo Franzki { 1952af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1953af504452SIngo Franzki off, count); 1954af504452SIngo Franzki } 1955af504452SIngo Franzki 1956af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1957af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1958af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1959af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1960af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1961af504452SIngo Franzki 1962af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1963af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1964af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1965af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1966af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1967af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1968af504452SIngo Franzki NULL 1969af504452SIngo Franzki }; 1970af504452SIngo Franzki 1971af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1972af504452SIngo Franzki .name = "ccadata", 1973af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1974af504452SIngo Franzki }; 1975af504452SIngo Franzki 1976f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) 1977f71fee27SIngo Franzki 1978f71fee27SIngo Franzki /* 1979f71fee27SIngo Franzki * Sysfs attribute read function for all secure key ccacipher binary attributes. 1980f71fee27SIngo Franzki * The implementation can not deal with partial reads, because a new random 1981f71fee27SIngo Franzki * secure key blob is generated with each read. In case of partial reads 1982f71fee27SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1983f71fee27SIngo Franzki */ 1984f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, 1985f71fee27SIngo Franzki bool is_xts, char *buf, loff_t off, 1986f71fee27SIngo Franzki size_t count) 1987f71fee27SIngo Franzki { 198855d0a513SHarald Freudenberger size_t keysize = CCACIPHERTOKENSIZE; 198946a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 199046a29b03SHarald Freudenberger int i, rc, card, dom; 1991f71fee27SIngo Franzki 1992f71fee27SIngo Franzki if (off != 0 || count < CCACIPHERTOKENSIZE) 1993f71fee27SIngo Franzki return -EINVAL; 1994f71fee27SIngo Franzki if (is_xts) 1995f71fee27SIngo Franzki if (count < 2 * CCACIPHERTOKENSIZE) 1996f71fee27SIngo Franzki return -EINVAL; 1997f71fee27SIngo Franzki 199855d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 199955d0a513SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 200032ca04bbSHarald Freudenberger ZCRYPT_CEX6, 0, 0, 0, 0); 2001f71fee27SIngo Franzki if (rc) 2002f71fee27SIngo Franzki return rc; 200355d0a513SHarald Freudenberger 200455d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 200555d0a513SHarald Freudenberger 200655d0a513SHarald Freudenberger /* simple try all apqns from the list */ 200755d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 200855d0a513SHarald Freudenberger card = apqns[i] >> 16; 200955d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 201055d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 201155d0a513SHarald Freudenberger if (rc == 0) 201255d0a513SHarald Freudenberger break; 201355d0a513SHarald Freudenberger } 201455d0a513SHarald Freudenberger if (rc) 201555d0a513SHarald Freudenberger return rc; 2016f71fee27SIngo Franzki 2017f71fee27SIngo Franzki if (is_xts) { 2018f71fee27SIngo Franzki keysize = CCACIPHERTOKENSIZE; 201955d0a513SHarald Freudenberger buf += CCACIPHERTOKENSIZE; 202055d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 202155d0a513SHarald Freudenberger if (rc == 0) 2022f71fee27SIngo Franzki return 2 * CCACIPHERTOKENSIZE; 2023f71fee27SIngo Franzki } 2024f71fee27SIngo Franzki 2025f71fee27SIngo Franzki return CCACIPHERTOKENSIZE; 2026f71fee27SIngo Franzki } 2027f71fee27SIngo Franzki 2028f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp, 2029f71fee27SIngo Franzki struct kobject *kobj, 2030f71fee27SIngo Franzki struct bin_attribute *attr, 2031f71fee27SIngo Franzki char *buf, loff_t off, 2032f71fee27SIngo Franzki size_t count) 2033f71fee27SIngo Franzki { 2034f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 2035f71fee27SIngo Franzki off, count); 2036f71fee27SIngo Franzki } 2037f71fee27SIngo Franzki 2038f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp, 2039f71fee27SIngo Franzki struct kobject *kobj, 2040f71fee27SIngo Franzki struct bin_attribute *attr, 2041f71fee27SIngo Franzki char *buf, loff_t off, 2042f71fee27SIngo Franzki size_t count) 2043f71fee27SIngo Franzki { 2044f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 2045f71fee27SIngo Franzki off, count); 2046f71fee27SIngo Franzki } 2047f71fee27SIngo Franzki 2048f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp, 2049f71fee27SIngo Franzki struct kobject *kobj, 2050f71fee27SIngo Franzki struct bin_attribute *attr, 2051f71fee27SIngo Franzki char *buf, loff_t off, 2052f71fee27SIngo Franzki size_t count) 2053f71fee27SIngo Franzki { 2054f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 2055f71fee27SIngo Franzki off, count); 2056f71fee27SIngo Franzki } 2057f71fee27SIngo Franzki 2058f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp, 2059f71fee27SIngo Franzki struct kobject *kobj, 2060f71fee27SIngo Franzki struct bin_attribute *attr, 2061f71fee27SIngo Franzki char *buf, loff_t off, 2062f71fee27SIngo Franzki size_t count) 2063f71fee27SIngo Franzki { 2064f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 2065f71fee27SIngo Franzki off, count); 2066f71fee27SIngo Franzki } 2067f71fee27SIngo Franzki 2068f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp, 2069f71fee27SIngo Franzki struct kobject *kobj, 2070f71fee27SIngo Franzki struct bin_attribute *attr, 2071f71fee27SIngo Franzki char *buf, loff_t off, 2072f71fee27SIngo Franzki size_t count) 2073f71fee27SIngo Franzki { 2074f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 2075f71fee27SIngo Franzki off, count); 2076f71fee27SIngo Franzki } 2077f71fee27SIngo Franzki 2078f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); 2079f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); 2080f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); 2081f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); 2082f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); 2083f71fee27SIngo Franzki 2084f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = { 2085f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128, 2086f71fee27SIngo Franzki &bin_attr_ccacipher_aes_192, 2087f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256, 2088f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128_xts, 2089f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256_xts, 2090f71fee27SIngo Franzki NULL 2091f71fee27SIngo Franzki }; 2092f71fee27SIngo Franzki 2093f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = { 2094f71fee27SIngo Franzki .name = "ccacipher", 2095f71fee27SIngo Franzki .bin_attrs = ccacipher_attrs, 2096f71fee27SIngo Franzki }; 2097f71fee27SIngo Franzki 209855d0a513SHarald Freudenberger /* 209955d0a513SHarald Freudenberger * Sysfs attribute read function for all ep11 aes key binary attributes. 210055d0a513SHarald Freudenberger * The implementation can not deal with partial reads, because a new random 210155d0a513SHarald Freudenberger * secure key blob is generated with each read. In case of partial reads 210255d0a513SHarald Freudenberger * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 210355d0a513SHarald Freudenberger * This function and the sysfs attributes using it provide EP11 key blobs 210455d0a513SHarald Freudenberger * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently 210555d0a513SHarald Freudenberger * 320 bytes. 210655d0a513SHarald Freudenberger */ 210755d0a513SHarald Freudenberger static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, 210855d0a513SHarald Freudenberger bool is_xts, char *buf, loff_t off, 210955d0a513SHarald Freudenberger size_t count) 211055d0a513SHarald Freudenberger { 211155d0a513SHarald Freudenberger size_t keysize = MAXEP11AESKEYBLOBSIZE; 211246a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 211346a29b03SHarald Freudenberger int i, rc, card, dom; 211455d0a513SHarald Freudenberger 211555d0a513SHarald Freudenberger if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) 211655d0a513SHarald Freudenberger return -EINVAL; 211755d0a513SHarald Freudenberger if (is_xts) 211855d0a513SHarald Freudenberger if (count < 2 * MAXEP11AESKEYBLOBSIZE) 211955d0a513SHarald Freudenberger return -EINVAL; 212055d0a513SHarald Freudenberger 212155d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 212255d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 212355d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 212455d0a513SHarald Freudenberger if (rc) 212555d0a513SHarald Freudenberger return rc; 212655d0a513SHarald Freudenberger 212755d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 212855d0a513SHarald Freudenberger 212955d0a513SHarald Freudenberger /* simple try all apqns from the list */ 213055d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 213155d0a513SHarald Freudenberger card = apqns[i] >> 16; 213255d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 213355d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 213455d0a513SHarald Freudenberger if (rc == 0) 213555d0a513SHarald Freudenberger break; 213655d0a513SHarald Freudenberger } 213755d0a513SHarald Freudenberger if (rc) 213855d0a513SHarald Freudenberger return rc; 213955d0a513SHarald Freudenberger 214055d0a513SHarald Freudenberger if (is_xts) { 214155d0a513SHarald Freudenberger keysize = MAXEP11AESKEYBLOBSIZE; 214255d0a513SHarald Freudenberger buf += MAXEP11AESKEYBLOBSIZE; 214355d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 214455d0a513SHarald Freudenberger if (rc == 0) 214555d0a513SHarald Freudenberger return 2 * MAXEP11AESKEYBLOBSIZE; 214655d0a513SHarald Freudenberger } 214755d0a513SHarald Freudenberger 214855d0a513SHarald Freudenberger return MAXEP11AESKEYBLOBSIZE; 214955d0a513SHarald Freudenberger } 215055d0a513SHarald Freudenberger 215155d0a513SHarald Freudenberger static ssize_t ep11_aes_128_read(struct file *filp, 215255d0a513SHarald Freudenberger struct kobject *kobj, 215355d0a513SHarald Freudenberger struct bin_attribute *attr, 215455d0a513SHarald Freudenberger char *buf, loff_t off, 215555d0a513SHarald Freudenberger size_t count) 215655d0a513SHarald Freudenberger { 215755d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 215855d0a513SHarald Freudenberger off, count); 215955d0a513SHarald Freudenberger } 216055d0a513SHarald Freudenberger 216155d0a513SHarald Freudenberger static ssize_t ep11_aes_192_read(struct file *filp, 216255d0a513SHarald Freudenberger struct kobject *kobj, 216355d0a513SHarald Freudenberger struct bin_attribute *attr, 216455d0a513SHarald Freudenberger char *buf, loff_t off, 216555d0a513SHarald Freudenberger size_t count) 216655d0a513SHarald Freudenberger { 216755d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 216855d0a513SHarald Freudenberger off, count); 216955d0a513SHarald Freudenberger } 217055d0a513SHarald Freudenberger 217155d0a513SHarald Freudenberger static ssize_t ep11_aes_256_read(struct file *filp, 217255d0a513SHarald Freudenberger struct kobject *kobj, 217355d0a513SHarald Freudenberger struct bin_attribute *attr, 217455d0a513SHarald Freudenberger char *buf, loff_t off, 217555d0a513SHarald Freudenberger size_t count) 217655d0a513SHarald Freudenberger { 217755d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 217855d0a513SHarald Freudenberger off, count); 217955d0a513SHarald Freudenberger } 218055d0a513SHarald Freudenberger 218155d0a513SHarald Freudenberger static ssize_t ep11_aes_128_xts_read(struct file *filp, 218255d0a513SHarald Freudenberger struct kobject *kobj, 218355d0a513SHarald Freudenberger struct bin_attribute *attr, 218455d0a513SHarald Freudenberger char *buf, loff_t off, 218555d0a513SHarald Freudenberger size_t count) 218655d0a513SHarald Freudenberger { 218755d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 218855d0a513SHarald Freudenberger off, count); 218955d0a513SHarald Freudenberger } 219055d0a513SHarald Freudenberger 219155d0a513SHarald Freudenberger static ssize_t ep11_aes_256_xts_read(struct file *filp, 219255d0a513SHarald Freudenberger struct kobject *kobj, 219355d0a513SHarald Freudenberger struct bin_attribute *attr, 219455d0a513SHarald Freudenberger char *buf, loff_t off, 219555d0a513SHarald Freudenberger size_t count) 219655d0a513SHarald Freudenberger { 219755d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 219855d0a513SHarald Freudenberger off, count); 219955d0a513SHarald Freudenberger } 220055d0a513SHarald Freudenberger 220155d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE); 220255d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE); 220355d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE); 220455d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE); 220555d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE); 220655d0a513SHarald Freudenberger 220755d0a513SHarald Freudenberger static struct bin_attribute *ep11_attrs[] = { 220855d0a513SHarald Freudenberger &bin_attr_ep11_aes_128, 220955d0a513SHarald Freudenberger &bin_attr_ep11_aes_192, 221055d0a513SHarald Freudenberger &bin_attr_ep11_aes_256, 221155d0a513SHarald Freudenberger &bin_attr_ep11_aes_128_xts, 221255d0a513SHarald Freudenberger &bin_attr_ep11_aes_256_xts, 221355d0a513SHarald Freudenberger NULL 221455d0a513SHarald Freudenberger }; 221555d0a513SHarald Freudenberger 221655d0a513SHarald Freudenberger static struct attribute_group ep11_attr_group = { 221755d0a513SHarald Freudenberger .name = "ep11", 221855d0a513SHarald Freudenberger .bin_attrs = ep11_attrs, 221955d0a513SHarald Freudenberger }; 222055d0a513SHarald Freudenberger 2221d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 2222d632c047SIngo Franzki &protkey_attr_group, 2223af504452SIngo Franzki &ccadata_attr_group, 2224f71fee27SIngo Franzki &ccacipher_attr_group, 222555d0a513SHarald Freudenberger &ep11_attr_group, 2226d632c047SIngo Franzki NULL, 2227d632c047SIngo Franzki }; 2228d632c047SIngo Franzki 2229e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 2230e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 2231e80d4af0SHarald Freudenberger .open = nonseekable_open, 2232e80d4af0SHarald Freudenberger .llseek = no_llseek, 2233e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 2234e80d4af0SHarald Freudenberger }; 2235e80d4af0SHarald Freudenberger 2236e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 2237e80d4af0SHarald Freudenberger .name = "pkey", 2238e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 2239e80d4af0SHarald Freudenberger .mode = 0666, 2240e80d4af0SHarald Freudenberger .fops = &pkey_fops, 2241d632c047SIngo Franzki .groups = pkey_attr_groups, 2242e80d4af0SHarald Freudenberger }; 2243e80d4af0SHarald Freudenberger 2244e80d4af0SHarald Freudenberger /* 2245e80d4af0SHarald Freudenberger * Module init 2246e80d4af0SHarald Freudenberger */ 2247cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 2248e80d4af0SHarald Freudenberger { 22495b35047eSHarald Freudenberger cpacf_mask_t func_mask; 2250e80d4af0SHarald Freudenberger 2251f822ad2cSHarald Freudenberger /* 2252f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 2253f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 2254f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 2255f822ad2cSHarald Freudenberger * are able to work with protected keys. 2256f822ad2cSHarald Freudenberger */ 22575b35047eSHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &func_mask)) 225858443b67SDavid Hildenbrand return -ENODEV; 2259e80d4af0SHarald Freudenberger 2260cb26b9ffSIngo Franzki /* check for kmc instructions available */ 22615b35047eSHarald Freudenberger if (!cpacf_query(CPACF_KMC, &func_mask)) 226258443b67SDavid Hildenbrand return -ENODEV; 22635b35047eSHarald Freudenberger if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) || 22645b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) || 22655b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256)) 226658443b67SDavid Hildenbrand return -ENODEV; 2267cb26b9ffSIngo Franzki 2268e80d4af0SHarald Freudenberger pkey_debug_init(); 2269e80d4af0SHarald Freudenberger 2270e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 2271e80d4af0SHarald Freudenberger } 2272e80d4af0SHarald Freudenberger 2273e80d4af0SHarald Freudenberger /* 2274e80d4af0SHarald Freudenberger * Module exit 2275e80d4af0SHarald Freudenberger */ 2276e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 2277e80d4af0SHarald Freudenberger { 2278e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 2279e80d4af0SHarald Freudenberger pkey_debug_exit(); 2280e80d4af0SHarald Freudenberger } 2281e80d4af0SHarald Freudenberger 22820a5f9b38SHeiko Carstens module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init); 2283e80d4af0SHarald Freudenberger module_exit(pkey_exit); 2284