1812141a9SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2e80d4af0SHarald Freudenberger /* 3e80d4af0SHarald Freudenberger * pkey device driver 4e80d4af0SHarald Freudenberger * 5183cb469SHarald Freudenberger * Copyright IBM Corp. 2017,2019 6e80d4af0SHarald Freudenberger * Author(s): Harald Freudenberger 7e80d4af0SHarald Freudenberger */ 8e80d4af0SHarald Freudenberger 9e80d4af0SHarald Freudenberger #define KMSG_COMPONENT "pkey" 10e80d4af0SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 11e80d4af0SHarald Freudenberger 12e80d4af0SHarald Freudenberger #include <linux/fs.h> 13e80d4af0SHarald Freudenberger #include <linux/init.h> 14e80d4af0SHarald Freudenberger #include <linux/miscdevice.h> 15e80d4af0SHarald Freudenberger #include <linux/module.h> 16e80d4af0SHarald Freudenberger #include <linux/slab.h> 17e80d4af0SHarald Freudenberger #include <linux/kallsyms.h> 18e80d4af0SHarald Freudenberger #include <linux/debugfs.h> 19a45a5c7dSIngo Franzki #include <linux/random.h> 2063c19be0SIngo Franzki #include <linux/cpufeature.h> 21e80d4af0SHarald Freudenberger #include <asm/zcrypt.h> 22e80d4af0SHarald Freudenberger #include <asm/cpacf.h> 23e80d4af0SHarald Freudenberger #include <asm/pkey.h> 24cb26b9ffSIngo Franzki #include <crypto/aes.h> 25e80d4af0SHarald Freudenberger 26e80d4af0SHarald Freudenberger #include "zcrypt_api.h" 27efc598e6SHarald Freudenberger #include "zcrypt_ccamisc.h" 2855d0a513SHarald Freudenberger #include "zcrypt_ep11misc.h" 29e80d4af0SHarald Freudenberger 30e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL"); 31e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 32e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface"); 33e80d4af0SHarald Freudenberger 34f2bbc96eSHarald Freudenberger #define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ 35fa6999e3SHarald Freudenberger #define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */ 36f2bbc96eSHarald Freudenberger #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ 37*f370f45cSHarald Freudenberger #define AES_WK_VP_SIZE 32 /* Size of WK VP block appended to a prot key */ 38f2bbc96eSHarald Freudenberger 39e80d4af0SHarald Freudenberger /* 40e80d4af0SHarald Freudenberger * debug feature data and functions 41e80d4af0SHarald Freudenberger */ 42e80d4af0SHarald Freudenberger 43e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 44e80d4af0SHarald Freudenberger 45e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 46e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 47e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 48e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 49e80d4af0SHarald Freudenberger 50e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 51e80d4af0SHarald Freudenberger { 526b1f16baSHarald Freudenberger /* 5 arguments per dbf entry (including the format string ptr) */ 536b1f16baSHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); 54e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 55e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 56e80d4af0SHarald Freudenberger } 57e80d4af0SHarald Freudenberger 58e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 59e80d4af0SHarald Freudenberger { 60e80d4af0SHarald Freudenberger debug_unregister(debug_info); 61e80d4af0SHarald Freudenberger } 62e80d4af0SHarald Freudenberger 630534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */ 640534bde7SIngo Franzki struct protaeskeytoken { 650534bde7SIngo Franzki u8 type; /* 0x00 for PAES specific key tokens */ 660534bde7SIngo Franzki u8 res0[3]; 670534bde7SIngo Franzki u8 version; /* should be 0x01 for protected AES key token */ 680534bde7SIngo Franzki u8 res1[3]; 690534bde7SIngo Franzki u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 700534bde7SIngo Franzki u32 len; /* bytes actually stored in protkey[] */ 710534bde7SIngo Franzki u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 720534bde7SIngo Franzki } __packed; 730534bde7SIngo Franzki 74888edbc4SHarald Freudenberger /* inside view of a clear key token (type 0x00 version 0x02) */ 75888edbc4SHarald Freudenberger struct clearaeskeytoken { 76888edbc4SHarald Freudenberger u8 type; /* 0x00 for PAES specific key tokens */ 77888edbc4SHarald Freudenberger u8 res0[3]; 78888edbc4SHarald Freudenberger u8 version; /* 0x02 for clear AES key token */ 79888edbc4SHarald Freudenberger u8 res1[3]; 80888edbc4SHarald Freudenberger u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 81888edbc4SHarald Freudenberger u32 len; /* bytes actually stored in clearkey[] */ 82fa226f1dSGustavo A. R. Silva u8 clearkey[]; /* clear key value */ 83888edbc4SHarald Freudenberger } __packed; 84888edbc4SHarald Freudenberger 85e80d4af0SHarald Freudenberger /* 86*f370f45cSHarald Freudenberger * Create a protected key from a clear key value via PCKMO instruction. 87e80d4af0SHarald Freudenberger */ 88*f370f45cSHarald Freudenberger static int pkey_clr2protkey(u32 keytype, const u8 *clrkey, 89*f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 90e80d4af0SHarald Freudenberger { 915b35047eSHarald Freudenberger /* mask of available pckmo subfunctions */ 925b35047eSHarald Freudenberger static cpacf_mask_t pckmo_functions; 935b35047eSHarald Freudenberger 94e80d4af0SHarald Freudenberger u8 paramblock[64]; 9546a29b03SHarald Freudenberger int keysize; 9646a29b03SHarald Freudenberger long fc; 97e80d4af0SHarald Freudenberger 98e80d4af0SHarald Freudenberger switch (keytype) { 99e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 100e80d4af0SHarald Freudenberger keysize = 16; 101e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 102e80d4af0SHarald Freudenberger break; 103e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 104e80d4af0SHarald Freudenberger keysize = 24; 105e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 106e80d4af0SHarald Freudenberger break; 107e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 108e80d4af0SHarald Freudenberger keysize = 32; 109e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 110e80d4af0SHarald Freudenberger break; 111e80d4af0SHarald Freudenberger default: 112*f370f45cSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", 113ac2b96f3SHarald Freudenberger __func__, keytype); 114e80d4af0SHarald Freudenberger return -EINVAL; 115e80d4af0SHarald Freudenberger } 116e80d4af0SHarald Freudenberger 117*f370f45cSHarald Freudenberger if (*protkeylen < keysize + AES_WK_VP_SIZE) { 118*f370f45cSHarald Freudenberger DEBUG_ERR("%s prot key buffer size too small: %u < %d\n", 119*f370f45cSHarald Freudenberger __func__, *protkeylen, keysize + AES_WK_VP_SIZE); 120*f370f45cSHarald Freudenberger return -EINVAL; 121*f370f45cSHarald Freudenberger } 122*f370f45cSHarald Freudenberger 1235b35047eSHarald Freudenberger /* Did we already check for PCKMO ? */ 1245b35047eSHarald Freudenberger if (!pckmo_functions.bytes[0]) { 1255b35047eSHarald Freudenberger /* no, so check now */ 1265b35047eSHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 1275b35047eSHarald Freudenberger return -ENODEV; 1285b35047eSHarald Freudenberger } 1295b35047eSHarald Freudenberger /* check for the pckmo subfunction we need now */ 130f822ad2cSHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, fc)) { 131f822ad2cSHarald Freudenberger DEBUG_ERR("%s pckmo functions not available\n", __func__); 13258443b67SDavid Hildenbrand return -ENODEV; 133f822ad2cSHarald Freudenberger } 134f822ad2cSHarald Freudenberger 135e80d4af0SHarald Freudenberger /* prepare param block */ 136e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 137*f370f45cSHarald Freudenberger memcpy(paramblock, clrkey, keysize); 138e80d4af0SHarald Freudenberger 139e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 140e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 141e80d4af0SHarald Freudenberger 142*f370f45cSHarald Freudenberger /* copy created protected key to key buffer including the wkvp block */ 143*f370f45cSHarald Freudenberger *protkeylen = keysize + AES_WK_VP_SIZE; 144*f370f45cSHarald Freudenberger memcpy(protkey, paramblock, *protkeylen); 145*f370f45cSHarald Freudenberger *protkeytype = keytype; 146e80d4af0SHarald Freudenberger 147e80d4af0SHarald Freudenberger return 0; 148e80d4af0SHarald Freudenberger } 149e80d4af0SHarald Freudenberger 150e80d4af0SHarald Freudenberger /* 151e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 152e80d4af0SHarald Freudenberger */ 153*f370f45cSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, u8 *protkey, 154*f370f45cSHarald Freudenberger u32 *protkeylen, u32 *protkeytype) 155e80d4af0SHarald Freudenberger { 156f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 15746a29b03SHarald Freudenberger u16 cardnr, domain; 15846a29b03SHarald Freudenberger int rc, verify; 159e80d4af0SHarald Freudenberger 16043cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 16143cb5a7cSHarald Freudenberger 162e80d4af0SHarald Freudenberger /* 163f2bbc96eSHarald Freudenberger * The cca_xxx2protkey call may fail when a card has been 164e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 165f4272c03SJulia Lawall * of the mkvp into the cache. Try 3 times: First without verify 166efc598e6SHarald Freudenberger * then with verify and last round with verify and old master 167efc598e6SHarald Freudenberger * key verification pattern match not ignored. 168e80d4af0SHarald Freudenberger */ 169efc598e6SHarald Freudenberger for (verify = 0; verify < 3; verify++) { 170f2bbc96eSHarald Freudenberger rc = cca_findcard(key, &cardnr, &domain, verify); 171efc598e6SHarald Freudenberger if (rc < 0) 172e80d4af0SHarald Freudenberger continue; 173efc598e6SHarald Freudenberger if (rc > 0 && verify < 2) 174efc598e6SHarald Freudenberger continue; 175f2bbc96eSHarald Freudenberger switch (hdr->version) { 176f2bbc96eSHarald Freudenberger case TOKVER_CCA_AES: 177*f370f45cSHarald Freudenberger rc = cca_sec2protkey(cardnr, domain, key, 178*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 179f2bbc96eSHarald Freudenberger break; 180f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 181*f370f45cSHarald Freudenberger rc = cca_cipher2protkey(cardnr, domain, key, 182*f370f45cSHarald Freudenberger protkey, protkeylen, 183*f370f45cSHarald Freudenberger protkeytype); 184f2bbc96eSHarald Freudenberger break; 185f2bbc96eSHarald Freudenberger default: 186f2bbc96eSHarald Freudenberger return -EINVAL; 187f2bbc96eSHarald Freudenberger } 188e80d4af0SHarald Freudenberger if (rc == 0) 189e80d4af0SHarald Freudenberger break; 190e80d4af0SHarald Freudenberger } 191e80d4af0SHarald Freudenberger 192e80d4af0SHarald Freudenberger if (rc) 193ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 194e80d4af0SHarald Freudenberger 195e80d4af0SHarald Freudenberger return rc; 196e80d4af0SHarald Freudenberger } 197e80d4af0SHarald Freudenberger 198e80d4af0SHarald Freudenberger /* 19955d0a513SHarald Freudenberger * Construct EP11 key with given clear key value. 20055d0a513SHarald Freudenberger */ 20155d0a513SHarald Freudenberger static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, 20255d0a513SHarald Freudenberger u8 *keybuf, size_t *keybuflen) 20355d0a513SHarald Freudenberger { 20455d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 20546a29b03SHarald Freudenberger u16 card, dom; 20646a29b03SHarald Freudenberger int i, rc; 20755d0a513SHarald Freudenberger 20843cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 20943cb5a7cSHarald Freudenberger 21055d0a513SHarald Freudenberger /* build a list of apqns suitable for ep11 keys with cpacf support */ 21155d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 21255d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 21355d0a513SHarald Freudenberger if (rc) 21455d0a513SHarald Freudenberger goto out; 21555d0a513SHarald Freudenberger 21655d0a513SHarald Freudenberger /* go through the list of apqns and try to bild an ep11 key */ 21755d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 21855d0a513SHarald Freudenberger card = apqns[i] >> 16; 21955d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 22055d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, clrkeylen * 8, 22155d0a513SHarald Freudenberger 0, clrkey, keybuf, keybuflen); 22255d0a513SHarald Freudenberger if (rc == 0) 22355d0a513SHarald Freudenberger break; 22455d0a513SHarald Freudenberger } 22555d0a513SHarald Freudenberger 22655d0a513SHarald Freudenberger out: 22755d0a513SHarald Freudenberger kfree(apqns); 22855d0a513SHarald Freudenberger if (rc) 22955d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 23055d0a513SHarald Freudenberger return rc; 23155d0a513SHarald Freudenberger } 23255d0a513SHarald Freudenberger 23355d0a513SHarald Freudenberger /* 23455d0a513SHarald Freudenberger * Find card and transform EP11 secure key into protected key. 23555d0a513SHarald Freudenberger */ 236*f370f45cSHarald Freudenberger static int pkey_ep11key2pkey(const u8 *key, u8 *protkey, 237*f370f45cSHarald Freudenberger u32 *protkeylen, u32 *protkeytype) 23855d0a513SHarald Freudenberger { 23955d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 24046a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 24146a29b03SHarald Freudenberger u16 card, dom; 24246a29b03SHarald Freudenberger int i, rc; 24355d0a513SHarald Freudenberger 24443cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 24543cb5a7cSHarald Freudenberger 24655d0a513SHarald Freudenberger /* build a list of apqns suitable for this key */ 24755d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 24855d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 24955d0a513SHarald Freudenberger if (rc) 25055d0a513SHarald Freudenberger goto out; 25155d0a513SHarald Freudenberger 25255d0a513SHarald Freudenberger /* go through the list of apqns and try to derive an pkey */ 25355d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 25455d0a513SHarald Freudenberger card = apqns[i] >> 16; 25555d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 256fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 257*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 25855d0a513SHarald Freudenberger if (rc == 0) 25955d0a513SHarald Freudenberger break; 26055d0a513SHarald Freudenberger } 26155d0a513SHarald Freudenberger 26255d0a513SHarald Freudenberger out: 26355d0a513SHarald Freudenberger kfree(apqns); 26455d0a513SHarald Freudenberger if (rc) 26555d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 26655d0a513SHarald Freudenberger return rc; 26755d0a513SHarald Freudenberger } 26855d0a513SHarald Freudenberger 26955d0a513SHarald Freudenberger /* 270e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 271e61a6134SHarald Freudenberger */ 272183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey, 273e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 274e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 275e61a6134SHarald Freudenberger { 276e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)seckey; 277e61a6134SHarald Freudenberger u16 cardnr, domain; 278e61a6134SHarald Freudenberger int rc; 279e61a6134SHarald Freudenberger 280e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 281efc598e6SHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *)seckey, 0); 282e61a6134SHarald Freudenberger if (rc) 283e61a6134SHarald Freudenberger goto out; 284e61a6134SHarald Freudenberger if (pattributes) 285e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 286e61a6134SHarald Freudenberger if (pkeysize) 287e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 288e61a6134SHarald Freudenberger 289e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 290efc598e6SHarald Freudenberger rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); 291efc598e6SHarald Freudenberger if (rc < 0) 292e61a6134SHarald Freudenberger goto out; 293e61a6134SHarald Freudenberger 294efc598e6SHarald Freudenberger if (rc > 0) { 295efc598e6SHarald Freudenberger /* key mkvp matches to old master key mkvp */ 296ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 297e61a6134SHarald Freudenberger if (pattributes) 298e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 299efc598e6SHarald Freudenberger rc = 0; 300e61a6134SHarald Freudenberger } 301e61a6134SHarald Freudenberger 302e61a6134SHarald Freudenberger if (pcardnr) 303e61a6134SHarald Freudenberger *pcardnr = cardnr; 304e61a6134SHarald Freudenberger if (pdomain) 305e61a6134SHarald Freudenberger *pdomain = domain; 306e61a6134SHarald Freudenberger 307e61a6134SHarald Freudenberger out: 308ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 309e61a6134SHarald Freudenberger return rc; 310e61a6134SHarald Freudenberger } 311e61a6134SHarald Freudenberger 312e61a6134SHarald Freudenberger /* 313a45a5c7dSIngo Franzki * Generate a random protected key 314a45a5c7dSIngo Franzki */ 315*f370f45cSHarald Freudenberger static int pkey_genprotkey(u32 keytype, u8 *protkey, 316*f370f45cSHarald Freudenberger u32 *protkeylen, u32 *protkeytype) 317a45a5c7dSIngo Franzki { 318*f370f45cSHarald Freudenberger u8 clrkey[32]; 319a45a5c7dSIngo Franzki int keysize; 320a45a5c7dSIngo Franzki int rc; 321a45a5c7dSIngo Franzki 322a45a5c7dSIngo Franzki switch (keytype) { 323a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_128: 324a45a5c7dSIngo Franzki keysize = 16; 325a45a5c7dSIngo Franzki break; 326a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_192: 327a45a5c7dSIngo Franzki keysize = 24; 328a45a5c7dSIngo Franzki break; 329a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_256: 330a45a5c7dSIngo Franzki keysize = 32; 331a45a5c7dSIngo Franzki break; 332a45a5c7dSIngo Franzki default: 333a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 334a45a5c7dSIngo Franzki keytype); 335a45a5c7dSIngo Franzki return -EINVAL; 336a45a5c7dSIngo Franzki } 337a45a5c7dSIngo Franzki 338a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 339*f370f45cSHarald Freudenberger get_random_bytes(clrkey, keysize); 340a45a5c7dSIngo Franzki 341a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 342*f370f45cSHarald Freudenberger rc = pkey_clr2protkey(keytype, clrkey, 343*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 344a45a5c7dSIngo Franzki if (rc) 345a45a5c7dSIngo Franzki return rc; 346a45a5c7dSIngo Franzki 347a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 348*f370f45cSHarald Freudenberger get_random_bytes(protkey, keysize); 349a45a5c7dSIngo Franzki 350a45a5c7dSIngo Franzki return 0; 351a45a5c7dSIngo Franzki } 352a45a5c7dSIngo Franzki 353a45a5c7dSIngo Franzki /* 354cb26b9ffSIngo Franzki * Verify if a protected key is still valid 355cb26b9ffSIngo Franzki */ 356*f370f45cSHarald Freudenberger static int pkey_verifyprotkey(const u8 *protkey, u32 protkeylen, 357*f370f45cSHarald Freudenberger u32 protkeytype) 358cb26b9ffSIngo Franzki { 359cb26b9ffSIngo Franzki struct { 360cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 361cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 362cb26b9ffSIngo Franzki } param; 363cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 364cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 365*f370f45cSHarald Freudenberger unsigned int k, pkeylen; 36646a29b03SHarald Freudenberger unsigned long fc; 367cb26b9ffSIngo Franzki 368*f370f45cSHarald Freudenberger switch (protkeytype) { 369cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 370*f370f45cSHarald Freudenberger pkeylen = 16 + AES_WK_VP_SIZE; 371cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 372cb26b9ffSIngo Franzki break; 373cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 374*f370f45cSHarald Freudenberger pkeylen = 24 + AES_WK_VP_SIZE; 375cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 376cb26b9ffSIngo Franzki break; 377cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 378*f370f45cSHarald Freudenberger pkeylen = 32 + AES_WK_VP_SIZE; 379cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 380cb26b9ffSIngo Franzki break; 381cb26b9ffSIngo Franzki default: 382*f370f45cSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %u\n", __func__, 383*f370f45cSHarald Freudenberger protkeytype); 384*f370f45cSHarald Freudenberger return -EINVAL; 385*f370f45cSHarald Freudenberger } 386*f370f45cSHarald Freudenberger if (protkeylen != pkeylen) { 387*f370f45cSHarald Freudenberger DEBUG_ERR("%s invalid protected key size %u for keytype %u\n", 388*f370f45cSHarald Freudenberger __func__, protkeylen, protkeytype); 389cb26b9ffSIngo Franzki return -EINVAL; 390cb26b9ffSIngo Franzki } 391cb26b9ffSIngo Franzki 392cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 393cb26b9ffSIngo Franzki 394cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 395*f370f45cSHarald Freudenberger memcpy(param.key, protkey, protkeylen); 396cb26b9ffSIngo Franzki 397cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 398cb26b9ffSIngo Franzki sizeof(null_msg)); 399cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 400cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 401cb26b9ffSIngo Franzki return -EKEYREJECTED; 402cb26b9ffSIngo Franzki } 403cb26b9ffSIngo Franzki 404cb26b9ffSIngo Franzki return 0; 405cb26b9ffSIngo Franzki } 406cb26b9ffSIngo Franzki 407cb26b9ffSIngo Franzki /* 408fb1136d6SIngo Franzki * Transform a non-CCA key token into a protected key 409fb1136d6SIngo Franzki */ 410183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, 411*f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 412fb1136d6SIngo Franzki { 413fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 41446a29b03SHarald Freudenberger u8 *tmpbuf = NULL; 41546a29b03SHarald Freudenberger int rc = -EINVAL; 416fb1136d6SIngo Franzki 417fb1136d6SIngo Franzki switch (hdr->version) { 418888edbc4SHarald Freudenberger case TOKVER_PROTECTED_KEY: { 419888edbc4SHarald Freudenberger struct protaeskeytoken *t; 420fb1136d6SIngo Franzki 421888edbc4SHarald Freudenberger if (keylen != sizeof(struct protaeskeytoken)) 422888edbc4SHarald Freudenberger goto out; 423fb1136d6SIngo Franzki t = (struct protaeskeytoken *)key; 424*f370f45cSHarald Freudenberger rc = pkey_verifyprotkey(t->protkey, t->len, t->keytype); 425*f370f45cSHarald Freudenberger if (rc) 426*f370f45cSHarald Freudenberger goto out; 427*f370f45cSHarald Freudenberger memcpy(protkey, t->protkey, t->len); 428*f370f45cSHarald Freudenberger *protkeylen = t->len; 429*f370f45cSHarald Freudenberger *protkeytype = t->keytype; 430888edbc4SHarald Freudenberger break; 431888edbc4SHarald Freudenberger } 432888edbc4SHarald Freudenberger case TOKVER_CLEAR_KEY: { 433888edbc4SHarald Freudenberger struct clearaeskeytoken *t; 434888edbc4SHarald Freudenberger struct pkey_clrkey ckey; 43555d0a513SHarald Freudenberger union u_tmpbuf { 43655d0a513SHarald Freudenberger u8 skey[SECKEYBLOBSIZE]; 43755d0a513SHarald Freudenberger u8 ep11key[MAXEP11AESKEYBLOBSIZE]; 43855d0a513SHarald Freudenberger }; 43955d0a513SHarald Freudenberger size_t tmpbuflen = sizeof(union u_tmpbuf); 440fb1136d6SIngo Franzki 441888edbc4SHarald Freudenberger if (keylen < sizeof(struct clearaeskeytoken)) 442888edbc4SHarald Freudenberger goto out; 443888edbc4SHarald Freudenberger t = (struct clearaeskeytoken *)key; 444888edbc4SHarald Freudenberger if (keylen != sizeof(*t) + t->len) 445888edbc4SHarald Freudenberger goto out; 4462004b57cSHarald Freudenberger if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) || 4472004b57cSHarald Freudenberger (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) || 4482004b57cSHarald Freudenberger (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) 449888edbc4SHarald Freudenberger memcpy(ckey.clrkey, t->clearkey, t->len); 450888edbc4SHarald Freudenberger else 451888edbc4SHarald Freudenberger goto out; 45255d0a513SHarald Freudenberger /* alloc temp key buffer space */ 45355d0a513SHarald Freudenberger tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 45455d0a513SHarald Freudenberger if (!tmpbuf) { 45555d0a513SHarald Freudenberger rc = -ENOMEM; 45655d0a513SHarald Freudenberger goto out; 45755d0a513SHarald Freudenberger } 458888edbc4SHarald Freudenberger /* try direct way with the PCKMO instruction */ 459*f370f45cSHarald Freudenberger rc = pkey_clr2protkey(t->keytype, ckey.clrkey, 460*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 461888edbc4SHarald Freudenberger if (rc == 0) 462888edbc4SHarald Freudenberger break; 463888edbc4SHarald Freudenberger /* PCKMO failed, so try the CCA secure key way */ 46443cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 465888edbc4SHarald Freudenberger rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, 46655d0a513SHarald Freudenberger ckey.clrkey, tmpbuf); 467888edbc4SHarald Freudenberger if (rc == 0) 468*f370f45cSHarald Freudenberger rc = pkey_skey2pkey(tmpbuf, 469*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 470888edbc4SHarald Freudenberger if (rc == 0) 471888edbc4SHarald Freudenberger break; 47255d0a513SHarald Freudenberger /* if the CCA way also failed, let's try via EP11 */ 47355d0a513SHarald Freudenberger rc = pkey_clr2ep11key(ckey.clrkey, t->len, 47455d0a513SHarald Freudenberger tmpbuf, &tmpbuflen); 47555d0a513SHarald Freudenberger if (rc == 0) 476*f370f45cSHarald Freudenberger rc = pkey_ep11key2pkey(tmpbuf, 477*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 47855d0a513SHarald Freudenberger /* now we should really have an protected key */ 479888edbc4SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", 480888edbc4SHarald Freudenberger __func__); 481888edbc4SHarald Freudenberger break; 482888edbc4SHarald Freudenberger } 48355d0a513SHarald Freudenberger case TOKVER_EP11_AES: { 48455d0a513SHarald Freudenberger /* check ep11 key for exportable as protected key */ 485fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 48655d0a513SHarald Freudenberger if (rc) 48755d0a513SHarald Freudenberger goto out; 488*f370f45cSHarald Freudenberger rc = pkey_ep11key2pkey(key, 489*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 49055d0a513SHarald Freudenberger break; 49155d0a513SHarald Freudenberger } 492fa6999e3SHarald Freudenberger case TOKVER_EP11_AES_WITH_HEADER: 493fa6999e3SHarald Freudenberger /* check ep11 key with header for exportable as protected key */ 494fa6999e3SHarald Freudenberger rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1); 495fa6999e3SHarald Freudenberger if (rc) 496fa6999e3SHarald Freudenberger goto out; 497fa6999e3SHarald Freudenberger rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header), 498*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 499fa6999e3SHarald Freudenberger break; 500fb1136d6SIngo Franzki default: 501fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 502fb1136d6SIngo Franzki __func__, hdr->version); 503888edbc4SHarald Freudenberger rc = -EINVAL; 504fb1136d6SIngo Franzki } 505888edbc4SHarald Freudenberger 506888edbc4SHarald Freudenberger out: 50755d0a513SHarald Freudenberger kfree(tmpbuf); 508888edbc4SHarald Freudenberger return rc; 509fb1136d6SIngo Franzki } 510fb1136d6SIngo Franzki 511fb1136d6SIngo Franzki /* 512fb1136d6SIngo Franzki * Transform a CCA internal key token into a protected key 513fb1136d6SIngo Franzki */ 514183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, 515*f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 516fb1136d6SIngo Franzki { 517fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 518fb1136d6SIngo Franzki 519fb1136d6SIngo Franzki switch (hdr->version) { 520fb1136d6SIngo Franzki case TOKVER_CCA_AES: 521fb1136d6SIngo Franzki if (keylen != sizeof(struct secaeskeytoken)) 522fb1136d6SIngo Franzki return -EINVAL; 523f2bbc96eSHarald Freudenberger break; 524f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 525f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 526f2bbc96eSHarald Freudenberger return -EINVAL; 527f2bbc96eSHarald Freudenberger break; 528fb1136d6SIngo Franzki default: 529fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 530fb1136d6SIngo Franzki __func__, hdr->version); 531fb1136d6SIngo Franzki return -EINVAL; 532fb1136d6SIngo Franzki } 533f2bbc96eSHarald Freudenberger 534*f370f45cSHarald Freudenberger return pkey_skey2pkey(key, protkey, protkeylen, protkeytype); 535fb1136d6SIngo Franzki } 536fb1136d6SIngo Franzki 537fb1136d6SIngo Franzki /* 538fb1136d6SIngo Franzki * Transform a key blob (of any type) into a protected key 539fb1136d6SIngo Franzki */ 540183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen, 541*f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 542fb1136d6SIngo Franzki { 543fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 54446a29b03SHarald Freudenberger int rc; 545fb1136d6SIngo Franzki 546f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) { 547f2bbc96eSHarald Freudenberger DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); 548f2bbc96eSHarald Freudenberger return -EINVAL; 549f2bbc96eSHarald Freudenberger } 550f2bbc96eSHarald Freudenberger 551f2bbc96eSHarald Freudenberger switch (hdr->type) { 552f2bbc96eSHarald Freudenberger case TOKTYPE_NON_CCA: 553*f370f45cSHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, 554*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 555f2bbc96eSHarald Freudenberger break; 556f2bbc96eSHarald Freudenberger case TOKTYPE_CCA_INTERNAL: 557*f370f45cSHarald Freudenberger rc = pkey_ccainttok2pkey(key, keylen, 558*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 559f2bbc96eSHarald Freudenberger break; 560f2bbc96eSHarald Freudenberger default: 561f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 562f2bbc96eSHarald Freudenberger __func__, hdr->type); 563f2bbc96eSHarald Freudenberger return -EINVAL; 564f2bbc96eSHarald Freudenberger } 565f2bbc96eSHarald Freudenberger 566f2bbc96eSHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 567f2bbc96eSHarald Freudenberger return rc; 568f2bbc96eSHarald Freudenberger } 569f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey); 570f2bbc96eSHarald Freudenberger 571f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 572f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 573f2bbc96eSHarald Freudenberger u32 kflags, u8 *keybuf, size_t *keybufsize) 574f2bbc96eSHarald Freudenberger { 575f2bbc96eSHarald Freudenberger int i, card, dom, rc; 576f2bbc96eSHarald Freudenberger 577f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 578f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 579f2bbc96eSHarald Freudenberger return -EINVAL; 580f2bbc96eSHarald Freudenberger 581f2bbc96eSHarald Freudenberger /* check key type and size */ 582f2bbc96eSHarald Freudenberger switch (ktype) { 583f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 584f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 585f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 586f2bbc96eSHarald Freudenberger return -EINVAL; 587f2bbc96eSHarald Freudenberger break; 58855d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 58955d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 59055d0a513SHarald Freudenberger return -EINVAL; 59155d0a513SHarald Freudenberger break; 592f2bbc96eSHarald Freudenberger default: 593f2bbc96eSHarald Freudenberger return -EINVAL; 594f2bbc96eSHarald Freudenberger } 595f2bbc96eSHarald Freudenberger switch (ksize) { 596f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 597f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 598f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 599f2bbc96eSHarald Freudenberger break; 600f2bbc96eSHarald Freudenberger default: 601f2bbc96eSHarald Freudenberger return -EINVAL; 602f2bbc96eSHarald Freudenberger } 603f2bbc96eSHarald Freudenberger 604f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 605f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 606f2bbc96eSHarald Freudenberger card = apqns[i].card; 607f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 60855d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 60955d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, ksize, kflags, 61055d0a513SHarald Freudenberger keybuf, keybufsize); 61155d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 612f2bbc96eSHarald Freudenberger rc = cca_genseckey(card, dom, ksize, keybuf); 613f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 6142004b57cSHarald Freudenberger } else { 6152004b57cSHarald Freudenberger /* TOKVER_CCA_VLSC */ 616f2bbc96eSHarald Freudenberger rc = cca_gencipherkey(card, dom, ksize, kflags, 617f2bbc96eSHarald Freudenberger keybuf, keybufsize); 6182004b57cSHarald Freudenberger } 619f2bbc96eSHarald Freudenberger if (rc == 0) 620f2bbc96eSHarald Freudenberger break; 621f2bbc96eSHarald Freudenberger } 622f2bbc96eSHarald Freudenberger 623f2bbc96eSHarald Freudenberger return rc; 624f2bbc96eSHarald Freudenberger } 625f2bbc96eSHarald Freudenberger 626f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 627f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 628f2bbc96eSHarald Freudenberger u32 kflags, const u8 *clrkey, 629f2bbc96eSHarald Freudenberger u8 *keybuf, size_t *keybufsize) 630f2bbc96eSHarald Freudenberger { 631f2bbc96eSHarald Freudenberger int i, card, dom, rc; 632f2bbc96eSHarald Freudenberger 633f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 634f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 635f2bbc96eSHarald Freudenberger return -EINVAL; 636f2bbc96eSHarald Freudenberger 637f2bbc96eSHarald Freudenberger /* check key type and size */ 638f2bbc96eSHarald Freudenberger switch (ktype) { 639f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 640f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 641f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 642f2bbc96eSHarald Freudenberger return -EINVAL; 643f2bbc96eSHarald Freudenberger break; 64455d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 64555d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 64655d0a513SHarald Freudenberger return -EINVAL; 64755d0a513SHarald Freudenberger break; 648f2bbc96eSHarald Freudenberger default: 649f2bbc96eSHarald Freudenberger return -EINVAL; 650f2bbc96eSHarald Freudenberger } 651f2bbc96eSHarald Freudenberger switch (ksize) { 652f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 653f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 654f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 655f2bbc96eSHarald Freudenberger break; 656f2bbc96eSHarald Freudenberger default: 657f2bbc96eSHarald Freudenberger return -EINVAL; 658f2bbc96eSHarald Freudenberger } 659f2bbc96eSHarald Freudenberger 66043cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 66143cb5a7cSHarald Freudenberger 662f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 663f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 664f2bbc96eSHarald Freudenberger card = apqns[i].card; 665f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 66655d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 66755d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, ksize, kflags, 66855d0a513SHarald Freudenberger clrkey, keybuf, keybufsize); 66955d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 670f2bbc96eSHarald Freudenberger rc = cca_clr2seckey(card, dom, ksize, 671f2bbc96eSHarald Freudenberger clrkey, keybuf); 672f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 6732004b57cSHarald Freudenberger } else { 6742004b57cSHarald Freudenberger /* TOKVER_CCA_VLSC */ 675f2bbc96eSHarald Freudenberger rc = cca_clr2cipherkey(card, dom, ksize, kflags, 676f2bbc96eSHarald Freudenberger clrkey, keybuf, keybufsize); 6772004b57cSHarald Freudenberger } 678f2bbc96eSHarald Freudenberger if (rc == 0) 679f2bbc96eSHarald Freudenberger break; 680f2bbc96eSHarald Freudenberger } 681f2bbc96eSHarald Freudenberger 682f2bbc96eSHarald Freudenberger return rc; 683f2bbc96eSHarald Freudenberger } 684f2bbc96eSHarald Freudenberger 685f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen, 686f2bbc96eSHarald Freudenberger u16 *cardnr, u16 *domain, 687f2bbc96eSHarald Freudenberger enum pkey_key_type *ktype, 688f2bbc96eSHarald Freudenberger enum pkey_key_size *ksize, u32 *flags) 689f2bbc96eSHarald Freudenberger { 690f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 69146a29b03SHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 69246a29b03SHarald Freudenberger int rc; 693f2bbc96eSHarald Freudenberger 69455d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 695f2bbc96eSHarald Freudenberger return -EINVAL; 696f2bbc96eSHarald Freudenberger 6972004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 6982004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 699f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 700f2bbc96eSHarald Freudenberger 701f2bbc96eSHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 702f2bbc96eSHarald Freudenberger if (rc) 703f2bbc96eSHarald Freudenberger goto out; 704f2bbc96eSHarald Freudenberger if (ktype) 705f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_DATA; 706f2bbc96eSHarald Freudenberger if (ksize) 707f2bbc96eSHarald Freudenberger *ksize = (enum pkey_key_size)t->bitsize; 708f2bbc96eSHarald Freudenberger 709f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 71032ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); 711f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 712f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 713f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 714f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 715f2bbc96eSHarald Freudenberger *cardnr, *domain, 71632ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, 71732ca04bbSHarald Freudenberger 0, t->mkvp, 1); 718f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 719f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 720f2bbc96eSHarald Freudenberger } 721f2bbc96eSHarald Freudenberger if (rc) 722f2bbc96eSHarald Freudenberger goto out; 723f2bbc96eSHarald Freudenberger 724f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 725f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 726f2bbc96eSHarald Freudenberger 7272004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 7282004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 729f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 730f2bbc96eSHarald Freudenberger 731f2bbc96eSHarald Freudenberger rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 732f2bbc96eSHarald Freudenberger if (rc) 733f2bbc96eSHarald Freudenberger goto out; 734f2bbc96eSHarald Freudenberger if (ktype) 735f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_CIPHER; 736f2bbc96eSHarald Freudenberger if (ksize) { 737f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_UNKNOWN; 738f2bbc96eSHarald Freudenberger if (!t->plfver && t->wpllen == 512) 739f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_128; 740f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 741f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_192; 742f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 743f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_256; 744f2bbc96eSHarald Freudenberger } 745f2bbc96eSHarald Freudenberger 746f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 74732ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); 748f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 749f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 750f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 751f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 752f2bbc96eSHarald Freudenberger *cardnr, *domain, 75332ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, 75432ca04bbSHarald Freudenberger 0, t->mkvp0, 1); 755f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 756f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 757f2bbc96eSHarald Freudenberger } 758f2bbc96eSHarald Freudenberger if (rc) 759f2bbc96eSHarald Freudenberger goto out; 760f2bbc96eSHarald Freudenberger 761f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 762f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 763f2bbc96eSHarald Freudenberger 7642004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 7652004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES) { 76655d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 76755d0a513SHarald Freudenberger 768fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 76955d0a513SHarald Freudenberger if (rc) 77055d0a513SHarald Freudenberger goto out; 77155d0a513SHarald Freudenberger if (ktype) 77255d0a513SHarald Freudenberger *ktype = PKEY_TYPE_EP11; 77355d0a513SHarald Freudenberger if (ksize) 77455d0a513SHarald Freudenberger *ksize = kb->head.keybitlen; 77555d0a513SHarald Freudenberger 77655d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 77755d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 77855d0a513SHarald Freudenberger if (rc) 77955d0a513SHarald Freudenberger goto out; 78055d0a513SHarald Freudenberger 78155d0a513SHarald Freudenberger if (flags) 78255d0a513SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 78355d0a513SHarald Freudenberger 78455d0a513SHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 78555d0a513SHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 78655d0a513SHarald Freudenberger 7872004b57cSHarald Freudenberger } else { 788f2bbc96eSHarald Freudenberger rc = -EINVAL; 7892004b57cSHarald Freudenberger } 790f2bbc96eSHarald Freudenberger 791f2bbc96eSHarald Freudenberger out: 792f2bbc96eSHarald Freudenberger kfree(_apqns); 793f2bbc96eSHarald Freudenberger return rc; 794f2bbc96eSHarald Freudenberger } 795f2bbc96eSHarald Freudenberger 796f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 797f2bbc96eSHarald Freudenberger const u8 *key, size_t keylen, 798*f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 799f2bbc96eSHarald Freudenberger { 800f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 80146a29b03SHarald Freudenberger int i, card, dom, rc; 802f2bbc96eSHarald Freudenberger 803f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 804f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 805f2bbc96eSHarald Freudenberger return -EINVAL; 806f2bbc96eSHarald Freudenberger 807fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 808fb1136d6SIngo Franzki return -EINVAL; 809fb1136d6SIngo Franzki 81055d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL) { 81155d0a513SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 812f2bbc96eSHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 813f2bbc96eSHarald Freudenberger return -EINVAL; 814f2bbc96eSHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 815f2bbc96eSHarald Freudenberger return -EINVAL; 81655d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 817f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 818f2bbc96eSHarald Freudenberger return -EINVAL; 819f2bbc96eSHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 820f2bbc96eSHarald Freudenberger return -EINVAL; 82155d0a513SHarald Freudenberger } else { 822f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 823f2bbc96eSHarald Freudenberger __func__, hdr->version); 824fb1136d6SIngo Franzki return -EINVAL; 825fb1136d6SIngo Franzki } 82655d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 82755d0a513SHarald Freudenberger if (hdr->version == TOKVER_EP11_AES) { 82855d0a513SHarald Freudenberger if (keylen < sizeof(struct ep11keyblob)) 82955d0a513SHarald Freudenberger return -EINVAL; 830fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 83155d0a513SHarald Freudenberger return -EINVAL; 83255d0a513SHarald Freudenberger } else { 833*f370f45cSHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, 834*f370f45cSHarald Freudenberger protkey, protkeylen, 835*f370f45cSHarald Freudenberger protkeytype); 83655d0a513SHarald Freudenberger } 83755d0a513SHarald Freudenberger } else { 838f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 839f2bbc96eSHarald Freudenberger __func__, hdr->type); 840f2bbc96eSHarald Freudenberger return -EINVAL; 841fb1136d6SIngo Franzki } 842f2bbc96eSHarald Freudenberger 84343cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 84443cb5a7cSHarald Freudenberger 845f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 846f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 847f2bbc96eSHarald Freudenberger card = apqns[i].card; 848f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 8492004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 8502004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 851*f370f45cSHarald Freudenberger rc = cca_sec2protkey(card, dom, key, 852*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 8532004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 8542004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 855*f370f45cSHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, 856*f370f45cSHarald Freudenberger protkey, protkeylen, 857*f370f45cSHarald Freudenberger protkeytype); 8582004b57cSHarald Freudenberger } else { 8592004b57cSHarald Freudenberger /* EP11 AES secure key blob */ 86055d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 86155d0a513SHarald Freudenberger 862fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 863*f370f45cSHarald Freudenberger protkey, protkeylen, 864*f370f45cSHarald Freudenberger protkeytype); 86555d0a513SHarald Freudenberger } 866f2bbc96eSHarald Freudenberger if (rc == 0) 867f2bbc96eSHarald Freudenberger break; 868f2bbc96eSHarald Freudenberger } 869f2bbc96eSHarald Freudenberger 870f2bbc96eSHarald Freudenberger return rc; 871f2bbc96eSHarald Freudenberger } 872f2bbc96eSHarald Freudenberger 873f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 874f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 875f2bbc96eSHarald Freudenberger { 876f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 87746a29b03SHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 87846a29b03SHarald Freudenberger int rc; 879f2bbc96eSHarald Freudenberger 88055d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || flags == 0) 881f2bbc96eSHarald Freudenberger return -EINVAL; 882f2bbc96eSHarald Freudenberger 88343cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 88443cb5a7cSHarald Freudenberger 8852004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 8862004b57cSHarald Freudenberger (hdr->version == TOKVER_EP11_AES_WITH_HEADER || 8872004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && 8882004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 889fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) 890fa6999e3SHarald Freudenberger (key + sizeof(struct ep11kblob_header)); 89146a29b03SHarald Freudenberger int minhwtype = 0, api = 0; 892fa6999e3SHarald Freudenberger 893fa6999e3SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 894fa6999e3SHarald Freudenberger return -EINVAL; 895fa6999e3SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 896fa6999e3SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 897fa6999e3SHarald Freudenberger api = EP11_API_V; 898fa6999e3SHarald Freudenberger } 899fa6999e3SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 900fa6999e3SHarald Freudenberger minhwtype, api, kb->wkvp); 901fa6999e3SHarald Freudenberger if (rc) 902fa6999e3SHarald Freudenberger goto out; 9032004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 9042004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 9052004b57cSHarald Freudenberger is_ep11_keyblob(key)) { 90655d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 90746a29b03SHarald Freudenberger int minhwtype = 0, api = 0; 90855d0a513SHarald Freudenberger 90955d0a513SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 91055d0a513SHarald Freudenberger return -EINVAL; 91155d0a513SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 91255d0a513SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 91355d0a513SHarald Freudenberger api = EP11_API_V; 91455d0a513SHarald Freudenberger } 91555d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 91655d0a513SHarald Freudenberger minhwtype, api, kb->wkvp); 91755d0a513SHarald Freudenberger if (rc) 91855d0a513SHarald Freudenberger goto out; 91955d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 920f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 92146a29b03SHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 922f2bbc96eSHarald Freudenberger 923f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 924f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 925f2bbc96eSHarald Freudenberger 926f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 927f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp; 928f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 929f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp; 93055d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 931f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 932f2bbc96eSHarald Freudenberger 933f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 934f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 935f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp0; 936f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 937f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp0; 93855d0a513SHarald Freudenberger } else { 93955d0a513SHarald Freudenberger /* unknown cca internal token type */ 94055d0a513SHarald Freudenberger return -EINVAL; 941f2bbc96eSHarald Freudenberger } 942f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 94332ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 94432ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 945f2bbc96eSHarald Freudenberger if (rc) 946f2bbc96eSHarald Freudenberger goto out; 947fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 948fa6999e3SHarald Freudenberger struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; 94946a29b03SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 950fa6999e3SHarald Freudenberger 951fa6999e3SHarald Freudenberger if (t->secid == 0x20) { 952fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 953fa6999e3SHarald Freudenberger cur_mkvp = t->mkvp; 954fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 955fa6999e3SHarald Freudenberger old_mkvp = t->mkvp; 956fa6999e3SHarald Freudenberger } else { 957fa6999e3SHarald Freudenberger /* unknown cca internal 2 token type */ 958fa6999e3SHarald Freudenberger return -EINVAL; 959fa6999e3SHarald Freudenberger } 960fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 961fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 962fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 963fa6999e3SHarald Freudenberger if (rc) 964fa6999e3SHarald Freudenberger goto out; 9652004b57cSHarald Freudenberger } else { 96655d0a513SHarald Freudenberger return -EINVAL; 9672004b57cSHarald Freudenberger } 96855d0a513SHarald Freudenberger 969f2bbc96eSHarald Freudenberger if (apqns) { 970f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 971f2bbc96eSHarald Freudenberger rc = -ENOSPC; 972f2bbc96eSHarald Freudenberger else 973f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 974f2bbc96eSHarald Freudenberger } 975f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 976f2bbc96eSHarald Freudenberger 977f2bbc96eSHarald Freudenberger out: 978f2bbc96eSHarald Freudenberger kfree(_apqns); 979f2bbc96eSHarald Freudenberger return rc; 980f2bbc96eSHarald Freudenberger } 981f2bbc96eSHarald Freudenberger 982f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype, 983f2bbc96eSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 984f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 985f2bbc96eSHarald Freudenberger { 986f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 98746a29b03SHarald Freudenberger int rc; 988f2bbc96eSHarald Freudenberger 98943cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 99043cb5a7cSHarald Freudenberger 991f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 992f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 993f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 994f2bbc96eSHarald Freudenberger 995f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 996f2bbc96eSHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 997f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 998f2bbc96eSHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 999f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 1000f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 1001f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 100232ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 100332ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 1004f2bbc96eSHarald Freudenberger if (rc) 1005f2bbc96eSHarald Freudenberger goto out; 1006fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_ECC) { 1007fa6999e3SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 1008fa6999e3SHarald Freudenberger 1009fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 1010fa6999e3SHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 1011fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 1012fa6999e3SHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 1013fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 1014fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 1015fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 1016fa6999e3SHarald Freudenberger if (rc) 1017fa6999e3SHarald Freudenberger goto out; 1018fa6999e3SHarald Freudenberger 1019fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_EP11 || 1020fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_AES || 1021fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_ECC) { 102255d0a513SHarald Freudenberger u8 *wkvp = NULL; 102355d0a513SHarald Freudenberger 102455d0a513SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 102555d0a513SHarald Freudenberger wkvp = cur_mkvp; 102655d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 102755d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, wkvp); 102855d0a513SHarald Freudenberger if (rc) 102955d0a513SHarald Freudenberger goto out; 103055d0a513SHarald Freudenberger 10312004b57cSHarald Freudenberger } else { 103255d0a513SHarald Freudenberger return -EINVAL; 10332004b57cSHarald Freudenberger } 103455d0a513SHarald Freudenberger 1035f2bbc96eSHarald Freudenberger if (apqns) { 1036f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 1037f2bbc96eSHarald Freudenberger rc = -ENOSPC; 1038f2bbc96eSHarald Freudenberger else 1039f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 1040f2bbc96eSHarald Freudenberger } 1041f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 1042f2bbc96eSHarald Freudenberger 1043f2bbc96eSHarald Freudenberger out: 1044f2bbc96eSHarald Freudenberger kfree(_apqns); 1045f2bbc96eSHarald Freudenberger return rc; 1046f2bbc96eSHarald Freudenberger } 1047fb1136d6SIngo Franzki 1048fa6999e3SHarald Freudenberger static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, 1049*f370f45cSHarald Freudenberger const u8 *key, size_t keylen, 1050*f370f45cSHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 1051fa6999e3SHarald Freudenberger { 1052fa6999e3SHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 105346a29b03SHarald Freudenberger int i, card, dom, rc; 1054fa6999e3SHarald Freudenberger 1055fa6999e3SHarald Freudenberger /* check for at least one apqn given */ 1056fa6999e3SHarald Freudenberger if (!apqns || !nr_apqns) 1057fa6999e3SHarald Freudenberger return -EINVAL; 1058fa6999e3SHarald Freudenberger 1059fa6999e3SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 1060fa6999e3SHarald Freudenberger return -EINVAL; 1061fa6999e3SHarald Freudenberger 10622004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 10632004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES_WITH_HEADER && 10642004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1065fa6999e3SHarald Freudenberger /* EP11 AES key blob with header */ 1066fa6999e3SHarald Freudenberger if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1)) 1067fa6999e3SHarald Freudenberger return -EINVAL; 10682004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 10692004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER && 10702004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1071fa6999e3SHarald Freudenberger /* EP11 ECC key blob with header */ 1072fa6999e3SHarald Freudenberger if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1)) 1073fa6999e3SHarald Freudenberger return -EINVAL; 10742004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 10752004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 10762004b57cSHarald Freudenberger is_ep11_keyblob(key)) { 1077fa6999e3SHarald Freudenberger /* EP11 AES key blob with header in session field */ 1078fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 1079fa6999e3SHarald Freudenberger return -EINVAL; 1080fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 1081fa6999e3SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 1082fa6999e3SHarald Freudenberger /* CCA AES data key */ 1083fa6999e3SHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 1084fa6999e3SHarald Freudenberger return -EINVAL; 1085fa6999e3SHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 1086fa6999e3SHarald Freudenberger return -EINVAL; 1087fa6999e3SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1088fa6999e3SHarald Freudenberger /* CCA AES cipher key */ 1089fa6999e3SHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 1090fa6999e3SHarald Freudenberger return -EINVAL; 1091fa6999e3SHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 1092fa6999e3SHarald Freudenberger return -EINVAL; 1093fa6999e3SHarald Freudenberger } else { 1094fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 1095fa6999e3SHarald Freudenberger __func__, hdr->version); 1096fa6999e3SHarald Freudenberger return -EINVAL; 1097fa6999e3SHarald Freudenberger } 1098fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1099fa6999e3SHarald Freudenberger /* CCA ECC (private) key */ 1100fa6999e3SHarald Freudenberger if (keylen < sizeof(struct eccprivkeytoken)) 1101fa6999e3SHarald Freudenberger return -EINVAL; 1102fa6999e3SHarald Freudenberger if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) 1103fa6999e3SHarald Freudenberger return -EINVAL; 1104fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 1105*f370f45cSHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, 1106*f370f45cSHarald Freudenberger protkey, protkeylen, protkeytype); 1107fa6999e3SHarald Freudenberger } else { 1108fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 1109fa6999e3SHarald Freudenberger __func__, hdr->type); 1110fa6999e3SHarald Freudenberger return -EINVAL; 1111fa6999e3SHarald Freudenberger } 1112fa6999e3SHarald Freudenberger 1113fa6999e3SHarald Freudenberger /* simple try all apqns from the list */ 1114fa6999e3SHarald Freudenberger for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 1115fa6999e3SHarald Freudenberger card = apqns[i].card; 1116fa6999e3SHarald Freudenberger dom = apqns[i].domain; 11172004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 11182004b57cSHarald Freudenberger (hdr->version == TOKVER_EP11_AES_WITH_HEADER || 11192004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && 11202004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) 1121fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1122fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 11232004b57cSHarald Freudenberger else if (hdr->type == TOKTYPE_NON_CCA && 11242004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 11252004b57cSHarald Freudenberger is_ep11_keyblob(key)) 1126fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1127fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 1128fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1129fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_AES) 1130fa6999e3SHarald Freudenberger rc = cca_sec2protkey(card, dom, key, protkey, 1131fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1132fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1133fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) 1134fa6999e3SHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, protkey, 1135fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1136fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) 1137fa6999e3SHarald Freudenberger rc = cca_ecc2protkey(card, dom, key, protkey, 1138fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1139fa6999e3SHarald Freudenberger else 1140fa6999e3SHarald Freudenberger return -EINVAL; 1141fa6999e3SHarald Freudenberger } 1142fa6999e3SHarald Freudenberger 1143fa6999e3SHarald Freudenberger return rc; 1144fa6999e3SHarald Freudenberger } 1145fa6999e3SHarald Freudenberger 1146fb1136d6SIngo Franzki /* 1147e80d4af0SHarald Freudenberger * File io functions 1148e80d4af0SHarald Freudenberger */ 1149e80d4af0SHarald Freudenberger 1150f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen) 1151f2bbc96eSHarald Freudenberger { 1152f2bbc96eSHarald Freudenberger if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) 1153f2bbc96eSHarald Freudenberger return ERR_PTR(-EINVAL); 1154f2bbc96eSHarald Freudenberger 11558b57e7c8SMarkus Elfring return memdup_user(ukey, keylen); 1156f2bbc96eSHarald Freudenberger } 1157f2bbc96eSHarald Freudenberger 1158f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 1159f2bbc96eSHarald Freudenberger { 11608b57e7c8SMarkus Elfring if (!uapqns || nr_apqns == 0) 11618b57e7c8SMarkus Elfring return NULL; 1162f2bbc96eSHarald Freudenberger 11638b57e7c8SMarkus Elfring return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); 1164f2bbc96eSHarald Freudenberger } 1165f2bbc96eSHarald Freudenberger 1166e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 1167e80d4af0SHarald Freudenberger unsigned long arg) 1168e80d4af0SHarald Freudenberger { 1169e80d4af0SHarald Freudenberger int rc; 1170e80d4af0SHarald Freudenberger 1171e80d4af0SHarald Freudenberger switch (cmd) { 1172e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1173e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *)arg; 1174e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1175e80d4af0SHarald Freudenberger 1176e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1177e80d4af0SHarald Freudenberger return -EFAULT; 1178efc598e6SHarald Freudenberger rc = cca_genseckey(kgs.cardnr, kgs.domain, 1179efc598e6SHarald Freudenberger kgs.keytype, kgs.seckey.seckey); 1180efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 1181e80d4af0SHarald Freudenberger if (rc) 1182e80d4af0SHarald Freudenberger break; 1183e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1184e80d4af0SHarald Freudenberger return -EFAULT; 1185e80d4af0SHarald Freudenberger break; 1186e80d4af0SHarald Freudenberger } 1187e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1188e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *)arg; 1189e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1190e80d4af0SHarald Freudenberger 1191e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1192e80d4af0SHarald Freudenberger return -EFAULT; 1193efc598e6SHarald Freudenberger rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1194efc598e6SHarald Freudenberger kcs.clrkey.clrkey, kcs.seckey.seckey); 1195efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 1196e80d4af0SHarald Freudenberger if (rc) 1197e80d4af0SHarald Freudenberger break; 1198e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1199e80d4af0SHarald Freudenberger return -EFAULT; 1200e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1201e80d4af0SHarald Freudenberger break; 1202e80d4af0SHarald Freudenberger } 1203e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1204e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *)arg; 1205e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1206e80d4af0SHarald Freudenberger 1207e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1208e80d4af0SHarald Freudenberger return -EFAULT; 1209*f370f45cSHarald Freudenberger ksp.protkey.len = sizeof(ksp.protkey.protkey); 1210efc598e6SHarald Freudenberger rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 1211efc598e6SHarald Freudenberger ksp.seckey.seckey, ksp.protkey.protkey, 1212aab73d27SHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1213efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 1214e80d4af0SHarald Freudenberger if (rc) 1215e80d4af0SHarald Freudenberger break; 1216e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1217e80d4af0SHarald Freudenberger return -EFAULT; 1218e80d4af0SHarald Freudenberger break; 1219e80d4af0SHarald Freudenberger } 1220e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1221e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *)arg; 1222e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1223e80d4af0SHarald Freudenberger 1224e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1225e80d4af0SHarald Freudenberger return -EFAULT; 1226*f370f45cSHarald Freudenberger kcp.protkey.len = sizeof(kcp.protkey.protkey); 1227*f370f45cSHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey, 1228*f370f45cSHarald Freudenberger kcp.protkey.protkey, 1229*f370f45cSHarald Freudenberger &kcp.protkey.len, &kcp.protkey.type); 1230ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1231e80d4af0SHarald Freudenberger if (rc) 1232e80d4af0SHarald Freudenberger break; 1233e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1234e80d4af0SHarald Freudenberger return -EFAULT; 1235e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1236e80d4af0SHarald Freudenberger break; 1237e80d4af0SHarald Freudenberger } 1238e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1239e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *)arg; 1240e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1241e80d4af0SHarald Freudenberger 1242e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1243e80d4af0SHarald Freudenberger return -EFAULT; 1244efc598e6SHarald Freudenberger rc = cca_findcard(kfc.seckey.seckey, 1245e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1246efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 1247efc598e6SHarald Freudenberger if (rc < 0) 1248e80d4af0SHarald Freudenberger break; 1249e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1250e80d4af0SHarald Freudenberger return -EFAULT; 1251e80d4af0SHarald Freudenberger break; 1252e80d4af0SHarald Freudenberger } 1253e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1254e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *)arg; 1255e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1256e80d4af0SHarald Freudenberger 1257e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1258e80d4af0SHarald Freudenberger return -EFAULT; 1259*f370f45cSHarald Freudenberger ksp.protkey.len = sizeof(ksp.protkey.protkey); 1260*f370f45cSHarald Freudenberger rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey, 1261*f370f45cSHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1262ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1263e80d4af0SHarald Freudenberger if (rc) 1264e80d4af0SHarald Freudenberger break; 1265e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1266e80d4af0SHarald Freudenberger return -EFAULT; 1267e80d4af0SHarald Freudenberger break; 1268e80d4af0SHarald Freudenberger } 1269e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1270e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *)arg; 1271e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1272e61a6134SHarald Freudenberger 1273e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1274e61a6134SHarald Freudenberger return -EFAULT; 1275e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1276e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1277ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1278e61a6134SHarald Freudenberger if (rc) 1279e61a6134SHarald Freudenberger break; 1280e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1281e61a6134SHarald Freudenberger return -EFAULT; 1282e61a6134SHarald Freudenberger break; 1283e61a6134SHarald Freudenberger } 1284a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1285a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *)arg; 1286a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1287a45a5c7dSIngo Franzki 1288a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1289a45a5c7dSIngo Franzki return -EFAULT; 1290*f370f45cSHarald Freudenberger kgp.protkey.len = sizeof(kgp.protkey.protkey); 1291*f370f45cSHarald Freudenberger rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey, 1292*f370f45cSHarald Freudenberger &kgp.protkey.len, &kgp.protkey.type); 1293a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1294a45a5c7dSIngo Franzki if (rc) 1295a45a5c7dSIngo Franzki break; 1296a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1297a45a5c7dSIngo Franzki return -EFAULT; 1298a45a5c7dSIngo Franzki break; 1299a45a5c7dSIngo Franzki } 1300cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 1301cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *)arg; 1302cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 1303cb26b9ffSIngo Franzki 1304cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 1305cb26b9ffSIngo Franzki return -EFAULT; 1306*f370f45cSHarald Freudenberger rc = pkey_verifyprotkey(kvp.protkey.protkey, 1307*f370f45cSHarald Freudenberger kvp.protkey.len, kvp.protkey.type); 1308cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 1309cb26b9ffSIngo Franzki break; 1310cb26b9ffSIngo Franzki } 1311fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 1312fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *)arg; 1313fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 1314183cb469SHarald Freudenberger u8 *kkey; 1315fb1136d6SIngo Franzki 1316fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 1317fb1136d6SIngo Franzki return -EFAULT; 1318f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1319f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1320f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1321*f370f45cSHarald Freudenberger ktp.protkey.len = sizeof(ktp.protkey.protkey); 1322*f370f45cSHarald Freudenberger rc = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey, 1323*f370f45cSHarald Freudenberger &ktp.protkey.len, &ktp.protkey.type); 1324fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 1325844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1326fb1136d6SIngo Franzki kfree(kkey); 1327fb1136d6SIngo Franzki if (rc) 1328fb1136d6SIngo Franzki break; 1329fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 1330fb1136d6SIngo Franzki return -EFAULT; 1331fb1136d6SIngo Franzki break; 1332fb1136d6SIngo Franzki } 1333f2bbc96eSHarald Freudenberger case PKEY_GENSECK2: { 1334f2bbc96eSHarald Freudenberger struct pkey_genseck2 __user *ugs = (void __user *)arg; 133546a29b03SHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1336f2bbc96eSHarald Freudenberger struct pkey_genseck2 kgs; 1337f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1338f2bbc96eSHarald Freudenberger u8 *kkey; 1339f2bbc96eSHarald Freudenberger 1340f2bbc96eSHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1341f2bbc96eSHarald Freudenberger return -EFAULT; 1342f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 1343f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1344f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1345f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1346f2bbc96eSHarald Freudenberger if (!kkey) { 1347f2bbc96eSHarald Freudenberger kfree(apqns); 1348f2bbc96eSHarald Freudenberger return -ENOMEM; 1349f2bbc96eSHarald Freudenberger } 1350f2bbc96eSHarald Freudenberger rc = pkey_genseckey2(apqns, kgs.apqn_entries, 1351f2bbc96eSHarald Freudenberger kgs.type, kgs.size, kgs.keygenflags, 1352f2bbc96eSHarald Freudenberger kkey, &klen); 1353f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 1354f2bbc96eSHarald Freudenberger kfree(apqns); 1355f2bbc96eSHarald Freudenberger if (rc) { 1356f2bbc96eSHarald Freudenberger kfree(kkey); 1357f2bbc96eSHarald Freudenberger break; 1358f2bbc96eSHarald Freudenberger } 1359f2bbc96eSHarald Freudenberger if (kgs.key) { 1360f2bbc96eSHarald Freudenberger if (kgs.keylen < klen) { 1361f2bbc96eSHarald Freudenberger kfree(kkey); 1362f2bbc96eSHarald Freudenberger return -EINVAL; 1363f2bbc96eSHarald Freudenberger } 1364f2bbc96eSHarald Freudenberger if (copy_to_user(kgs.key, kkey, klen)) { 1365f2bbc96eSHarald Freudenberger kfree(kkey); 1366f2bbc96eSHarald Freudenberger return -EFAULT; 1367f2bbc96eSHarald Freudenberger } 1368f2bbc96eSHarald Freudenberger } 1369f2bbc96eSHarald Freudenberger kgs.keylen = klen; 1370f2bbc96eSHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1371f2bbc96eSHarald Freudenberger rc = -EFAULT; 1372f2bbc96eSHarald Freudenberger kfree(kkey); 1373f2bbc96eSHarald Freudenberger break; 1374f2bbc96eSHarald Freudenberger } 1375f2bbc96eSHarald Freudenberger case PKEY_CLR2SECK2: { 1376f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 __user *ucs = (void __user *)arg; 137746a29b03SHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1378f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 kcs; 1379f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1380f2bbc96eSHarald Freudenberger u8 *kkey; 1381f2bbc96eSHarald Freudenberger 1382f2bbc96eSHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1383f2bbc96eSHarald Freudenberger return -EFAULT; 1384f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 1385f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1386f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1387f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1388f2bbc96eSHarald Freudenberger if (!kkey) { 1389f2bbc96eSHarald Freudenberger kfree(apqns); 1390f2bbc96eSHarald Freudenberger return -ENOMEM; 1391f2bbc96eSHarald Freudenberger } 1392f2bbc96eSHarald Freudenberger rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 1393f2bbc96eSHarald Freudenberger kcs.type, kcs.size, kcs.keygenflags, 1394f2bbc96eSHarald Freudenberger kcs.clrkey.clrkey, kkey, &klen); 1395f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 1396f2bbc96eSHarald Freudenberger kfree(apqns); 1397f2bbc96eSHarald Freudenberger if (rc) { 1398f2bbc96eSHarald Freudenberger kfree(kkey); 1399f2bbc96eSHarald Freudenberger break; 1400f2bbc96eSHarald Freudenberger } 1401f2bbc96eSHarald Freudenberger if (kcs.key) { 1402f2bbc96eSHarald Freudenberger if (kcs.keylen < klen) { 1403f2bbc96eSHarald Freudenberger kfree(kkey); 1404f2bbc96eSHarald Freudenberger return -EINVAL; 1405f2bbc96eSHarald Freudenberger } 1406f2bbc96eSHarald Freudenberger if (copy_to_user(kcs.key, kkey, klen)) { 1407f2bbc96eSHarald Freudenberger kfree(kkey); 1408f2bbc96eSHarald Freudenberger return -EFAULT; 1409f2bbc96eSHarald Freudenberger } 1410f2bbc96eSHarald Freudenberger } 1411f2bbc96eSHarald Freudenberger kcs.keylen = klen; 1412f2bbc96eSHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1413f2bbc96eSHarald Freudenberger rc = -EFAULT; 1414f2bbc96eSHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1415f2bbc96eSHarald Freudenberger kfree(kkey); 1416f2bbc96eSHarald Freudenberger break; 1417f2bbc96eSHarald Freudenberger } 1418f2bbc96eSHarald Freudenberger case PKEY_VERIFYKEY2: { 1419f2bbc96eSHarald Freudenberger struct pkey_verifykey2 __user *uvk = (void __user *)arg; 1420f2bbc96eSHarald Freudenberger struct pkey_verifykey2 kvk; 1421f2bbc96eSHarald Freudenberger u8 *kkey; 1422f2bbc96eSHarald Freudenberger 1423f2bbc96eSHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1424f2bbc96eSHarald Freudenberger return -EFAULT; 1425f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kvk.key, kvk.keylen); 1426f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1427f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1428f2bbc96eSHarald Freudenberger rc = pkey_verifykey2(kkey, kvk.keylen, 1429f2bbc96eSHarald Freudenberger &kvk.cardnr, &kvk.domain, 1430f2bbc96eSHarald Freudenberger &kvk.type, &kvk.size, &kvk.flags); 1431f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 1432f2bbc96eSHarald Freudenberger kfree(kkey); 1433f2bbc96eSHarald Freudenberger if (rc) 1434f2bbc96eSHarald Freudenberger break; 1435f2bbc96eSHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1436f2bbc96eSHarald Freudenberger return -EFAULT; 1437f2bbc96eSHarald Freudenberger break; 1438f2bbc96eSHarald Freudenberger } 1439f2bbc96eSHarald Freudenberger case PKEY_KBLOB2PROTK2: { 1440f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 __user *utp = (void __user *)arg; 1441f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 144246a29b03SHarald Freudenberger struct pkey_kblob2pkey2 ktp; 1443f2bbc96eSHarald Freudenberger u8 *kkey; 1444f2bbc96eSHarald Freudenberger 1445f2bbc96eSHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1446f2bbc96eSHarald Freudenberger return -EFAULT; 1447f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1448f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1449f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1450f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1451f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1452f2bbc96eSHarald Freudenberger kfree(apqns); 1453f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1454f2bbc96eSHarald Freudenberger } 1455*f370f45cSHarald Freudenberger ktp.protkey.len = sizeof(ktp.protkey.protkey); 1456f2bbc96eSHarald Freudenberger rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 1457*f370f45cSHarald Freudenberger kkey, ktp.keylen, 1458*f370f45cSHarald Freudenberger ktp.protkey.protkey, &ktp.protkey.len, 1459*f370f45cSHarald Freudenberger &ktp.protkey.type); 1460f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 1461f2bbc96eSHarald Freudenberger kfree(apqns); 1462844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1463f2bbc96eSHarald Freudenberger kfree(kkey); 1464f2bbc96eSHarald Freudenberger if (rc) 1465f2bbc96eSHarald Freudenberger break; 1466f2bbc96eSHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1467f2bbc96eSHarald Freudenberger return -EFAULT; 1468f2bbc96eSHarald Freudenberger break; 1469f2bbc96eSHarald Freudenberger } 1470f2bbc96eSHarald Freudenberger case PKEY_APQNS4K: { 1471f2bbc96eSHarald Freudenberger struct pkey_apqns4key __user *uak = (void __user *)arg; 1472f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 147346a29b03SHarald Freudenberger struct pkey_apqns4key kak; 1474f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1475f2bbc96eSHarald Freudenberger u8 *kkey; 1476f2bbc96eSHarald Freudenberger 1477f2bbc96eSHarald Freudenberger if (copy_from_user(&kak, uak, sizeof(kak))) 1478f2bbc96eSHarald Freudenberger return -EFAULT; 1479f2bbc96eSHarald Freudenberger nr_apqns = kak.apqn_entries; 1480f2bbc96eSHarald Freudenberger if (nr_apqns) { 1481f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1482f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1483f2bbc96eSHarald Freudenberger GFP_KERNEL); 1484f2bbc96eSHarald Freudenberger if (!apqns) 1485f2bbc96eSHarald Freudenberger return -ENOMEM; 1486f2bbc96eSHarald Freudenberger } 1487f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kak.key, kak.keylen); 1488f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1489f2bbc96eSHarald Freudenberger kfree(apqns); 1490f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1491f2bbc96eSHarald Freudenberger } 1492f2bbc96eSHarald Freudenberger rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 1493f2bbc96eSHarald Freudenberger apqns, &nr_apqns); 1494f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 1495f2bbc96eSHarald Freudenberger kfree(kkey); 1496f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1497f2bbc96eSHarald Freudenberger kfree(apqns); 1498f2bbc96eSHarald Freudenberger break; 1499f2bbc96eSHarald Freudenberger } 1500f2bbc96eSHarald Freudenberger if (!rc && kak.apqns) { 1501f2bbc96eSHarald Freudenberger if (nr_apqns > kak.apqn_entries) { 1502f2bbc96eSHarald Freudenberger kfree(apqns); 1503f2bbc96eSHarald Freudenberger return -EINVAL; 1504f2bbc96eSHarald Freudenberger } 1505f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1506f2bbc96eSHarald Freudenberger if (len) { 1507f2bbc96eSHarald Freudenberger if (copy_to_user(kak.apqns, apqns, len)) { 1508f2bbc96eSHarald Freudenberger kfree(apqns); 1509f2bbc96eSHarald Freudenberger return -EFAULT; 1510f2bbc96eSHarald Freudenberger } 1511f2bbc96eSHarald Freudenberger } 1512f2bbc96eSHarald Freudenberger } 1513f2bbc96eSHarald Freudenberger kak.apqn_entries = nr_apqns; 1514f2bbc96eSHarald Freudenberger if (copy_to_user(uak, &kak, sizeof(kak))) 1515f2bbc96eSHarald Freudenberger rc = -EFAULT; 1516f2bbc96eSHarald Freudenberger kfree(apqns); 1517f2bbc96eSHarald Freudenberger break; 1518f2bbc96eSHarald Freudenberger } 1519f2bbc96eSHarald Freudenberger case PKEY_APQNS4KT: { 1520f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype __user *uat = (void __user *)arg; 1521f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 152246a29b03SHarald Freudenberger struct pkey_apqns4keytype kat; 1523f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1524f2bbc96eSHarald Freudenberger 1525f2bbc96eSHarald Freudenberger if (copy_from_user(&kat, uat, sizeof(kat))) 1526f2bbc96eSHarald Freudenberger return -EFAULT; 1527f2bbc96eSHarald Freudenberger nr_apqns = kat.apqn_entries; 1528f2bbc96eSHarald Freudenberger if (nr_apqns) { 1529f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1530f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1531f2bbc96eSHarald Freudenberger GFP_KERNEL); 1532f2bbc96eSHarald Freudenberger if (!apqns) 1533f2bbc96eSHarald Freudenberger return -ENOMEM; 1534f2bbc96eSHarald Freudenberger } 1535f2bbc96eSHarald Freudenberger rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 1536f2bbc96eSHarald Freudenberger kat.flags, apqns, &nr_apqns); 1537f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 1538f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1539f2bbc96eSHarald Freudenberger kfree(apqns); 1540f2bbc96eSHarald Freudenberger break; 1541f2bbc96eSHarald Freudenberger } 1542f2bbc96eSHarald Freudenberger if (!rc && kat.apqns) { 1543f2bbc96eSHarald Freudenberger if (nr_apqns > kat.apqn_entries) { 1544f2bbc96eSHarald Freudenberger kfree(apqns); 1545f2bbc96eSHarald Freudenberger return -EINVAL; 1546f2bbc96eSHarald Freudenberger } 1547f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1548f2bbc96eSHarald Freudenberger if (len) { 1549f2bbc96eSHarald Freudenberger if (copy_to_user(kat.apqns, apqns, len)) { 1550f2bbc96eSHarald Freudenberger kfree(apqns); 1551f2bbc96eSHarald Freudenberger return -EFAULT; 1552f2bbc96eSHarald Freudenberger } 1553f2bbc96eSHarald Freudenberger } 1554f2bbc96eSHarald Freudenberger } 1555f2bbc96eSHarald Freudenberger kat.apqn_entries = nr_apqns; 1556f2bbc96eSHarald Freudenberger if (copy_to_user(uat, &kat, sizeof(kat))) 1557f2bbc96eSHarald Freudenberger rc = -EFAULT; 1558f2bbc96eSHarald Freudenberger kfree(apqns); 1559f2bbc96eSHarald Freudenberger break; 1560f2bbc96eSHarald Freudenberger } 1561fa6999e3SHarald Freudenberger case PKEY_KBLOB2PROTK3: { 1562fa6999e3SHarald Freudenberger struct pkey_kblob2pkey3 __user *utp = (void __user *)arg; 1563fa6999e3SHarald Freudenberger u32 protkeylen = PROTKEYBLOBBUFSIZE; 156446a29b03SHarald Freudenberger struct pkey_apqn *apqns = NULL; 156546a29b03SHarald Freudenberger struct pkey_kblob2pkey3 ktp; 1566fa6999e3SHarald Freudenberger u8 *kkey, *protkey; 1567fa6999e3SHarald Freudenberger 1568fa6999e3SHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1569fa6999e3SHarald Freudenberger return -EFAULT; 1570fa6999e3SHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1571fa6999e3SHarald Freudenberger if (IS_ERR(apqns)) 1572fa6999e3SHarald Freudenberger return PTR_ERR(apqns); 1573fa6999e3SHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1574fa6999e3SHarald Freudenberger if (IS_ERR(kkey)) { 1575fa6999e3SHarald Freudenberger kfree(apqns); 1576fa6999e3SHarald Freudenberger return PTR_ERR(kkey); 1577fa6999e3SHarald Freudenberger } 1578fa6999e3SHarald Freudenberger protkey = kmalloc(protkeylen, GFP_KERNEL); 1579fa6999e3SHarald Freudenberger if (!protkey) { 1580fa6999e3SHarald Freudenberger kfree(apqns); 1581fa6999e3SHarald Freudenberger kfree(kkey); 1582fa6999e3SHarald Freudenberger return -ENOMEM; 1583fa6999e3SHarald Freudenberger } 1584*f370f45cSHarald Freudenberger rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, 1585*f370f45cSHarald Freudenberger kkey, ktp.keylen, 1586*f370f45cSHarald Freudenberger protkey, &protkeylen, &ktp.pkeytype); 1587fa6999e3SHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); 1588fa6999e3SHarald Freudenberger kfree(apqns); 1589844cf829SHolger Dengler memzero_explicit(kkey, ktp.keylen); 1590fa6999e3SHarald Freudenberger kfree(kkey); 1591fa6999e3SHarald Freudenberger if (rc) { 1592fa6999e3SHarald Freudenberger kfree(protkey); 1593fa6999e3SHarald Freudenberger break; 1594fa6999e3SHarald Freudenberger } 1595fa6999e3SHarald Freudenberger if (ktp.pkey && ktp.pkeylen) { 1596fa6999e3SHarald Freudenberger if (protkeylen > ktp.pkeylen) { 1597fa6999e3SHarald Freudenberger kfree(protkey); 1598fa6999e3SHarald Freudenberger return -EINVAL; 1599fa6999e3SHarald Freudenberger } 1600fa6999e3SHarald Freudenberger if (copy_to_user(ktp.pkey, protkey, protkeylen)) { 1601fa6999e3SHarald Freudenberger kfree(protkey); 1602fa6999e3SHarald Freudenberger return -EFAULT; 1603fa6999e3SHarald Freudenberger } 1604fa6999e3SHarald Freudenberger } 1605fa6999e3SHarald Freudenberger kfree(protkey); 1606fa6999e3SHarald Freudenberger ktp.pkeylen = protkeylen; 1607fa6999e3SHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1608fa6999e3SHarald Freudenberger return -EFAULT; 1609fa6999e3SHarald Freudenberger break; 1610fa6999e3SHarald Freudenberger } 1611e80d4af0SHarald Freudenberger default: 1612e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1613e80d4af0SHarald Freudenberger return -ENOTTY; 1614e80d4af0SHarald Freudenberger } 1615e80d4af0SHarald Freudenberger 1616e80d4af0SHarald Freudenberger return rc; 1617e80d4af0SHarald Freudenberger } 1618e80d4af0SHarald Freudenberger 1619e80d4af0SHarald Freudenberger /* 1620e80d4af0SHarald Freudenberger * Sysfs and file io operations 1621e80d4af0SHarald Freudenberger */ 1622d632c047SIngo Franzki 1623d632c047SIngo Franzki /* 1624d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1625d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1626d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1627d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1628d632c047SIngo Franzki */ 1629d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1630d632c047SIngo Franzki loff_t off, size_t count) 1631d632c047SIngo Franzki { 1632d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1633d632c047SIngo Franzki struct pkey_protkey protkey; 1634d632c047SIngo Franzki int rc; 1635d632c047SIngo Franzki 1636d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1637d632c047SIngo Franzki return -EINVAL; 1638d632c047SIngo Franzki if (is_xts) 1639d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1640d632c047SIngo Franzki return -EINVAL; 1641d632c047SIngo Franzki 1642d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1643d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1644d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1645d632c047SIngo Franzki protkeytoken.keytype = keytype; 1646d632c047SIngo Franzki 1647*f370f45cSHarald Freudenberger protkey.len = sizeof(protkey.protkey); 1648*f370f45cSHarald Freudenberger rc = pkey_genprotkey(protkeytoken.keytype, 1649*f370f45cSHarald Freudenberger protkey.protkey, &protkey.len, &protkey.type); 1650d632c047SIngo Franzki if (rc) 1651d632c047SIngo Franzki return rc; 1652d632c047SIngo Franzki 1653d632c047SIngo Franzki protkeytoken.len = protkey.len; 1654d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1655d632c047SIngo Franzki 1656d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1657d632c047SIngo Franzki 1658d632c047SIngo Franzki if (is_xts) { 1659*f370f45cSHarald Freudenberger /* xts needs a second protected key, reuse protkey struct */ 1660*f370f45cSHarald Freudenberger protkey.len = sizeof(protkey.protkey); 1661*f370f45cSHarald Freudenberger rc = pkey_genprotkey(protkeytoken.keytype, 1662*f370f45cSHarald Freudenberger protkey.protkey, &protkey.len, &protkey.type); 1663d632c047SIngo Franzki if (rc) 1664d632c047SIngo Franzki return rc; 1665d632c047SIngo Franzki 1666d632c047SIngo Franzki protkeytoken.len = protkey.len; 1667d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1668d632c047SIngo Franzki 1669d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1670d632c047SIngo Franzki sizeof(protkeytoken)); 1671d632c047SIngo Franzki 1672d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1673d632c047SIngo Franzki } 1674d632c047SIngo Franzki 1675d632c047SIngo Franzki return sizeof(protkeytoken); 1676d632c047SIngo Franzki } 1677d632c047SIngo Franzki 1678d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1679d632c047SIngo Franzki struct kobject *kobj, 1680d632c047SIngo Franzki struct bin_attribute *attr, 1681d632c047SIngo Franzki char *buf, loff_t off, 1682d632c047SIngo Franzki size_t count) 1683d632c047SIngo Franzki { 1684d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1685d632c047SIngo Franzki off, count); 1686d632c047SIngo Franzki } 1687d632c047SIngo Franzki 1688d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1689d632c047SIngo Franzki struct kobject *kobj, 1690d632c047SIngo Franzki struct bin_attribute *attr, 1691d632c047SIngo Franzki char *buf, loff_t off, 1692d632c047SIngo Franzki size_t count) 1693d632c047SIngo Franzki { 1694d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1695d632c047SIngo Franzki off, count); 1696d632c047SIngo Franzki } 1697d632c047SIngo Franzki 1698d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1699d632c047SIngo Franzki struct kobject *kobj, 1700d632c047SIngo Franzki struct bin_attribute *attr, 1701d632c047SIngo Franzki char *buf, loff_t off, 1702d632c047SIngo Franzki size_t count) 1703d632c047SIngo Franzki { 1704d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1705d632c047SIngo Franzki off, count); 1706d632c047SIngo Franzki } 1707d632c047SIngo Franzki 1708d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1709d632c047SIngo Franzki struct kobject *kobj, 1710d632c047SIngo Franzki struct bin_attribute *attr, 1711d632c047SIngo Franzki char *buf, loff_t off, 1712d632c047SIngo Franzki size_t count) 1713d632c047SIngo Franzki { 1714d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1715d632c047SIngo Franzki off, count); 1716d632c047SIngo Franzki } 1717d632c047SIngo Franzki 1718d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1719d632c047SIngo Franzki struct kobject *kobj, 1720d632c047SIngo Franzki struct bin_attribute *attr, 1721d632c047SIngo Franzki char *buf, loff_t off, 1722d632c047SIngo Franzki size_t count) 1723d632c047SIngo Franzki { 1724d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1725d632c047SIngo Franzki off, count); 1726d632c047SIngo Franzki } 1727d632c047SIngo Franzki 1728d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1729d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1730d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1731d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1732d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1733d632c047SIngo Franzki 1734d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1735d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1736d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1737d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1738d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1739d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1740d632c047SIngo Franzki NULL 1741d632c047SIngo Franzki }; 1742d632c047SIngo Franzki 1743d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1744d632c047SIngo Franzki .name = "protkey", 1745d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1746d632c047SIngo Franzki }; 1747d632c047SIngo Franzki 1748af504452SIngo Franzki /* 1749af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1750af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1751af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1752af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1753af504452SIngo Franzki */ 1754af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1755af504452SIngo Franzki loff_t off, size_t count) 1756af504452SIngo Franzki { 1757efc598e6SHarald Freudenberger struct pkey_seckey *seckey = (struct pkey_seckey *)buf; 175846a29b03SHarald Freudenberger int rc; 1759af504452SIngo Franzki 1760af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1761af504452SIngo Franzki return -EINVAL; 1762af504452SIngo Franzki if (is_xts) 1763af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1764af504452SIngo Franzki return -EINVAL; 1765af504452SIngo Franzki 1766efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1767af504452SIngo Franzki if (rc) 1768af504452SIngo Franzki return rc; 1769af504452SIngo Franzki 1770af504452SIngo Franzki if (is_xts) { 1771efc598e6SHarald Freudenberger seckey++; 1772efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1773af504452SIngo Franzki if (rc) 1774af504452SIngo Franzki return rc; 1775af504452SIngo Franzki 1776af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1777af504452SIngo Franzki } 1778af504452SIngo Franzki 1779af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1780af504452SIngo Franzki } 1781af504452SIngo Franzki 1782af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1783af504452SIngo Franzki struct kobject *kobj, 1784af504452SIngo Franzki struct bin_attribute *attr, 1785af504452SIngo Franzki char *buf, loff_t off, 1786af504452SIngo Franzki size_t count) 1787af504452SIngo Franzki { 1788af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1789af504452SIngo Franzki off, count); 1790af504452SIngo Franzki } 1791af504452SIngo Franzki 1792af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1793af504452SIngo Franzki struct kobject *kobj, 1794af504452SIngo Franzki struct bin_attribute *attr, 1795af504452SIngo Franzki char *buf, loff_t off, 1796af504452SIngo Franzki size_t count) 1797af504452SIngo Franzki { 1798af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1799af504452SIngo Franzki off, count); 1800af504452SIngo Franzki } 1801af504452SIngo Franzki 1802af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1803af504452SIngo Franzki struct kobject *kobj, 1804af504452SIngo Franzki struct bin_attribute *attr, 1805af504452SIngo Franzki char *buf, loff_t off, 1806af504452SIngo Franzki size_t count) 1807af504452SIngo Franzki { 1808af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1809af504452SIngo Franzki off, count); 1810af504452SIngo Franzki } 1811af504452SIngo Franzki 1812af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1813af504452SIngo Franzki struct kobject *kobj, 1814af504452SIngo Franzki struct bin_attribute *attr, 1815af504452SIngo Franzki char *buf, loff_t off, 1816af504452SIngo Franzki size_t count) 1817af504452SIngo Franzki { 1818af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1819af504452SIngo Franzki off, count); 1820af504452SIngo Franzki } 1821af504452SIngo Franzki 1822af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1823af504452SIngo Franzki struct kobject *kobj, 1824af504452SIngo Franzki struct bin_attribute *attr, 1825af504452SIngo Franzki char *buf, loff_t off, 1826af504452SIngo Franzki size_t count) 1827af504452SIngo Franzki { 1828af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1829af504452SIngo Franzki off, count); 1830af504452SIngo Franzki } 1831af504452SIngo Franzki 1832af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1833af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1834af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1835af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1836af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1837af504452SIngo Franzki 1838af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1839af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1840af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1841af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1842af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1843af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1844af504452SIngo Franzki NULL 1845af504452SIngo Franzki }; 1846af504452SIngo Franzki 1847af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1848af504452SIngo Franzki .name = "ccadata", 1849af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1850af504452SIngo Franzki }; 1851af504452SIngo Franzki 1852f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) 1853f71fee27SIngo Franzki 1854f71fee27SIngo Franzki /* 1855f71fee27SIngo Franzki * Sysfs attribute read function for all secure key ccacipher binary attributes. 1856f71fee27SIngo Franzki * The implementation can not deal with partial reads, because a new random 1857f71fee27SIngo Franzki * secure key blob is generated with each read. In case of partial reads 1858f71fee27SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1859f71fee27SIngo Franzki */ 1860f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, 1861f71fee27SIngo Franzki bool is_xts, char *buf, loff_t off, 1862f71fee27SIngo Franzki size_t count) 1863f71fee27SIngo Franzki { 186455d0a513SHarald Freudenberger size_t keysize = CCACIPHERTOKENSIZE; 186546a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 186646a29b03SHarald Freudenberger int i, rc, card, dom; 1867f71fee27SIngo Franzki 1868f71fee27SIngo Franzki if (off != 0 || count < CCACIPHERTOKENSIZE) 1869f71fee27SIngo Franzki return -EINVAL; 1870f71fee27SIngo Franzki if (is_xts) 1871f71fee27SIngo Franzki if (count < 2 * CCACIPHERTOKENSIZE) 1872f71fee27SIngo Franzki return -EINVAL; 1873f71fee27SIngo Franzki 187455d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 187555d0a513SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 187632ca04bbSHarald Freudenberger ZCRYPT_CEX6, 0, 0, 0, 0); 1877f71fee27SIngo Franzki if (rc) 1878f71fee27SIngo Franzki return rc; 187955d0a513SHarald Freudenberger 188055d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 188155d0a513SHarald Freudenberger 188255d0a513SHarald Freudenberger /* simple try all apqns from the list */ 188355d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 188455d0a513SHarald Freudenberger card = apqns[i] >> 16; 188555d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 188655d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 188755d0a513SHarald Freudenberger if (rc == 0) 188855d0a513SHarald Freudenberger break; 188955d0a513SHarald Freudenberger } 189055d0a513SHarald Freudenberger if (rc) 189155d0a513SHarald Freudenberger return rc; 1892f71fee27SIngo Franzki 1893f71fee27SIngo Franzki if (is_xts) { 1894f71fee27SIngo Franzki keysize = CCACIPHERTOKENSIZE; 189555d0a513SHarald Freudenberger buf += CCACIPHERTOKENSIZE; 189655d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 189755d0a513SHarald Freudenberger if (rc == 0) 1898f71fee27SIngo Franzki return 2 * CCACIPHERTOKENSIZE; 1899f71fee27SIngo Franzki } 1900f71fee27SIngo Franzki 1901f71fee27SIngo Franzki return CCACIPHERTOKENSIZE; 1902f71fee27SIngo Franzki } 1903f71fee27SIngo Franzki 1904f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp, 1905f71fee27SIngo Franzki struct kobject *kobj, 1906f71fee27SIngo Franzki struct bin_attribute *attr, 1907f71fee27SIngo Franzki char *buf, loff_t off, 1908f71fee27SIngo Franzki size_t count) 1909f71fee27SIngo Franzki { 1910f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 1911f71fee27SIngo Franzki off, count); 1912f71fee27SIngo Franzki } 1913f71fee27SIngo Franzki 1914f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp, 1915f71fee27SIngo Franzki struct kobject *kobj, 1916f71fee27SIngo Franzki struct bin_attribute *attr, 1917f71fee27SIngo Franzki char *buf, loff_t off, 1918f71fee27SIngo Franzki size_t count) 1919f71fee27SIngo Franzki { 1920f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 1921f71fee27SIngo Franzki off, count); 1922f71fee27SIngo Franzki } 1923f71fee27SIngo Franzki 1924f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp, 1925f71fee27SIngo Franzki struct kobject *kobj, 1926f71fee27SIngo Franzki struct bin_attribute *attr, 1927f71fee27SIngo Franzki char *buf, loff_t off, 1928f71fee27SIngo Franzki size_t count) 1929f71fee27SIngo Franzki { 1930f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 1931f71fee27SIngo Franzki off, count); 1932f71fee27SIngo Franzki } 1933f71fee27SIngo Franzki 1934f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp, 1935f71fee27SIngo Franzki struct kobject *kobj, 1936f71fee27SIngo Franzki struct bin_attribute *attr, 1937f71fee27SIngo Franzki char *buf, loff_t off, 1938f71fee27SIngo Franzki size_t count) 1939f71fee27SIngo Franzki { 1940f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 1941f71fee27SIngo Franzki off, count); 1942f71fee27SIngo Franzki } 1943f71fee27SIngo Franzki 1944f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp, 1945f71fee27SIngo Franzki struct kobject *kobj, 1946f71fee27SIngo Franzki struct bin_attribute *attr, 1947f71fee27SIngo Franzki char *buf, loff_t off, 1948f71fee27SIngo Franzki size_t count) 1949f71fee27SIngo Franzki { 1950f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 1951f71fee27SIngo Franzki off, count); 1952f71fee27SIngo Franzki } 1953f71fee27SIngo Franzki 1954f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); 1955f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); 1956f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); 1957f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); 1958f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); 1959f71fee27SIngo Franzki 1960f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = { 1961f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128, 1962f71fee27SIngo Franzki &bin_attr_ccacipher_aes_192, 1963f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256, 1964f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128_xts, 1965f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256_xts, 1966f71fee27SIngo Franzki NULL 1967f71fee27SIngo Franzki }; 1968f71fee27SIngo Franzki 1969f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = { 1970f71fee27SIngo Franzki .name = "ccacipher", 1971f71fee27SIngo Franzki .bin_attrs = ccacipher_attrs, 1972f71fee27SIngo Franzki }; 1973f71fee27SIngo Franzki 197455d0a513SHarald Freudenberger /* 197555d0a513SHarald Freudenberger * Sysfs attribute read function for all ep11 aes key binary attributes. 197655d0a513SHarald Freudenberger * The implementation can not deal with partial reads, because a new random 197755d0a513SHarald Freudenberger * secure key blob is generated with each read. In case of partial reads 197855d0a513SHarald Freudenberger * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 197955d0a513SHarald Freudenberger * This function and the sysfs attributes using it provide EP11 key blobs 198055d0a513SHarald Freudenberger * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently 198155d0a513SHarald Freudenberger * 320 bytes. 198255d0a513SHarald Freudenberger */ 198355d0a513SHarald Freudenberger static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, 198455d0a513SHarald Freudenberger bool is_xts, char *buf, loff_t off, 198555d0a513SHarald Freudenberger size_t count) 198655d0a513SHarald Freudenberger { 198755d0a513SHarald Freudenberger size_t keysize = MAXEP11AESKEYBLOBSIZE; 198846a29b03SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 198946a29b03SHarald Freudenberger int i, rc, card, dom; 199055d0a513SHarald Freudenberger 199155d0a513SHarald Freudenberger if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) 199255d0a513SHarald Freudenberger return -EINVAL; 199355d0a513SHarald Freudenberger if (is_xts) 199455d0a513SHarald Freudenberger if (count < 2 * MAXEP11AESKEYBLOBSIZE) 199555d0a513SHarald Freudenberger return -EINVAL; 199655d0a513SHarald Freudenberger 199755d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 199855d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 199955d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 200055d0a513SHarald Freudenberger if (rc) 200155d0a513SHarald Freudenberger return rc; 200255d0a513SHarald Freudenberger 200355d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 200455d0a513SHarald Freudenberger 200555d0a513SHarald Freudenberger /* simple try all apqns from the list */ 200655d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 200755d0a513SHarald Freudenberger card = apqns[i] >> 16; 200855d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 200955d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 201055d0a513SHarald Freudenberger if (rc == 0) 201155d0a513SHarald Freudenberger break; 201255d0a513SHarald Freudenberger } 201355d0a513SHarald Freudenberger if (rc) 201455d0a513SHarald Freudenberger return rc; 201555d0a513SHarald Freudenberger 201655d0a513SHarald Freudenberger if (is_xts) { 201755d0a513SHarald Freudenberger keysize = MAXEP11AESKEYBLOBSIZE; 201855d0a513SHarald Freudenberger buf += MAXEP11AESKEYBLOBSIZE; 201955d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 202055d0a513SHarald Freudenberger if (rc == 0) 202155d0a513SHarald Freudenberger return 2 * MAXEP11AESKEYBLOBSIZE; 202255d0a513SHarald Freudenberger } 202355d0a513SHarald Freudenberger 202455d0a513SHarald Freudenberger return MAXEP11AESKEYBLOBSIZE; 202555d0a513SHarald Freudenberger } 202655d0a513SHarald Freudenberger 202755d0a513SHarald Freudenberger static ssize_t ep11_aes_128_read(struct file *filp, 202855d0a513SHarald Freudenberger struct kobject *kobj, 202955d0a513SHarald Freudenberger struct bin_attribute *attr, 203055d0a513SHarald Freudenberger char *buf, loff_t off, 203155d0a513SHarald Freudenberger size_t count) 203255d0a513SHarald Freudenberger { 203355d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 203455d0a513SHarald Freudenberger off, count); 203555d0a513SHarald Freudenberger } 203655d0a513SHarald Freudenberger 203755d0a513SHarald Freudenberger static ssize_t ep11_aes_192_read(struct file *filp, 203855d0a513SHarald Freudenberger struct kobject *kobj, 203955d0a513SHarald Freudenberger struct bin_attribute *attr, 204055d0a513SHarald Freudenberger char *buf, loff_t off, 204155d0a513SHarald Freudenberger size_t count) 204255d0a513SHarald Freudenberger { 204355d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 204455d0a513SHarald Freudenberger off, count); 204555d0a513SHarald Freudenberger } 204655d0a513SHarald Freudenberger 204755d0a513SHarald Freudenberger static ssize_t ep11_aes_256_read(struct file *filp, 204855d0a513SHarald Freudenberger struct kobject *kobj, 204955d0a513SHarald Freudenberger struct bin_attribute *attr, 205055d0a513SHarald Freudenberger char *buf, loff_t off, 205155d0a513SHarald Freudenberger size_t count) 205255d0a513SHarald Freudenberger { 205355d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 205455d0a513SHarald Freudenberger off, count); 205555d0a513SHarald Freudenberger } 205655d0a513SHarald Freudenberger 205755d0a513SHarald Freudenberger static ssize_t ep11_aes_128_xts_read(struct file *filp, 205855d0a513SHarald Freudenberger struct kobject *kobj, 205955d0a513SHarald Freudenberger struct bin_attribute *attr, 206055d0a513SHarald Freudenberger char *buf, loff_t off, 206155d0a513SHarald Freudenberger size_t count) 206255d0a513SHarald Freudenberger { 206355d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 206455d0a513SHarald Freudenberger off, count); 206555d0a513SHarald Freudenberger } 206655d0a513SHarald Freudenberger 206755d0a513SHarald Freudenberger static ssize_t ep11_aes_256_xts_read(struct file *filp, 206855d0a513SHarald Freudenberger struct kobject *kobj, 206955d0a513SHarald Freudenberger struct bin_attribute *attr, 207055d0a513SHarald Freudenberger char *buf, loff_t off, 207155d0a513SHarald Freudenberger size_t count) 207255d0a513SHarald Freudenberger { 207355d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 207455d0a513SHarald Freudenberger off, count); 207555d0a513SHarald Freudenberger } 207655d0a513SHarald Freudenberger 207755d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE); 207855d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE); 207955d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE); 208055d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE); 208155d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE); 208255d0a513SHarald Freudenberger 208355d0a513SHarald Freudenberger static struct bin_attribute *ep11_attrs[] = { 208455d0a513SHarald Freudenberger &bin_attr_ep11_aes_128, 208555d0a513SHarald Freudenberger &bin_attr_ep11_aes_192, 208655d0a513SHarald Freudenberger &bin_attr_ep11_aes_256, 208755d0a513SHarald Freudenberger &bin_attr_ep11_aes_128_xts, 208855d0a513SHarald Freudenberger &bin_attr_ep11_aes_256_xts, 208955d0a513SHarald Freudenberger NULL 209055d0a513SHarald Freudenberger }; 209155d0a513SHarald Freudenberger 209255d0a513SHarald Freudenberger static struct attribute_group ep11_attr_group = { 209355d0a513SHarald Freudenberger .name = "ep11", 209455d0a513SHarald Freudenberger .bin_attrs = ep11_attrs, 209555d0a513SHarald Freudenberger }; 209655d0a513SHarald Freudenberger 2097d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 2098d632c047SIngo Franzki &protkey_attr_group, 2099af504452SIngo Franzki &ccadata_attr_group, 2100f71fee27SIngo Franzki &ccacipher_attr_group, 210155d0a513SHarald Freudenberger &ep11_attr_group, 2102d632c047SIngo Franzki NULL, 2103d632c047SIngo Franzki }; 2104d632c047SIngo Franzki 2105e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 2106e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 2107e80d4af0SHarald Freudenberger .open = nonseekable_open, 2108e80d4af0SHarald Freudenberger .llseek = no_llseek, 2109e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 2110e80d4af0SHarald Freudenberger }; 2111e80d4af0SHarald Freudenberger 2112e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 2113e80d4af0SHarald Freudenberger .name = "pkey", 2114e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 2115e80d4af0SHarald Freudenberger .mode = 0666, 2116e80d4af0SHarald Freudenberger .fops = &pkey_fops, 2117d632c047SIngo Franzki .groups = pkey_attr_groups, 2118e80d4af0SHarald Freudenberger }; 2119e80d4af0SHarald Freudenberger 2120e80d4af0SHarald Freudenberger /* 2121e80d4af0SHarald Freudenberger * Module init 2122e80d4af0SHarald Freudenberger */ 2123cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 2124e80d4af0SHarald Freudenberger { 21255b35047eSHarald Freudenberger cpacf_mask_t func_mask; 2126e80d4af0SHarald Freudenberger 2127f822ad2cSHarald Freudenberger /* 2128f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 2129f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 2130f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 2131f822ad2cSHarald Freudenberger * are able to work with protected keys. 2132f822ad2cSHarald Freudenberger */ 21335b35047eSHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &func_mask)) 213458443b67SDavid Hildenbrand return -ENODEV; 2135e80d4af0SHarald Freudenberger 2136cb26b9ffSIngo Franzki /* check for kmc instructions available */ 21375b35047eSHarald Freudenberger if (!cpacf_query(CPACF_KMC, &func_mask)) 213858443b67SDavid Hildenbrand return -ENODEV; 21395b35047eSHarald Freudenberger if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) || 21405b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) || 21415b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256)) 214258443b67SDavid Hildenbrand return -ENODEV; 2143cb26b9ffSIngo Franzki 2144e80d4af0SHarald Freudenberger pkey_debug_init(); 2145e80d4af0SHarald Freudenberger 2146e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 2147e80d4af0SHarald Freudenberger } 2148e80d4af0SHarald Freudenberger 2149e80d4af0SHarald Freudenberger /* 2150e80d4af0SHarald Freudenberger * Module exit 2151e80d4af0SHarald Freudenberger */ 2152e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 2153e80d4af0SHarald Freudenberger { 2154e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 2155e80d4af0SHarald Freudenberger pkey_debug_exit(); 2156e80d4af0SHarald Freudenberger } 2157e80d4af0SHarald Freudenberger 21580a5f9b38SHeiko Carstens module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init); 2159e80d4af0SHarald Freudenberger module_exit(pkey_exit); 2160