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 */ 37f2bbc96eSHarald Freudenberger 38e80d4af0SHarald Freudenberger /* 39e80d4af0SHarald Freudenberger * debug feature data and functions 40e80d4af0SHarald Freudenberger */ 41e80d4af0SHarald Freudenberger 42e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 43e80d4af0SHarald Freudenberger 44e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 45e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 46e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 47e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 48e80d4af0SHarald Freudenberger 49e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 50e80d4af0SHarald Freudenberger { 516b1f16baSHarald Freudenberger /* 5 arguments per dbf entry (including the format string ptr) */ 526b1f16baSHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); 53e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 54e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 55e80d4af0SHarald Freudenberger } 56e80d4af0SHarald Freudenberger 57e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 58e80d4af0SHarald Freudenberger { 59e80d4af0SHarald Freudenberger debug_unregister(debug_info); 60e80d4af0SHarald Freudenberger } 61e80d4af0SHarald Freudenberger 620534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */ 630534bde7SIngo Franzki struct protaeskeytoken { 640534bde7SIngo Franzki u8 type; /* 0x00 for PAES specific key tokens */ 650534bde7SIngo Franzki u8 res0[3]; 660534bde7SIngo Franzki u8 version; /* should be 0x01 for protected AES key token */ 670534bde7SIngo Franzki u8 res1[3]; 680534bde7SIngo Franzki u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 690534bde7SIngo Franzki u32 len; /* bytes actually stored in protkey[] */ 700534bde7SIngo Franzki u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 710534bde7SIngo Franzki } __packed; 720534bde7SIngo Franzki 73888edbc4SHarald Freudenberger /* inside view of a clear key token (type 0x00 version 0x02) */ 74888edbc4SHarald Freudenberger struct clearaeskeytoken { 75888edbc4SHarald Freudenberger u8 type; /* 0x00 for PAES specific key tokens */ 76888edbc4SHarald Freudenberger u8 res0[3]; 77888edbc4SHarald Freudenberger u8 version; /* 0x02 for clear AES key token */ 78888edbc4SHarald Freudenberger u8 res1[3]; 79888edbc4SHarald Freudenberger u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 80888edbc4SHarald Freudenberger u32 len; /* bytes actually stored in clearkey[] */ 81fa226f1dSGustavo A. R. Silva u8 clearkey[]; /* clear key value */ 82888edbc4SHarald Freudenberger } __packed; 83888edbc4SHarald Freudenberger 84e80d4af0SHarald Freudenberger /* 85e80d4af0SHarald Freudenberger * Create a protected key from a clear key value. 86e80d4af0SHarald Freudenberger */ 87183cb469SHarald Freudenberger static int pkey_clr2protkey(u32 keytype, 88e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 89e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 90e80d4af0SHarald Freudenberger { 915b35047eSHarald Freudenberger /* mask of available pckmo subfunctions */ 925b35047eSHarald Freudenberger static cpacf_mask_t pckmo_functions; 935b35047eSHarald Freudenberger 94e80d4af0SHarald Freudenberger long fc; 95e80d4af0SHarald Freudenberger int keysize; 96e80d4af0SHarald Freudenberger u8 paramblock[64]; 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: 112ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 113ac2b96f3SHarald Freudenberger __func__, keytype); 114e80d4af0SHarald Freudenberger return -EINVAL; 115e80d4af0SHarald Freudenberger } 116e80d4af0SHarald Freudenberger 1175b35047eSHarald Freudenberger /* Did we already check for PCKMO ? */ 1185b35047eSHarald Freudenberger if (!pckmo_functions.bytes[0]) { 1195b35047eSHarald Freudenberger /* no, so check now */ 1205b35047eSHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 1215b35047eSHarald Freudenberger return -ENODEV; 1225b35047eSHarald Freudenberger } 1235b35047eSHarald Freudenberger /* check for the pckmo subfunction we need now */ 124f822ad2cSHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, fc)) { 125f822ad2cSHarald Freudenberger DEBUG_ERR("%s pckmo functions not available\n", __func__); 12658443b67SDavid Hildenbrand return -ENODEV; 127f822ad2cSHarald Freudenberger } 128f822ad2cSHarald Freudenberger 129e80d4af0SHarald Freudenberger /* prepare param block */ 130e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 131e80d4af0SHarald Freudenberger memcpy(paramblock, clrkey->clrkey, keysize); 132e80d4af0SHarald Freudenberger 133e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 134e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 135e80d4af0SHarald Freudenberger 136e80d4af0SHarald Freudenberger /* copy created protected key */ 137e80d4af0SHarald Freudenberger protkey->type = keytype; 138e80d4af0SHarald Freudenberger protkey->len = keysize + 32; 139e80d4af0SHarald Freudenberger memcpy(protkey->protkey, paramblock, keysize + 32); 140e80d4af0SHarald Freudenberger 141e80d4af0SHarald Freudenberger return 0; 142e80d4af0SHarald Freudenberger } 143e80d4af0SHarald Freudenberger 144e80d4af0SHarald Freudenberger /* 145e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 146e80d4af0SHarald Freudenberger */ 147f2bbc96eSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) 148e80d4af0SHarald Freudenberger { 149e80d4af0SHarald Freudenberger int rc, verify; 150f2bbc96eSHarald Freudenberger u16 cardnr, domain; 151f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 152e80d4af0SHarald Freudenberger 15343cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 15443cb5a7cSHarald Freudenberger 155e80d4af0SHarald Freudenberger /* 156f2bbc96eSHarald Freudenberger * The cca_xxx2protkey call may fail when a card has been 157e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 158f4272c03SJulia Lawall * of the mkvp into the cache. Try 3 times: First without verify 159efc598e6SHarald Freudenberger * then with verify and last round with verify and old master 160efc598e6SHarald Freudenberger * key verification pattern match not ignored. 161e80d4af0SHarald Freudenberger */ 162efc598e6SHarald Freudenberger for (verify = 0; verify < 3; verify++) { 163f2bbc96eSHarald Freudenberger rc = cca_findcard(key, &cardnr, &domain, verify); 164efc598e6SHarald Freudenberger if (rc < 0) 165e80d4af0SHarald Freudenberger continue; 166efc598e6SHarald Freudenberger if (rc > 0 && verify < 2) 167efc598e6SHarald Freudenberger continue; 168f2bbc96eSHarald Freudenberger switch (hdr->version) { 169f2bbc96eSHarald Freudenberger case TOKVER_CCA_AES: 170f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(cardnr, domain, 171f2bbc96eSHarald Freudenberger key, pkey->protkey, 172f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 173f2bbc96eSHarald Freudenberger break; 174f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 175f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(cardnr, domain, 176f2bbc96eSHarald Freudenberger key, pkey->protkey, 177f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 178f2bbc96eSHarald Freudenberger break; 179f2bbc96eSHarald Freudenberger default: 180f2bbc96eSHarald Freudenberger return -EINVAL; 181f2bbc96eSHarald Freudenberger } 182e80d4af0SHarald Freudenberger if (rc == 0) 183e80d4af0SHarald Freudenberger break; 184e80d4af0SHarald Freudenberger } 185e80d4af0SHarald Freudenberger 186e80d4af0SHarald Freudenberger if (rc) 187ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 188e80d4af0SHarald Freudenberger 189e80d4af0SHarald Freudenberger return rc; 190e80d4af0SHarald Freudenberger } 191e80d4af0SHarald Freudenberger 192e80d4af0SHarald Freudenberger /* 19355d0a513SHarald Freudenberger * Construct EP11 key with given clear key value. 19455d0a513SHarald Freudenberger */ 19555d0a513SHarald Freudenberger static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, 19655d0a513SHarald Freudenberger u8 *keybuf, size_t *keybuflen) 19755d0a513SHarald Freudenberger { 19855d0a513SHarald Freudenberger int i, rc; 19955d0a513SHarald Freudenberger u16 card, dom; 20055d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 20155d0a513SHarald Freudenberger 20243cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 20343cb5a7cSHarald Freudenberger 20455d0a513SHarald Freudenberger /* build a list of apqns suitable for ep11 keys with cpacf support */ 20555d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 20655d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 20755d0a513SHarald Freudenberger if (rc) 20855d0a513SHarald Freudenberger goto out; 20955d0a513SHarald Freudenberger 21055d0a513SHarald Freudenberger /* go through the list of apqns and try to bild an ep11 key */ 21155d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 21255d0a513SHarald Freudenberger card = apqns[i] >> 16; 21355d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 21455d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, clrkeylen * 8, 21555d0a513SHarald Freudenberger 0, clrkey, keybuf, keybuflen); 21655d0a513SHarald Freudenberger if (rc == 0) 21755d0a513SHarald Freudenberger break; 21855d0a513SHarald Freudenberger } 21955d0a513SHarald Freudenberger 22055d0a513SHarald Freudenberger out: 22155d0a513SHarald Freudenberger kfree(apqns); 22255d0a513SHarald Freudenberger if (rc) 22355d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 22455d0a513SHarald Freudenberger return rc; 22555d0a513SHarald Freudenberger } 22655d0a513SHarald Freudenberger 22755d0a513SHarald Freudenberger /* 22855d0a513SHarald Freudenberger * Find card and transform EP11 secure key into protected key. 22955d0a513SHarald Freudenberger */ 23055d0a513SHarald Freudenberger static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) 23155d0a513SHarald Freudenberger { 23255d0a513SHarald Freudenberger int i, rc; 23355d0a513SHarald Freudenberger u16 card, dom; 23455d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 23555d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 23655d0a513SHarald Freudenberger 23743cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 23843cb5a7cSHarald Freudenberger 23955d0a513SHarald Freudenberger /* build a list of apqns suitable for this key */ 24055d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 24155d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 24255d0a513SHarald Freudenberger if (rc) 24355d0a513SHarald Freudenberger goto out; 24455d0a513SHarald Freudenberger 24555d0a513SHarald Freudenberger /* go through the list of apqns and try to derive an pkey */ 24655d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 24755d0a513SHarald Freudenberger card = apqns[i] >> 16; 24855d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 249fa6999e3SHarald Freudenberger pkey->len = sizeof(pkey->protkey); 250fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 25155d0a513SHarald Freudenberger pkey->protkey, &pkey->len, &pkey->type); 25255d0a513SHarald Freudenberger if (rc == 0) 25355d0a513SHarald Freudenberger break; 25455d0a513SHarald Freudenberger } 25555d0a513SHarald Freudenberger 25655d0a513SHarald Freudenberger out: 25755d0a513SHarald Freudenberger kfree(apqns); 25855d0a513SHarald Freudenberger if (rc) 25955d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 26055d0a513SHarald Freudenberger return rc; 26155d0a513SHarald Freudenberger } 26255d0a513SHarald Freudenberger 26355d0a513SHarald Freudenberger /* 264e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 265e61a6134SHarald Freudenberger */ 266183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey, 267e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 268e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 269e61a6134SHarald Freudenberger { 270e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)seckey; 271e61a6134SHarald Freudenberger u16 cardnr, domain; 272e61a6134SHarald Freudenberger int rc; 273e61a6134SHarald Freudenberger 274e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 275efc598e6SHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *)seckey, 0); 276e61a6134SHarald Freudenberger if (rc) 277e61a6134SHarald Freudenberger goto out; 278e61a6134SHarald Freudenberger if (pattributes) 279e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 280e61a6134SHarald Freudenberger if (pkeysize) 281e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 282e61a6134SHarald Freudenberger 283e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 284efc598e6SHarald Freudenberger rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); 285efc598e6SHarald Freudenberger if (rc < 0) 286e61a6134SHarald Freudenberger goto out; 287e61a6134SHarald Freudenberger 288efc598e6SHarald Freudenberger if (rc > 0) { 289efc598e6SHarald Freudenberger /* key mkvp matches to old master key mkvp */ 290ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 291e61a6134SHarald Freudenberger if (pattributes) 292e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 293efc598e6SHarald Freudenberger rc = 0; 294e61a6134SHarald Freudenberger } 295e61a6134SHarald Freudenberger 296e61a6134SHarald Freudenberger if (pcardnr) 297e61a6134SHarald Freudenberger *pcardnr = cardnr; 298e61a6134SHarald Freudenberger if (pdomain) 299e61a6134SHarald Freudenberger *pdomain = domain; 300e61a6134SHarald Freudenberger 301e61a6134SHarald Freudenberger out: 302ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 303e61a6134SHarald Freudenberger return rc; 304e61a6134SHarald Freudenberger } 305e61a6134SHarald Freudenberger 306e61a6134SHarald Freudenberger /* 307a45a5c7dSIngo Franzki * Generate a random protected key 308a45a5c7dSIngo Franzki */ 309183cb469SHarald Freudenberger static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) 310a45a5c7dSIngo Franzki { 311a45a5c7dSIngo Franzki struct pkey_clrkey clrkey; 312a45a5c7dSIngo Franzki int keysize; 313a45a5c7dSIngo Franzki int rc; 314a45a5c7dSIngo Franzki 315a45a5c7dSIngo Franzki switch (keytype) { 316a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_128: 317a45a5c7dSIngo Franzki keysize = 16; 318a45a5c7dSIngo Franzki break; 319a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_192: 320a45a5c7dSIngo Franzki keysize = 24; 321a45a5c7dSIngo Franzki break; 322a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_256: 323a45a5c7dSIngo Franzki keysize = 32; 324a45a5c7dSIngo Franzki break; 325a45a5c7dSIngo Franzki default: 326a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 327a45a5c7dSIngo Franzki keytype); 328a45a5c7dSIngo Franzki return -EINVAL; 329a45a5c7dSIngo Franzki } 330a45a5c7dSIngo Franzki 331a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 332a45a5c7dSIngo Franzki get_random_bytes(clrkey.clrkey, keysize); 333a45a5c7dSIngo Franzki 334a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 335a45a5c7dSIngo Franzki rc = pkey_clr2protkey(keytype, &clrkey, protkey); 336a45a5c7dSIngo Franzki if (rc) 337a45a5c7dSIngo Franzki return rc; 338a45a5c7dSIngo Franzki 339a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 340a45a5c7dSIngo Franzki get_random_bytes(protkey->protkey, keysize); 341a45a5c7dSIngo Franzki 342a45a5c7dSIngo Franzki return 0; 343a45a5c7dSIngo Franzki } 344a45a5c7dSIngo Franzki 345a45a5c7dSIngo Franzki /* 346cb26b9ffSIngo Franzki * Verify if a protected key is still valid 347cb26b9ffSIngo Franzki */ 348183cb469SHarald Freudenberger static int pkey_verifyprotkey(const struct pkey_protkey *protkey) 349cb26b9ffSIngo Franzki { 350cb26b9ffSIngo Franzki unsigned long fc; 351cb26b9ffSIngo Franzki struct { 352cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 353cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 354cb26b9ffSIngo Franzki } param; 355cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 356cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 357cb26b9ffSIngo Franzki unsigned int k; 358cb26b9ffSIngo Franzki 359cb26b9ffSIngo Franzki switch (protkey->type) { 360cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 361cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 362cb26b9ffSIngo Franzki break; 363cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 364cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 365cb26b9ffSIngo Franzki break; 366cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 367cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 368cb26b9ffSIngo Franzki break; 369cb26b9ffSIngo Franzki default: 370cb26b9ffSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 371cb26b9ffSIngo Franzki protkey->type); 372cb26b9ffSIngo Franzki return -EINVAL; 373cb26b9ffSIngo Franzki } 374cb26b9ffSIngo Franzki 375cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 376cb26b9ffSIngo Franzki 377cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 378cb26b9ffSIngo Franzki memcpy(param.key, protkey->protkey, sizeof(param.key)); 379cb26b9ffSIngo Franzki 380cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 381cb26b9ffSIngo Franzki sizeof(null_msg)); 382cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 383cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 384cb26b9ffSIngo Franzki return -EKEYREJECTED; 385cb26b9ffSIngo Franzki } 386cb26b9ffSIngo Franzki 387cb26b9ffSIngo Franzki return 0; 388cb26b9ffSIngo Franzki } 389cb26b9ffSIngo Franzki 390cb26b9ffSIngo Franzki /* 391fb1136d6SIngo Franzki * Transform a non-CCA key token into a protected key 392fb1136d6SIngo Franzki */ 393183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, 394fb1136d6SIngo Franzki struct pkey_protkey *protkey) 395fb1136d6SIngo Franzki { 396888edbc4SHarald Freudenberger int rc = -EINVAL; 39755d0a513SHarald Freudenberger u8 *tmpbuf = NULL; 398fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 399fb1136d6SIngo Franzki 400fb1136d6SIngo Franzki switch (hdr->version) { 401888edbc4SHarald Freudenberger case TOKVER_PROTECTED_KEY: { 402888edbc4SHarald Freudenberger struct protaeskeytoken *t; 403fb1136d6SIngo Franzki 404888edbc4SHarald Freudenberger if (keylen != sizeof(struct protaeskeytoken)) 405888edbc4SHarald Freudenberger goto out; 406fb1136d6SIngo Franzki t = (struct protaeskeytoken *)key; 407fb1136d6SIngo Franzki protkey->len = t->len; 408fb1136d6SIngo Franzki protkey->type = t->keytype; 409fb1136d6SIngo Franzki memcpy(protkey->protkey, t->protkey, 410fb1136d6SIngo Franzki sizeof(protkey->protkey)); 411888edbc4SHarald Freudenberger rc = pkey_verifyprotkey(protkey); 412888edbc4SHarald Freudenberger break; 413888edbc4SHarald Freudenberger } 414888edbc4SHarald Freudenberger case TOKVER_CLEAR_KEY: { 415888edbc4SHarald Freudenberger struct clearaeskeytoken *t; 416888edbc4SHarald Freudenberger struct pkey_clrkey ckey; 41755d0a513SHarald Freudenberger union u_tmpbuf { 41855d0a513SHarald Freudenberger u8 skey[SECKEYBLOBSIZE]; 41955d0a513SHarald Freudenberger u8 ep11key[MAXEP11AESKEYBLOBSIZE]; 42055d0a513SHarald Freudenberger }; 42155d0a513SHarald Freudenberger size_t tmpbuflen = sizeof(union u_tmpbuf); 422fb1136d6SIngo Franzki 423888edbc4SHarald Freudenberger if (keylen < sizeof(struct clearaeskeytoken)) 424888edbc4SHarald Freudenberger goto out; 425888edbc4SHarald Freudenberger t = (struct clearaeskeytoken *)key; 426888edbc4SHarald Freudenberger if (keylen != sizeof(*t) + t->len) 427888edbc4SHarald Freudenberger goto out; 4282004b57cSHarald Freudenberger if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) || 4292004b57cSHarald Freudenberger (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) || 4302004b57cSHarald Freudenberger (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) 431888edbc4SHarald Freudenberger memcpy(ckey.clrkey, t->clearkey, t->len); 432888edbc4SHarald Freudenberger else 433888edbc4SHarald Freudenberger goto out; 43455d0a513SHarald Freudenberger /* alloc temp key buffer space */ 43555d0a513SHarald Freudenberger tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 43655d0a513SHarald Freudenberger if (!tmpbuf) { 43755d0a513SHarald Freudenberger rc = -ENOMEM; 43855d0a513SHarald Freudenberger goto out; 43955d0a513SHarald Freudenberger } 440888edbc4SHarald Freudenberger /* try direct way with the PCKMO instruction */ 441888edbc4SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, &ckey, protkey); 442888edbc4SHarald Freudenberger if (rc == 0) 443888edbc4SHarald Freudenberger break; 444888edbc4SHarald Freudenberger /* PCKMO failed, so try the CCA secure key way */ 44543cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 446888edbc4SHarald Freudenberger rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, 44755d0a513SHarald Freudenberger ckey.clrkey, tmpbuf); 448888edbc4SHarald Freudenberger if (rc == 0) 44955d0a513SHarald Freudenberger rc = pkey_skey2pkey(tmpbuf, protkey); 450888edbc4SHarald Freudenberger if (rc == 0) 451888edbc4SHarald Freudenberger break; 45255d0a513SHarald Freudenberger /* if the CCA way also failed, let's try via EP11 */ 45355d0a513SHarald Freudenberger rc = pkey_clr2ep11key(ckey.clrkey, t->len, 45455d0a513SHarald Freudenberger tmpbuf, &tmpbuflen); 45555d0a513SHarald Freudenberger if (rc == 0) 45655d0a513SHarald Freudenberger rc = pkey_ep11key2pkey(tmpbuf, protkey); 45755d0a513SHarald Freudenberger /* now we should really have an protected key */ 458888edbc4SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", 459888edbc4SHarald Freudenberger __func__); 460888edbc4SHarald Freudenberger break; 461888edbc4SHarald Freudenberger } 46255d0a513SHarald Freudenberger case TOKVER_EP11_AES: { 46355d0a513SHarald Freudenberger /* check ep11 key for exportable as protected key */ 464fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 46555d0a513SHarald Freudenberger if (rc) 46655d0a513SHarald Freudenberger goto out; 46755d0a513SHarald Freudenberger rc = pkey_ep11key2pkey(key, protkey); 46855d0a513SHarald Freudenberger break; 46955d0a513SHarald Freudenberger } 470fa6999e3SHarald Freudenberger case TOKVER_EP11_AES_WITH_HEADER: 471fa6999e3SHarald Freudenberger /* check ep11 key with header for exportable as protected key */ 472fa6999e3SHarald Freudenberger rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1); 473fa6999e3SHarald Freudenberger if (rc) 474fa6999e3SHarald Freudenberger goto out; 475fa6999e3SHarald Freudenberger rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header), 476fa6999e3SHarald Freudenberger protkey); 477fa6999e3SHarald Freudenberger break; 478fb1136d6SIngo Franzki default: 479fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 480fb1136d6SIngo Franzki __func__, hdr->version); 481888edbc4SHarald Freudenberger rc = -EINVAL; 482fb1136d6SIngo Franzki } 483888edbc4SHarald Freudenberger 484888edbc4SHarald Freudenberger out: 48555d0a513SHarald Freudenberger kfree(tmpbuf); 486888edbc4SHarald Freudenberger return rc; 487fb1136d6SIngo Franzki } 488fb1136d6SIngo Franzki 489fb1136d6SIngo Franzki /* 490fb1136d6SIngo Franzki * Transform a CCA internal key token into a protected key 491fb1136d6SIngo Franzki */ 492183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, 493fb1136d6SIngo Franzki struct pkey_protkey *protkey) 494fb1136d6SIngo Franzki { 495fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 496fb1136d6SIngo Franzki 497fb1136d6SIngo Franzki switch (hdr->version) { 498fb1136d6SIngo Franzki case TOKVER_CCA_AES: 499fb1136d6SIngo Franzki if (keylen != sizeof(struct secaeskeytoken)) 500fb1136d6SIngo Franzki return -EINVAL; 501f2bbc96eSHarald Freudenberger break; 502f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 503f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 504f2bbc96eSHarald Freudenberger return -EINVAL; 505f2bbc96eSHarald Freudenberger break; 506fb1136d6SIngo Franzki default: 507fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 508fb1136d6SIngo Franzki __func__, hdr->version); 509fb1136d6SIngo Franzki return -EINVAL; 510fb1136d6SIngo Franzki } 511f2bbc96eSHarald Freudenberger 512f2bbc96eSHarald Freudenberger return pkey_skey2pkey(key, protkey); 513fb1136d6SIngo Franzki } 514fb1136d6SIngo Franzki 515fb1136d6SIngo Franzki /* 516fb1136d6SIngo Franzki * Transform a key blob (of any type) into a protected key 517fb1136d6SIngo Franzki */ 518183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen, 519fb1136d6SIngo Franzki struct pkey_protkey *protkey) 520fb1136d6SIngo Franzki { 521f2bbc96eSHarald Freudenberger int rc; 522fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 523fb1136d6SIngo Franzki 524f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) { 525f2bbc96eSHarald Freudenberger DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); 526f2bbc96eSHarald Freudenberger return -EINVAL; 527f2bbc96eSHarald Freudenberger } 528f2bbc96eSHarald Freudenberger 529f2bbc96eSHarald Freudenberger switch (hdr->type) { 530f2bbc96eSHarald Freudenberger case TOKTYPE_NON_CCA: 531f2bbc96eSHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, protkey); 532f2bbc96eSHarald Freudenberger break; 533f2bbc96eSHarald Freudenberger case TOKTYPE_CCA_INTERNAL: 534f2bbc96eSHarald Freudenberger rc = pkey_ccainttok2pkey(key, keylen, protkey); 535f2bbc96eSHarald Freudenberger break; 536f2bbc96eSHarald Freudenberger default: 537f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 538f2bbc96eSHarald Freudenberger __func__, hdr->type); 539f2bbc96eSHarald Freudenberger return -EINVAL; 540f2bbc96eSHarald Freudenberger } 541f2bbc96eSHarald Freudenberger 542f2bbc96eSHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 543f2bbc96eSHarald Freudenberger return rc; 544f2bbc96eSHarald Freudenberger } 545f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey); 546f2bbc96eSHarald Freudenberger 547f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 548f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 549f2bbc96eSHarald Freudenberger u32 kflags, u8 *keybuf, size_t *keybufsize) 550f2bbc96eSHarald Freudenberger { 551f2bbc96eSHarald Freudenberger int i, card, dom, rc; 552f2bbc96eSHarald Freudenberger 553f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 554f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 555f2bbc96eSHarald Freudenberger return -EINVAL; 556f2bbc96eSHarald Freudenberger 557f2bbc96eSHarald Freudenberger /* check key type and size */ 558f2bbc96eSHarald Freudenberger switch (ktype) { 559f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 560f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 561f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 562f2bbc96eSHarald Freudenberger return -EINVAL; 563f2bbc96eSHarald Freudenberger break; 56455d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 56555d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 56655d0a513SHarald Freudenberger return -EINVAL; 56755d0a513SHarald Freudenberger break; 568f2bbc96eSHarald Freudenberger default: 569f2bbc96eSHarald Freudenberger return -EINVAL; 570f2bbc96eSHarald Freudenberger } 571f2bbc96eSHarald Freudenberger switch (ksize) { 572f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 573f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 574f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 575f2bbc96eSHarald Freudenberger break; 576f2bbc96eSHarald Freudenberger default: 577f2bbc96eSHarald Freudenberger return -EINVAL; 578f2bbc96eSHarald Freudenberger } 579f2bbc96eSHarald Freudenberger 580f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 581f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 582f2bbc96eSHarald Freudenberger card = apqns[i].card; 583f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 58455d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 58555d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, ksize, kflags, 58655d0a513SHarald Freudenberger keybuf, keybufsize); 58755d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 588f2bbc96eSHarald Freudenberger rc = cca_genseckey(card, dom, ksize, keybuf); 589f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 5902004b57cSHarald Freudenberger } else { 5912004b57cSHarald Freudenberger /* TOKVER_CCA_VLSC */ 592f2bbc96eSHarald Freudenberger rc = cca_gencipherkey(card, dom, ksize, kflags, 593f2bbc96eSHarald Freudenberger keybuf, keybufsize); 5942004b57cSHarald Freudenberger } 595f2bbc96eSHarald Freudenberger if (rc == 0) 596f2bbc96eSHarald Freudenberger break; 597f2bbc96eSHarald Freudenberger } 598f2bbc96eSHarald Freudenberger 599f2bbc96eSHarald Freudenberger return rc; 600f2bbc96eSHarald Freudenberger } 601f2bbc96eSHarald Freudenberger 602f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 603f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 604f2bbc96eSHarald Freudenberger u32 kflags, const u8 *clrkey, 605f2bbc96eSHarald Freudenberger u8 *keybuf, size_t *keybufsize) 606f2bbc96eSHarald Freudenberger { 607f2bbc96eSHarald Freudenberger int i, card, dom, rc; 608f2bbc96eSHarald Freudenberger 609f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 610f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 611f2bbc96eSHarald Freudenberger return -EINVAL; 612f2bbc96eSHarald Freudenberger 613f2bbc96eSHarald Freudenberger /* check key type and size */ 614f2bbc96eSHarald Freudenberger switch (ktype) { 615f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 616f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 617f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 618f2bbc96eSHarald Freudenberger return -EINVAL; 619f2bbc96eSHarald Freudenberger break; 62055d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 62155d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 62255d0a513SHarald Freudenberger return -EINVAL; 62355d0a513SHarald Freudenberger break; 624f2bbc96eSHarald Freudenberger default: 625f2bbc96eSHarald Freudenberger return -EINVAL; 626f2bbc96eSHarald Freudenberger } 627f2bbc96eSHarald Freudenberger switch (ksize) { 628f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 629f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 630f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 631f2bbc96eSHarald Freudenberger break; 632f2bbc96eSHarald Freudenberger default: 633f2bbc96eSHarald Freudenberger return -EINVAL; 634f2bbc96eSHarald Freudenberger } 635f2bbc96eSHarald Freudenberger 63643cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 63743cb5a7cSHarald Freudenberger 638f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 639f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 640f2bbc96eSHarald Freudenberger card = apqns[i].card; 641f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 64255d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 64355d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, ksize, kflags, 64455d0a513SHarald Freudenberger clrkey, keybuf, keybufsize); 64555d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 646f2bbc96eSHarald Freudenberger rc = cca_clr2seckey(card, dom, ksize, 647f2bbc96eSHarald Freudenberger clrkey, keybuf); 648f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 6492004b57cSHarald Freudenberger } else { 6502004b57cSHarald Freudenberger /* TOKVER_CCA_VLSC */ 651f2bbc96eSHarald Freudenberger rc = cca_clr2cipherkey(card, dom, ksize, kflags, 652f2bbc96eSHarald Freudenberger clrkey, keybuf, keybufsize); 6532004b57cSHarald Freudenberger } 654f2bbc96eSHarald Freudenberger if (rc == 0) 655f2bbc96eSHarald Freudenberger break; 656f2bbc96eSHarald Freudenberger } 657f2bbc96eSHarald Freudenberger 658f2bbc96eSHarald Freudenberger return rc; 659f2bbc96eSHarald Freudenberger } 660f2bbc96eSHarald Freudenberger 661f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen, 662f2bbc96eSHarald Freudenberger u16 *cardnr, u16 *domain, 663f2bbc96eSHarald Freudenberger enum pkey_key_type *ktype, 664f2bbc96eSHarald Freudenberger enum pkey_key_size *ksize, u32 *flags) 665f2bbc96eSHarald Freudenberger { 666f2bbc96eSHarald Freudenberger int rc; 667f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 668f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 669f2bbc96eSHarald Freudenberger 67055d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 671f2bbc96eSHarald Freudenberger return -EINVAL; 672f2bbc96eSHarald Freudenberger 6732004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 6742004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 675f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 676f2bbc96eSHarald Freudenberger 677f2bbc96eSHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 678f2bbc96eSHarald Freudenberger if (rc) 679f2bbc96eSHarald Freudenberger goto out; 680f2bbc96eSHarald Freudenberger if (ktype) 681f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_DATA; 682f2bbc96eSHarald Freudenberger if (ksize) 683f2bbc96eSHarald Freudenberger *ksize = (enum pkey_key_size)t->bitsize; 684f2bbc96eSHarald Freudenberger 685f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 68632ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); 687f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 688f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 689f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 690f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 691f2bbc96eSHarald Freudenberger *cardnr, *domain, 69232ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, 69332ca04bbSHarald Freudenberger 0, t->mkvp, 1); 694f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 695f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 696f2bbc96eSHarald Freudenberger } 697f2bbc96eSHarald Freudenberger if (rc) 698f2bbc96eSHarald Freudenberger goto out; 699f2bbc96eSHarald Freudenberger 700f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 701f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 702f2bbc96eSHarald Freudenberger 7032004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 7042004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 705f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 706f2bbc96eSHarald Freudenberger 707f2bbc96eSHarald Freudenberger rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 708f2bbc96eSHarald Freudenberger if (rc) 709f2bbc96eSHarald Freudenberger goto out; 710f2bbc96eSHarald Freudenberger if (ktype) 711f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_CIPHER; 712f2bbc96eSHarald Freudenberger if (ksize) { 713f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_UNKNOWN; 714f2bbc96eSHarald Freudenberger if (!t->plfver && t->wpllen == 512) 715f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_128; 716f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 717f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_192; 718f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 719f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_256; 720f2bbc96eSHarald Freudenberger } 721f2bbc96eSHarald Freudenberger 722f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 72332ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); 724f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 725f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 726f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 727f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 728f2bbc96eSHarald Freudenberger *cardnr, *domain, 72932ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, 73032ca04bbSHarald Freudenberger 0, t->mkvp0, 1); 731f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 732f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 733f2bbc96eSHarald Freudenberger } 734f2bbc96eSHarald Freudenberger if (rc) 735f2bbc96eSHarald Freudenberger goto out; 736f2bbc96eSHarald Freudenberger 737f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 738f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 739f2bbc96eSHarald Freudenberger 7402004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 7412004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES) { 74255d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 74355d0a513SHarald Freudenberger 744fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 74555d0a513SHarald Freudenberger if (rc) 74655d0a513SHarald Freudenberger goto out; 74755d0a513SHarald Freudenberger if (ktype) 74855d0a513SHarald Freudenberger *ktype = PKEY_TYPE_EP11; 74955d0a513SHarald Freudenberger if (ksize) 75055d0a513SHarald Freudenberger *ksize = kb->head.keybitlen; 75155d0a513SHarald Freudenberger 75255d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 75355d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 75455d0a513SHarald Freudenberger if (rc) 75555d0a513SHarald Freudenberger goto out; 75655d0a513SHarald Freudenberger 75755d0a513SHarald Freudenberger if (flags) 75855d0a513SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 75955d0a513SHarald Freudenberger 76055d0a513SHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 76155d0a513SHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 76255d0a513SHarald Freudenberger 7632004b57cSHarald Freudenberger } else { 764f2bbc96eSHarald Freudenberger rc = -EINVAL; 7652004b57cSHarald Freudenberger } 766f2bbc96eSHarald Freudenberger 767f2bbc96eSHarald Freudenberger out: 768f2bbc96eSHarald Freudenberger kfree(_apqns); 769f2bbc96eSHarald Freudenberger return rc; 770f2bbc96eSHarald Freudenberger } 771f2bbc96eSHarald Freudenberger 772f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 773f2bbc96eSHarald Freudenberger const u8 *key, size_t keylen, 774f2bbc96eSHarald Freudenberger struct pkey_protkey *pkey) 775f2bbc96eSHarald Freudenberger { 776f2bbc96eSHarald Freudenberger int i, card, dom, rc; 777f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 778f2bbc96eSHarald Freudenberger 779f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 780f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 781f2bbc96eSHarald Freudenberger return -EINVAL; 782f2bbc96eSHarald Freudenberger 783fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 784fb1136d6SIngo Franzki return -EINVAL; 785fb1136d6SIngo Franzki 78655d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL) { 78755d0a513SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 788f2bbc96eSHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 789f2bbc96eSHarald Freudenberger return -EINVAL; 790f2bbc96eSHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 791f2bbc96eSHarald Freudenberger return -EINVAL; 79255d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 793f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 794f2bbc96eSHarald Freudenberger return -EINVAL; 795f2bbc96eSHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 796f2bbc96eSHarald Freudenberger return -EINVAL; 79755d0a513SHarald Freudenberger } else { 798f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 799f2bbc96eSHarald Freudenberger __func__, hdr->version); 800fb1136d6SIngo Franzki return -EINVAL; 801fb1136d6SIngo Franzki } 80255d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 80355d0a513SHarald Freudenberger if (hdr->version == TOKVER_EP11_AES) { 80455d0a513SHarald Freudenberger if (keylen < sizeof(struct ep11keyblob)) 80555d0a513SHarald Freudenberger return -EINVAL; 806fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 80755d0a513SHarald Freudenberger return -EINVAL; 80855d0a513SHarald Freudenberger } else { 80955d0a513SHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, pkey); 81055d0a513SHarald Freudenberger } 81155d0a513SHarald Freudenberger } else { 812f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 813f2bbc96eSHarald Freudenberger __func__, hdr->type); 814f2bbc96eSHarald Freudenberger return -EINVAL; 815fb1136d6SIngo Franzki } 816f2bbc96eSHarald Freudenberger 81743cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 81843cb5a7cSHarald Freudenberger 819f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 820f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 821f2bbc96eSHarald Freudenberger card = apqns[i].card; 822f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 8232004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL && 8242004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_AES) { 825f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(card, dom, key, pkey->protkey, 826f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 8272004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 8282004b57cSHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) { 829f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, pkey->protkey, 830f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 8312004b57cSHarald Freudenberger } else { 8322004b57cSHarald Freudenberger /* EP11 AES secure key blob */ 83355d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 83455d0a513SHarald Freudenberger 835fa6999e3SHarald Freudenberger pkey->len = sizeof(pkey->protkey); 836fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 83755d0a513SHarald Freudenberger pkey->protkey, &pkey->len, 83855d0a513SHarald Freudenberger &pkey->type); 83955d0a513SHarald Freudenberger } 840f2bbc96eSHarald Freudenberger if (rc == 0) 841f2bbc96eSHarald Freudenberger break; 842f2bbc96eSHarald Freudenberger } 843f2bbc96eSHarald Freudenberger 844f2bbc96eSHarald Freudenberger return rc; 845f2bbc96eSHarald Freudenberger } 846f2bbc96eSHarald Freudenberger 847f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 848f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 849f2bbc96eSHarald Freudenberger { 85075be6b98STianjia Zhang int rc; 851f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 852f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 853f2bbc96eSHarald Freudenberger 85455d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || flags == 0) 855f2bbc96eSHarald Freudenberger return -EINVAL; 856f2bbc96eSHarald Freudenberger 85743cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 85843cb5a7cSHarald Freudenberger 8592004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 8602004b57cSHarald Freudenberger (hdr->version == TOKVER_EP11_AES_WITH_HEADER || 8612004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && 8622004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 863fa6999e3SHarald Freudenberger int minhwtype = 0, api = 0; 864fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) 865fa6999e3SHarald Freudenberger (key + sizeof(struct ep11kblob_header)); 866fa6999e3SHarald Freudenberger 867fa6999e3SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 868fa6999e3SHarald Freudenberger return -EINVAL; 869fa6999e3SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 870fa6999e3SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 871fa6999e3SHarald Freudenberger api = EP11_API_V; 872fa6999e3SHarald Freudenberger } 873fa6999e3SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 874fa6999e3SHarald Freudenberger minhwtype, api, kb->wkvp); 875fa6999e3SHarald Freudenberger if (rc) 876fa6999e3SHarald Freudenberger goto out; 8772004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 8782004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 8792004b57cSHarald Freudenberger is_ep11_keyblob(key)) { 88055d0a513SHarald Freudenberger int minhwtype = 0, api = 0; 88155d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 88255d0a513SHarald Freudenberger 88355d0a513SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 88455d0a513SHarald Freudenberger return -EINVAL; 88555d0a513SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 88655d0a513SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 88755d0a513SHarald Freudenberger api = EP11_API_V; 88855d0a513SHarald Freudenberger } 88955d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 89055d0a513SHarald Freudenberger minhwtype, api, kb->wkvp); 89155d0a513SHarald Freudenberger if (rc) 89255d0a513SHarald Freudenberger goto out; 89355d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 894f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 895f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 896f2bbc96eSHarald Freudenberger 897f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 898f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 899f2bbc96eSHarald Freudenberger 900f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 901f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp; 902f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 903f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp; 90455d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 905f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 906f2bbc96eSHarald Freudenberger 907f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 908f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 909f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp0; 910f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 911f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp0; 91255d0a513SHarald Freudenberger } else { 91355d0a513SHarald Freudenberger /* unknown cca internal token type */ 91455d0a513SHarald Freudenberger return -EINVAL; 915f2bbc96eSHarald Freudenberger } 916f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 91732ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 91832ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 919f2bbc96eSHarald Freudenberger if (rc) 920f2bbc96eSHarald Freudenberger goto out; 921fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 922fa6999e3SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 923fa6999e3SHarald Freudenberger struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; 924fa6999e3SHarald Freudenberger 925fa6999e3SHarald Freudenberger if (t->secid == 0x20) { 926fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 927fa6999e3SHarald Freudenberger cur_mkvp = t->mkvp; 928fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 929fa6999e3SHarald Freudenberger old_mkvp = t->mkvp; 930fa6999e3SHarald Freudenberger } else { 931fa6999e3SHarald Freudenberger /* unknown cca internal 2 token type */ 932fa6999e3SHarald Freudenberger return -EINVAL; 933fa6999e3SHarald Freudenberger } 934fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 935fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 936fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 937fa6999e3SHarald Freudenberger if (rc) 938fa6999e3SHarald Freudenberger goto out; 9392004b57cSHarald Freudenberger } else { 94055d0a513SHarald Freudenberger return -EINVAL; 9412004b57cSHarald Freudenberger } 94255d0a513SHarald Freudenberger 943f2bbc96eSHarald Freudenberger if (apqns) { 944f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 945f2bbc96eSHarald Freudenberger rc = -ENOSPC; 946f2bbc96eSHarald Freudenberger else 947f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 948f2bbc96eSHarald Freudenberger } 949f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 950f2bbc96eSHarald Freudenberger 951f2bbc96eSHarald Freudenberger out: 952f2bbc96eSHarald Freudenberger kfree(_apqns); 953f2bbc96eSHarald Freudenberger return rc; 954f2bbc96eSHarald Freudenberger } 955f2bbc96eSHarald Freudenberger 956f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype, 957f2bbc96eSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 958f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 959f2bbc96eSHarald Freudenberger { 96075be6b98STianjia Zhang int rc; 961f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 962f2bbc96eSHarald Freudenberger 96343cb5a7cSHarald Freudenberger zcrypt_wait_api_operational(); 96443cb5a7cSHarald Freudenberger 965f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 966f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 967f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 968f2bbc96eSHarald Freudenberger 969f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 970f2bbc96eSHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 971f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 972f2bbc96eSHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 973f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 974f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 975f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 97632ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 97732ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 978f2bbc96eSHarald Freudenberger if (rc) 979f2bbc96eSHarald Freudenberger goto out; 980fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_ECC) { 981fa6999e3SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 982fa6999e3SHarald Freudenberger 983fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 984fa6999e3SHarald Freudenberger cur_mkvp = *((u64 *)cur_mkvp); 985fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 986fa6999e3SHarald Freudenberger old_mkvp = *((u64 *)alt_mkvp); 987fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 988fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 989fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 990fa6999e3SHarald Freudenberger if (rc) 991fa6999e3SHarald Freudenberger goto out; 992fa6999e3SHarald Freudenberger 993fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_EP11 || 994fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_AES || 995fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_ECC) { 99655d0a513SHarald Freudenberger u8 *wkvp = NULL; 99755d0a513SHarald Freudenberger 99855d0a513SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 99955d0a513SHarald Freudenberger wkvp = cur_mkvp; 100055d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 100155d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, wkvp); 100255d0a513SHarald Freudenberger if (rc) 100355d0a513SHarald Freudenberger goto out; 100455d0a513SHarald Freudenberger 10052004b57cSHarald Freudenberger } else { 100655d0a513SHarald Freudenberger return -EINVAL; 10072004b57cSHarald Freudenberger } 100855d0a513SHarald Freudenberger 1009f2bbc96eSHarald Freudenberger if (apqns) { 1010f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 1011f2bbc96eSHarald Freudenberger rc = -ENOSPC; 1012f2bbc96eSHarald Freudenberger else 1013f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 1014f2bbc96eSHarald Freudenberger } 1015f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 1016f2bbc96eSHarald Freudenberger 1017f2bbc96eSHarald Freudenberger out: 1018f2bbc96eSHarald Freudenberger kfree(_apqns); 1019f2bbc96eSHarald Freudenberger return rc; 1020f2bbc96eSHarald Freudenberger } 1021fb1136d6SIngo Franzki 1022fa6999e3SHarald Freudenberger static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, 1023fa6999e3SHarald Freudenberger const u8 *key, size_t keylen, u32 *protkeytype, 1024fa6999e3SHarald Freudenberger u8 *protkey, u32 *protkeylen) 1025fa6999e3SHarald Freudenberger { 1026fa6999e3SHarald Freudenberger int i, card, dom, rc; 1027fa6999e3SHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 1028fa6999e3SHarald Freudenberger 1029fa6999e3SHarald Freudenberger /* check for at least one apqn given */ 1030fa6999e3SHarald Freudenberger if (!apqns || !nr_apqns) 1031fa6999e3SHarald Freudenberger return -EINVAL; 1032fa6999e3SHarald Freudenberger 1033fa6999e3SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 1034fa6999e3SHarald Freudenberger return -EINVAL; 1035fa6999e3SHarald Freudenberger 10362004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 10372004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES_WITH_HEADER && 10382004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1039fa6999e3SHarald Freudenberger /* EP11 AES key blob with header */ 1040fa6999e3SHarald Freudenberger if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1)) 1041fa6999e3SHarald Freudenberger return -EINVAL; 10422004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 10432004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER && 10442004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1045fa6999e3SHarald Freudenberger /* EP11 ECC key blob with header */ 1046fa6999e3SHarald Freudenberger if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1)) 1047fa6999e3SHarald Freudenberger return -EINVAL; 10482004b57cSHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA && 10492004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 10502004b57cSHarald Freudenberger is_ep11_keyblob(key)) { 1051fa6999e3SHarald Freudenberger /* EP11 AES key blob with header in session field */ 1052fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 1053fa6999e3SHarald Freudenberger return -EINVAL; 1054fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 1055fa6999e3SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 1056fa6999e3SHarald Freudenberger /* CCA AES data key */ 1057fa6999e3SHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 1058fa6999e3SHarald Freudenberger return -EINVAL; 1059fa6999e3SHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 1060fa6999e3SHarald Freudenberger return -EINVAL; 1061fa6999e3SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1062fa6999e3SHarald Freudenberger /* CCA AES cipher key */ 1063fa6999e3SHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 1064fa6999e3SHarald Freudenberger return -EINVAL; 1065fa6999e3SHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 1066fa6999e3SHarald Freudenberger return -EINVAL; 1067fa6999e3SHarald Freudenberger } else { 1068fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 1069fa6999e3SHarald Freudenberger __func__, hdr->version); 1070fa6999e3SHarald Freudenberger return -EINVAL; 1071fa6999e3SHarald Freudenberger } 1072fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1073fa6999e3SHarald Freudenberger /* CCA ECC (private) key */ 1074fa6999e3SHarald Freudenberger if (keylen < sizeof(struct eccprivkeytoken)) 1075fa6999e3SHarald Freudenberger return -EINVAL; 1076fa6999e3SHarald Freudenberger if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) 1077fa6999e3SHarald Freudenberger return -EINVAL; 1078fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 1079fa6999e3SHarald Freudenberger struct pkey_protkey pkey; 1080fa6999e3SHarald Freudenberger 1081fa6999e3SHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, &pkey); 1082fa6999e3SHarald Freudenberger if (rc) 1083fa6999e3SHarald Freudenberger return rc; 1084fa6999e3SHarald Freudenberger memcpy(protkey, pkey.protkey, pkey.len); 1085fa6999e3SHarald Freudenberger *protkeylen = pkey.len; 1086fa6999e3SHarald Freudenberger *protkeytype = pkey.type; 1087fa6999e3SHarald Freudenberger return 0; 1088fa6999e3SHarald Freudenberger } else { 1089fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 1090fa6999e3SHarald Freudenberger __func__, hdr->type); 1091fa6999e3SHarald Freudenberger return -EINVAL; 1092fa6999e3SHarald Freudenberger } 1093fa6999e3SHarald Freudenberger 1094fa6999e3SHarald Freudenberger /* simple try all apqns from the list */ 1095fa6999e3SHarald Freudenberger for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 1096fa6999e3SHarald Freudenberger card = apqns[i].card; 1097fa6999e3SHarald Freudenberger dom = apqns[i].domain; 10982004b57cSHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && 10992004b57cSHarald Freudenberger (hdr->version == TOKVER_EP11_AES_WITH_HEADER || 11002004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && 11012004b57cSHarald Freudenberger is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) 1102fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1103fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 11042004b57cSHarald Freudenberger else if (hdr->type == TOKTYPE_NON_CCA && 11052004b57cSHarald Freudenberger hdr->version == TOKVER_EP11_AES && 11062004b57cSHarald Freudenberger is_ep11_keyblob(key)) 1107fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1108fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 1109fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1110fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_AES) 1111fa6999e3SHarald Freudenberger rc = cca_sec2protkey(card, dom, key, protkey, 1112fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1113fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1114fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) 1115fa6999e3SHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, protkey, 1116fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1117fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) 1118fa6999e3SHarald Freudenberger rc = cca_ecc2protkey(card, dom, key, protkey, 1119fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1120fa6999e3SHarald Freudenberger else 1121fa6999e3SHarald Freudenberger return -EINVAL; 1122fa6999e3SHarald Freudenberger } 1123fa6999e3SHarald Freudenberger 1124fa6999e3SHarald Freudenberger return rc; 1125fa6999e3SHarald Freudenberger } 1126fa6999e3SHarald Freudenberger 1127fb1136d6SIngo Franzki /* 1128e80d4af0SHarald Freudenberger * File io functions 1129e80d4af0SHarald Freudenberger */ 1130e80d4af0SHarald Freudenberger 1131f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen) 1132f2bbc96eSHarald Freudenberger { 1133f2bbc96eSHarald Freudenberger if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) 1134f2bbc96eSHarald Freudenberger return ERR_PTR(-EINVAL); 1135f2bbc96eSHarald Freudenberger 11368b57e7c8SMarkus Elfring return memdup_user(ukey, keylen); 1137f2bbc96eSHarald Freudenberger } 1138f2bbc96eSHarald Freudenberger 1139f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 1140f2bbc96eSHarald Freudenberger { 11418b57e7c8SMarkus Elfring if (!uapqns || nr_apqns == 0) 11428b57e7c8SMarkus Elfring return NULL; 1143f2bbc96eSHarald Freudenberger 11448b57e7c8SMarkus Elfring return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); 1145f2bbc96eSHarald Freudenberger } 1146f2bbc96eSHarald Freudenberger 1147e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 1148e80d4af0SHarald Freudenberger unsigned long arg) 1149e80d4af0SHarald Freudenberger { 1150e80d4af0SHarald Freudenberger int rc; 1151e80d4af0SHarald Freudenberger 1152e80d4af0SHarald Freudenberger switch (cmd) { 1153e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1154e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *)arg; 1155e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1156e80d4af0SHarald Freudenberger 1157e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1158e80d4af0SHarald Freudenberger return -EFAULT; 1159efc598e6SHarald Freudenberger rc = cca_genseckey(kgs.cardnr, kgs.domain, 1160efc598e6SHarald Freudenberger kgs.keytype, kgs.seckey.seckey); 1161efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 1162e80d4af0SHarald Freudenberger if (rc) 1163e80d4af0SHarald Freudenberger break; 1164e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1165e80d4af0SHarald Freudenberger return -EFAULT; 1166e80d4af0SHarald Freudenberger break; 1167e80d4af0SHarald Freudenberger } 1168e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1169e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *)arg; 1170e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1171e80d4af0SHarald Freudenberger 1172e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1173e80d4af0SHarald Freudenberger return -EFAULT; 1174efc598e6SHarald Freudenberger rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1175efc598e6SHarald Freudenberger kcs.clrkey.clrkey, kcs.seckey.seckey); 1176efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 1177e80d4af0SHarald Freudenberger if (rc) 1178e80d4af0SHarald Freudenberger break; 1179e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1180e80d4af0SHarald Freudenberger return -EFAULT; 1181e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1182e80d4af0SHarald Freudenberger break; 1183e80d4af0SHarald Freudenberger } 1184e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1185e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *)arg; 1186e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1187e80d4af0SHarald Freudenberger 1188e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1189e80d4af0SHarald Freudenberger return -EFAULT; 1190efc598e6SHarald Freudenberger rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 1191efc598e6SHarald Freudenberger ksp.seckey.seckey, ksp.protkey.protkey, 1192aab73d27SHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1193efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 1194e80d4af0SHarald Freudenberger if (rc) 1195e80d4af0SHarald Freudenberger break; 1196e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1197e80d4af0SHarald Freudenberger return -EFAULT; 1198e80d4af0SHarald Freudenberger break; 1199e80d4af0SHarald Freudenberger } 1200e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1201e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *)arg; 1202e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1203e80d4af0SHarald Freudenberger 1204e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1205e80d4af0SHarald Freudenberger return -EFAULT; 1206e80d4af0SHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, 1207e80d4af0SHarald Freudenberger &kcp.clrkey, &kcp.protkey); 1208ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1209e80d4af0SHarald Freudenberger if (rc) 1210e80d4af0SHarald Freudenberger break; 1211e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1212e80d4af0SHarald Freudenberger return -EFAULT; 1213e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1214e80d4af0SHarald Freudenberger break; 1215e80d4af0SHarald Freudenberger } 1216e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1217e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *)arg; 1218e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1219e80d4af0SHarald Freudenberger 1220e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1221e80d4af0SHarald Freudenberger return -EFAULT; 1222efc598e6SHarald Freudenberger rc = cca_findcard(kfc.seckey.seckey, 1223e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1224efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 1225efc598e6SHarald Freudenberger if (rc < 0) 1226e80d4af0SHarald Freudenberger break; 1227e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1228e80d4af0SHarald Freudenberger return -EFAULT; 1229e80d4af0SHarald Freudenberger break; 1230e80d4af0SHarald Freudenberger } 1231e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1232e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *)arg; 1233e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1234e80d4af0SHarald Freudenberger 1235e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1236e80d4af0SHarald Freudenberger return -EFAULT; 1237f2bbc96eSHarald Freudenberger rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey); 1238ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1239e80d4af0SHarald Freudenberger if (rc) 1240e80d4af0SHarald Freudenberger break; 1241e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1242e80d4af0SHarald Freudenberger return -EFAULT; 1243e80d4af0SHarald Freudenberger break; 1244e80d4af0SHarald Freudenberger } 1245e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1246e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *)arg; 1247e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1248e61a6134SHarald Freudenberger 1249e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1250e61a6134SHarald Freudenberger return -EFAULT; 1251e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1252e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1253ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1254e61a6134SHarald Freudenberger if (rc) 1255e61a6134SHarald Freudenberger break; 1256e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1257e61a6134SHarald Freudenberger return -EFAULT; 1258e61a6134SHarald Freudenberger break; 1259e61a6134SHarald Freudenberger } 1260a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1261a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *)arg; 1262a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1263a45a5c7dSIngo Franzki 1264a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1265a45a5c7dSIngo Franzki return -EFAULT; 1266a45a5c7dSIngo Franzki rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); 1267a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1268a45a5c7dSIngo Franzki if (rc) 1269a45a5c7dSIngo Franzki break; 1270a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1271a45a5c7dSIngo Franzki return -EFAULT; 1272a45a5c7dSIngo Franzki break; 1273a45a5c7dSIngo Franzki } 1274cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 1275cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *)arg; 1276cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 1277cb26b9ffSIngo Franzki 1278cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 1279cb26b9ffSIngo Franzki return -EFAULT; 1280cb26b9ffSIngo Franzki rc = pkey_verifyprotkey(&kvp.protkey); 1281cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 1282cb26b9ffSIngo Franzki break; 1283cb26b9ffSIngo Franzki } 1284fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 1285fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *)arg; 1286fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 1287183cb469SHarald Freudenberger u8 *kkey; 1288fb1136d6SIngo Franzki 1289fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 1290fb1136d6SIngo Franzki return -EFAULT; 1291f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1292f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1293f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1294fb1136d6SIngo Franzki rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); 1295fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 1296fb1136d6SIngo Franzki kfree(kkey); 1297fb1136d6SIngo Franzki if (rc) 1298fb1136d6SIngo Franzki break; 1299fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 1300fb1136d6SIngo Franzki return -EFAULT; 1301fb1136d6SIngo Franzki break; 1302fb1136d6SIngo Franzki } 1303f2bbc96eSHarald Freudenberger case PKEY_GENSECK2: { 1304f2bbc96eSHarald Freudenberger struct pkey_genseck2 __user *ugs = (void __user *)arg; 1305f2bbc96eSHarald Freudenberger struct pkey_genseck2 kgs; 1306f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1307f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1308f2bbc96eSHarald Freudenberger u8 *kkey; 1309f2bbc96eSHarald Freudenberger 1310f2bbc96eSHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1311f2bbc96eSHarald Freudenberger return -EFAULT; 1312f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 1313f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1314f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1315f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1316f2bbc96eSHarald Freudenberger if (!kkey) { 1317f2bbc96eSHarald Freudenberger kfree(apqns); 1318f2bbc96eSHarald Freudenberger return -ENOMEM; 1319f2bbc96eSHarald Freudenberger } 1320f2bbc96eSHarald Freudenberger rc = pkey_genseckey2(apqns, kgs.apqn_entries, 1321f2bbc96eSHarald Freudenberger kgs.type, kgs.size, kgs.keygenflags, 1322f2bbc96eSHarald Freudenberger kkey, &klen); 1323f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 1324f2bbc96eSHarald Freudenberger kfree(apqns); 1325f2bbc96eSHarald Freudenberger if (rc) { 1326f2bbc96eSHarald Freudenberger kfree(kkey); 1327f2bbc96eSHarald Freudenberger break; 1328f2bbc96eSHarald Freudenberger } 1329f2bbc96eSHarald Freudenberger if (kgs.key) { 1330f2bbc96eSHarald Freudenberger if (kgs.keylen < klen) { 1331f2bbc96eSHarald Freudenberger kfree(kkey); 1332f2bbc96eSHarald Freudenberger return -EINVAL; 1333f2bbc96eSHarald Freudenberger } 1334f2bbc96eSHarald Freudenberger if (copy_to_user(kgs.key, kkey, klen)) { 1335f2bbc96eSHarald Freudenberger kfree(kkey); 1336f2bbc96eSHarald Freudenberger return -EFAULT; 1337f2bbc96eSHarald Freudenberger } 1338f2bbc96eSHarald Freudenberger } 1339f2bbc96eSHarald Freudenberger kgs.keylen = klen; 1340f2bbc96eSHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1341f2bbc96eSHarald Freudenberger rc = -EFAULT; 1342f2bbc96eSHarald Freudenberger kfree(kkey); 1343f2bbc96eSHarald Freudenberger break; 1344f2bbc96eSHarald Freudenberger } 1345f2bbc96eSHarald Freudenberger case PKEY_CLR2SECK2: { 1346f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 __user *ucs = (void __user *)arg; 1347f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 kcs; 1348f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1349f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1350f2bbc96eSHarald Freudenberger u8 *kkey; 1351f2bbc96eSHarald Freudenberger 1352f2bbc96eSHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1353f2bbc96eSHarald Freudenberger return -EFAULT; 1354f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 1355f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1356f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1357f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1358f2bbc96eSHarald Freudenberger if (!kkey) { 1359f2bbc96eSHarald Freudenberger kfree(apqns); 1360f2bbc96eSHarald Freudenberger return -ENOMEM; 1361f2bbc96eSHarald Freudenberger } 1362f2bbc96eSHarald Freudenberger rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 1363f2bbc96eSHarald Freudenberger kcs.type, kcs.size, kcs.keygenflags, 1364f2bbc96eSHarald Freudenberger kcs.clrkey.clrkey, kkey, &klen); 1365f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 1366f2bbc96eSHarald Freudenberger kfree(apqns); 1367f2bbc96eSHarald Freudenberger if (rc) { 1368f2bbc96eSHarald Freudenberger kfree(kkey); 1369f2bbc96eSHarald Freudenberger break; 1370f2bbc96eSHarald Freudenberger } 1371f2bbc96eSHarald Freudenberger if (kcs.key) { 1372f2bbc96eSHarald Freudenberger if (kcs.keylen < klen) { 1373f2bbc96eSHarald Freudenberger kfree(kkey); 1374f2bbc96eSHarald Freudenberger return -EINVAL; 1375f2bbc96eSHarald Freudenberger } 1376f2bbc96eSHarald Freudenberger if (copy_to_user(kcs.key, kkey, klen)) { 1377f2bbc96eSHarald Freudenberger kfree(kkey); 1378f2bbc96eSHarald Freudenberger return -EFAULT; 1379f2bbc96eSHarald Freudenberger } 1380f2bbc96eSHarald Freudenberger } 1381f2bbc96eSHarald Freudenberger kcs.keylen = klen; 1382f2bbc96eSHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1383f2bbc96eSHarald Freudenberger rc = -EFAULT; 1384f2bbc96eSHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1385f2bbc96eSHarald Freudenberger kfree(kkey); 1386f2bbc96eSHarald Freudenberger break; 1387f2bbc96eSHarald Freudenberger } 1388f2bbc96eSHarald Freudenberger case PKEY_VERIFYKEY2: { 1389f2bbc96eSHarald Freudenberger struct pkey_verifykey2 __user *uvk = (void __user *)arg; 1390f2bbc96eSHarald Freudenberger struct pkey_verifykey2 kvk; 1391f2bbc96eSHarald Freudenberger u8 *kkey; 1392f2bbc96eSHarald Freudenberger 1393f2bbc96eSHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1394f2bbc96eSHarald Freudenberger return -EFAULT; 1395f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kvk.key, kvk.keylen); 1396f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1397f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1398f2bbc96eSHarald Freudenberger rc = pkey_verifykey2(kkey, kvk.keylen, 1399f2bbc96eSHarald Freudenberger &kvk.cardnr, &kvk.domain, 1400f2bbc96eSHarald Freudenberger &kvk.type, &kvk.size, &kvk.flags); 1401f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 1402f2bbc96eSHarald Freudenberger kfree(kkey); 1403f2bbc96eSHarald Freudenberger if (rc) 1404f2bbc96eSHarald Freudenberger break; 1405f2bbc96eSHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1406f2bbc96eSHarald Freudenberger return -EFAULT; 1407f2bbc96eSHarald Freudenberger break; 1408f2bbc96eSHarald Freudenberger } 1409f2bbc96eSHarald Freudenberger case PKEY_KBLOB2PROTK2: { 1410f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 __user *utp = (void __user *)arg; 1411f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 ktp; 1412f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1413f2bbc96eSHarald Freudenberger u8 *kkey; 1414f2bbc96eSHarald Freudenberger 1415f2bbc96eSHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1416f2bbc96eSHarald Freudenberger return -EFAULT; 1417f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1418f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1419f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1420f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1421f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1422f2bbc96eSHarald Freudenberger kfree(apqns); 1423f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1424f2bbc96eSHarald Freudenberger } 1425f2bbc96eSHarald Freudenberger rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 1426f2bbc96eSHarald Freudenberger kkey, ktp.keylen, &ktp.protkey); 1427f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 1428f2bbc96eSHarald Freudenberger kfree(apqns); 1429f2bbc96eSHarald Freudenberger kfree(kkey); 1430f2bbc96eSHarald Freudenberger if (rc) 1431f2bbc96eSHarald Freudenberger break; 1432f2bbc96eSHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1433f2bbc96eSHarald Freudenberger return -EFAULT; 1434f2bbc96eSHarald Freudenberger break; 1435f2bbc96eSHarald Freudenberger } 1436f2bbc96eSHarald Freudenberger case PKEY_APQNS4K: { 1437f2bbc96eSHarald Freudenberger struct pkey_apqns4key __user *uak = (void __user *)arg; 1438f2bbc96eSHarald Freudenberger struct pkey_apqns4key kak; 1439f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1440f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1441f2bbc96eSHarald Freudenberger u8 *kkey; 1442f2bbc96eSHarald Freudenberger 1443f2bbc96eSHarald Freudenberger if (copy_from_user(&kak, uak, sizeof(kak))) 1444f2bbc96eSHarald Freudenberger return -EFAULT; 1445f2bbc96eSHarald Freudenberger nr_apqns = kak.apqn_entries; 1446f2bbc96eSHarald Freudenberger if (nr_apqns) { 1447f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1448f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1449f2bbc96eSHarald Freudenberger GFP_KERNEL); 1450f2bbc96eSHarald Freudenberger if (!apqns) 1451f2bbc96eSHarald Freudenberger return -ENOMEM; 1452f2bbc96eSHarald Freudenberger } 1453f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kak.key, kak.keylen); 1454f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1455f2bbc96eSHarald Freudenberger kfree(apqns); 1456f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1457f2bbc96eSHarald Freudenberger } 1458f2bbc96eSHarald Freudenberger rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 1459f2bbc96eSHarald Freudenberger apqns, &nr_apqns); 1460f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 1461f2bbc96eSHarald Freudenberger kfree(kkey); 1462f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1463f2bbc96eSHarald Freudenberger kfree(apqns); 1464f2bbc96eSHarald Freudenberger break; 1465f2bbc96eSHarald Freudenberger } 1466f2bbc96eSHarald Freudenberger if (!rc && kak.apqns) { 1467f2bbc96eSHarald Freudenberger if (nr_apqns > kak.apqn_entries) { 1468f2bbc96eSHarald Freudenberger kfree(apqns); 1469f2bbc96eSHarald Freudenberger return -EINVAL; 1470f2bbc96eSHarald Freudenberger } 1471f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1472f2bbc96eSHarald Freudenberger if (len) { 1473f2bbc96eSHarald Freudenberger if (copy_to_user(kak.apqns, apqns, len)) { 1474f2bbc96eSHarald Freudenberger kfree(apqns); 1475f2bbc96eSHarald Freudenberger return -EFAULT; 1476f2bbc96eSHarald Freudenberger } 1477f2bbc96eSHarald Freudenberger } 1478f2bbc96eSHarald Freudenberger } 1479f2bbc96eSHarald Freudenberger kak.apqn_entries = nr_apqns; 1480f2bbc96eSHarald Freudenberger if (copy_to_user(uak, &kak, sizeof(kak))) 1481f2bbc96eSHarald Freudenberger rc = -EFAULT; 1482f2bbc96eSHarald Freudenberger kfree(apqns); 1483f2bbc96eSHarald Freudenberger break; 1484f2bbc96eSHarald Freudenberger } 1485f2bbc96eSHarald Freudenberger case PKEY_APQNS4KT: { 1486f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype __user *uat = (void __user *)arg; 1487f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype kat; 1488f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1489f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1490f2bbc96eSHarald Freudenberger 1491f2bbc96eSHarald Freudenberger if (copy_from_user(&kat, uat, sizeof(kat))) 1492f2bbc96eSHarald Freudenberger return -EFAULT; 1493f2bbc96eSHarald Freudenberger nr_apqns = kat.apqn_entries; 1494f2bbc96eSHarald Freudenberger if (nr_apqns) { 1495f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1496f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1497f2bbc96eSHarald Freudenberger GFP_KERNEL); 1498f2bbc96eSHarald Freudenberger if (!apqns) 1499f2bbc96eSHarald Freudenberger return -ENOMEM; 1500f2bbc96eSHarald Freudenberger } 1501f2bbc96eSHarald Freudenberger rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 1502f2bbc96eSHarald Freudenberger kat.flags, apqns, &nr_apqns); 1503f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 1504f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1505f2bbc96eSHarald Freudenberger kfree(apqns); 1506f2bbc96eSHarald Freudenberger break; 1507f2bbc96eSHarald Freudenberger } 1508f2bbc96eSHarald Freudenberger if (!rc && kat.apqns) { 1509f2bbc96eSHarald Freudenberger if (nr_apqns > kat.apqn_entries) { 1510f2bbc96eSHarald Freudenberger kfree(apqns); 1511f2bbc96eSHarald Freudenberger return -EINVAL; 1512f2bbc96eSHarald Freudenberger } 1513f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1514f2bbc96eSHarald Freudenberger if (len) { 1515f2bbc96eSHarald Freudenberger if (copy_to_user(kat.apqns, apqns, len)) { 1516f2bbc96eSHarald Freudenberger kfree(apqns); 1517f2bbc96eSHarald Freudenberger return -EFAULT; 1518f2bbc96eSHarald Freudenberger } 1519f2bbc96eSHarald Freudenberger } 1520f2bbc96eSHarald Freudenberger } 1521f2bbc96eSHarald Freudenberger kat.apqn_entries = nr_apqns; 1522f2bbc96eSHarald Freudenberger if (copy_to_user(uat, &kat, sizeof(kat))) 1523f2bbc96eSHarald Freudenberger rc = -EFAULT; 1524f2bbc96eSHarald Freudenberger kfree(apqns); 1525f2bbc96eSHarald Freudenberger break; 1526f2bbc96eSHarald Freudenberger } 1527fa6999e3SHarald Freudenberger case PKEY_KBLOB2PROTK3: { 1528fa6999e3SHarald Freudenberger struct pkey_kblob2pkey3 __user *utp = (void __user *)arg; 1529fa6999e3SHarald Freudenberger struct pkey_kblob2pkey3 ktp; 1530fa6999e3SHarald Freudenberger struct pkey_apqn *apqns = NULL; 1531fa6999e3SHarald Freudenberger u32 protkeylen = PROTKEYBLOBBUFSIZE; 1532fa6999e3SHarald Freudenberger u8 *kkey, *protkey; 1533fa6999e3SHarald Freudenberger 1534fa6999e3SHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1535fa6999e3SHarald Freudenberger return -EFAULT; 1536fa6999e3SHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1537fa6999e3SHarald Freudenberger if (IS_ERR(apqns)) 1538fa6999e3SHarald Freudenberger return PTR_ERR(apqns); 1539fa6999e3SHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1540fa6999e3SHarald Freudenberger if (IS_ERR(kkey)) { 1541fa6999e3SHarald Freudenberger kfree(apqns); 1542fa6999e3SHarald Freudenberger return PTR_ERR(kkey); 1543fa6999e3SHarald Freudenberger } 1544fa6999e3SHarald Freudenberger protkey = kmalloc(protkeylen, GFP_KERNEL); 1545fa6999e3SHarald Freudenberger if (!protkey) { 1546fa6999e3SHarald Freudenberger kfree(apqns); 1547fa6999e3SHarald Freudenberger kfree(kkey); 1548fa6999e3SHarald Freudenberger return -ENOMEM; 1549fa6999e3SHarald Freudenberger } 1550fa6999e3SHarald Freudenberger rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, kkey, 1551fa6999e3SHarald Freudenberger ktp.keylen, &ktp.pkeytype, 1552fa6999e3SHarald Freudenberger protkey, &protkeylen); 1553fa6999e3SHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); 1554fa6999e3SHarald Freudenberger kfree(apqns); 1555fa6999e3SHarald Freudenberger kfree(kkey); 1556fa6999e3SHarald Freudenberger if (rc) { 1557fa6999e3SHarald Freudenberger kfree(protkey); 1558fa6999e3SHarald Freudenberger break; 1559fa6999e3SHarald Freudenberger } 1560fa6999e3SHarald Freudenberger if (ktp.pkey && ktp.pkeylen) { 1561fa6999e3SHarald Freudenberger if (protkeylen > ktp.pkeylen) { 1562fa6999e3SHarald Freudenberger kfree(protkey); 1563fa6999e3SHarald Freudenberger return -EINVAL; 1564fa6999e3SHarald Freudenberger } 1565fa6999e3SHarald Freudenberger if (copy_to_user(ktp.pkey, protkey, protkeylen)) { 1566fa6999e3SHarald Freudenberger kfree(protkey); 1567fa6999e3SHarald Freudenberger return -EFAULT; 1568fa6999e3SHarald Freudenberger } 1569fa6999e3SHarald Freudenberger } 1570fa6999e3SHarald Freudenberger kfree(protkey); 1571fa6999e3SHarald Freudenberger ktp.pkeylen = protkeylen; 1572fa6999e3SHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1573fa6999e3SHarald Freudenberger return -EFAULT; 1574fa6999e3SHarald Freudenberger break; 1575fa6999e3SHarald Freudenberger } 1576e80d4af0SHarald Freudenberger default: 1577e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1578e80d4af0SHarald Freudenberger return -ENOTTY; 1579e80d4af0SHarald Freudenberger } 1580e80d4af0SHarald Freudenberger 1581e80d4af0SHarald Freudenberger return rc; 1582e80d4af0SHarald Freudenberger } 1583e80d4af0SHarald Freudenberger 1584e80d4af0SHarald Freudenberger /* 1585e80d4af0SHarald Freudenberger * Sysfs and file io operations 1586e80d4af0SHarald Freudenberger */ 1587d632c047SIngo Franzki 1588d632c047SIngo Franzki /* 1589d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1590d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1591d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1592d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1593d632c047SIngo Franzki */ 1594d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1595d632c047SIngo Franzki loff_t off, size_t count) 1596d632c047SIngo Franzki { 1597d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1598d632c047SIngo Franzki struct pkey_protkey protkey; 1599d632c047SIngo Franzki int rc; 1600d632c047SIngo Franzki 1601d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1602d632c047SIngo Franzki return -EINVAL; 1603d632c047SIngo Franzki if (is_xts) 1604d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1605d632c047SIngo Franzki return -EINVAL; 1606d632c047SIngo Franzki 1607d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1608d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1609d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1610d632c047SIngo Franzki protkeytoken.keytype = keytype; 1611d632c047SIngo Franzki 1612d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1613d632c047SIngo Franzki if (rc) 1614d632c047SIngo Franzki return rc; 1615d632c047SIngo Franzki 1616d632c047SIngo Franzki protkeytoken.len = protkey.len; 1617d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1618d632c047SIngo Franzki 1619d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1620d632c047SIngo Franzki 1621d632c047SIngo Franzki if (is_xts) { 1622d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1623d632c047SIngo Franzki if (rc) 1624d632c047SIngo Franzki return rc; 1625d632c047SIngo Franzki 1626d632c047SIngo Franzki protkeytoken.len = protkey.len; 1627d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1628d632c047SIngo Franzki 1629d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1630d632c047SIngo Franzki sizeof(protkeytoken)); 1631d632c047SIngo Franzki 1632d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1633d632c047SIngo Franzki } 1634d632c047SIngo Franzki 1635d632c047SIngo Franzki return sizeof(protkeytoken); 1636d632c047SIngo Franzki } 1637d632c047SIngo Franzki 1638d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1639d632c047SIngo Franzki struct kobject *kobj, 1640d632c047SIngo Franzki struct bin_attribute *attr, 1641d632c047SIngo Franzki char *buf, loff_t off, 1642d632c047SIngo Franzki size_t count) 1643d632c047SIngo Franzki { 1644d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1645d632c047SIngo Franzki off, count); 1646d632c047SIngo Franzki } 1647d632c047SIngo Franzki 1648d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1649d632c047SIngo Franzki struct kobject *kobj, 1650d632c047SIngo Franzki struct bin_attribute *attr, 1651d632c047SIngo Franzki char *buf, loff_t off, 1652d632c047SIngo Franzki size_t count) 1653d632c047SIngo Franzki { 1654d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1655d632c047SIngo Franzki off, count); 1656d632c047SIngo Franzki } 1657d632c047SIngo Franzki 1658d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1659d632c047SIngo Franzki struct kobject *kobj, 1660d632c047SIngo Franzki struct bin_attribute *attr, 1661d632c047SIngo Franzki char *buf, loff_t off, 1662d632c047SIngo Franzki size_t count) 1663d632c047SIngo Franzki { 1664d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1665d632c047SIngo Franzki off, count); 1666d632c047SIngo Franzki } 1667d632c047SIngo Franzki 1668d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1669d632c047SIngo Franzki struct kobject *kobj, 1670d632c047SIngo Franzki struct bin_attribute *attr, 1671d632c047SIngo Franzki char *buf, loff_t off, 1672d632c047SIngo Franzki size_t count) 1673d632c047SIngo Franzki { 1674d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1675d632c047SIngo Franzki off, count); 1676d632c047SIngo Franzki } 1677d632c047SIngo Franzki 1678d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_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_256, true, buf, 1685d632c047SIngo Franzki off, count); 1686d632c047SIngo Franzki } 1687d632c047SIngo Franzki 1688d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1689d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1690d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1691d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1692d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1693d632c047SIngo Franzki 1694d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1695d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1696d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1697d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1698d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1699d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1700d632c047SIngo Franzki NULL 1701d632c047SIngo Franzki }; 1702d632c047SIngo Franzki 1703d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1704d632c047SIngo Franzki .name = "protkey", 1705d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1706d632c047SIngo Franzki }; 1707d632c047SIngo Franzki 1708af504452SIngo Franzki /* 1709af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1710af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1711af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1712af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1713af504452SIngo Franzki */ 1714af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1715af504452SIngo Franzki loff_t off, size_t count) 1716af504452SIngo Franzki { 1717af504452SIngo Franzki int rc; 1718efc598e6SHarald Freudenberger struct pkey_seckey *seckey = (struct pkey_seckey *)buf; 1719af504452SIngo Franzki 1720af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1721af504452SIngo Franzki return -EINVAL; 1722af504452SIngo Franzki if (is_xts) 1723af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1724af504452SIngo Franzki return -EINVAL; 1725af504452SIngo Franzki 1726efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1727af504452SIngo Franzki if (rc) 1728af504452SIngo Franzki return rc; 1729af504452SIngo Franzki 1730af504452SIngo Franzki if (is_xts) { 1731efc598e6SHarald Freudenberger seckey++; 1732efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1733af504452SIngo Franzki if (rc) 1734af504452SIngo Franzki return rc; 1735af504452SIngo Franzki 1736af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1737af504452SIngo Franzki } 1738af504452SIngo Franzki 1739af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1740af504452SIngo Franzki } 1741af504452SIngo Franzki 1742af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1743af504452SIngo Franzki struct kobject *kobj, 1744af504452SIngo Franzki struct bin_attribute *attr, 1745af504452SIngo Franzki char *buf, loff_t off, 1746af504452SIngo Franzki size_t count) 1747af504452SIngo Franzki { 1748af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1749af504452SIngo Franzki off, count); 1750af504452SIngo Franzki } 1751af504452SIngo Franzki 1752af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1753af504452SIngo Franzki struct kobject *kobj, 1754af504452SIngo Franzki struct bin_attribute *attr, 1755af504452SIngo Franzki char *buf, loff_t off, 1756af504452SIngo Franzki size_t count) 1757af504452SIngo Franzki { 1758af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1759af504452SIngo Franzki off, count); 1760af504452SIngo Franzki } 1761af504452SIngo Franzki 1762af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1763af504452SIngo Franzki struct kobject *kobj, 1764af504452SIngo Franzki struct bin_attribute *attr, 1765af504452SIngo Franzki char *buf, loff_t off, 1766af504452SIngo Franzki size_t count) 1767af504452SIngo Franzki { 1768af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1769af504452SIngo Franzki off, count); 1770af504452SIngo Franzki } 1771af504452SIngo Franzki 1772af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1773af504452SIngo Franzki struct kobject *kobj, 1774af504452SIngo Franzki struct bin_attribute *attr, 1775af504452SIngo Franzki char *buf, loff_t off, 1776af504452SIngo Franzki size_t count) 1777af504452SIngo Franzki { 1778af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1779af504452SIngo Franzki off, count); 1780af504452SIngo Franzki } 1781af504452SIngo Franzki 1782af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_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_256, true, buf, 1789af504452SIngo Franzki off, count); 1790af504452SIngo Franzki } 1791af504452SIngo Franzki 1792af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1793af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1794af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1795af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1796af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1797af504452SIngo Franzki 1798af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1799af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1800af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1801af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1802af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1803af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1804af504452SIngo Franzki NULL 1805af504452SIngo Franzki }; 1806af504452SIngo Franzki 1807af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1808af504452SIngo Franzki .name = "ccadata", 1809af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1810af504452SIngo Franzki }; 1811af504452SIngo Franzki 1812f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) 1813f71fee27SIngo Franzki 1814f71fee27SIngo Franzki /* 1815f71fee27SIngo Franzki * Sysfs attribute read function for all secure key ccacipher binary attributes. 1816f71fee27SIngo Franzki * The implementation can not deal with partial reads, because a new random 1817f71fee27SIngo Franzki * secure key blob is generated with each read. In case of partial reads 1818f71fee27SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1819f71fee27SIngo Franzki */ 1820f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, 1821f71fee27SIngo Franzki bool is_xts, char *buf, loff_t off, 1822f71fee27SIngo Franzki size_t count) 1823f71fee27SIngo Franzki { 182455d0a513SHarald Freudenberger int i, rc, card, dom; 182555d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 182655d0a513SHarald Freudenberger size_t keysize = CCACIPHERTOKENSIZE; 1827f71fee27SIngo Franzki 1828f71fee27SIngo Franzki if (off != 0 || count < CCACIPHERTOKENSIZE) 1829f71fee27SIngo Franzki return -EINVAL; 1830f71fee27SIngo Franzki if (is_xts) 1831f71fee27SIngo Franzki if (count < 2 * CCACIPHERTOKENSIZE) 1832f71fee27SIngo Franzki return -EINVAL; 1833f71fee27SIngo Franzki 183455d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 183555d0a513SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 183632ca04bbSHarald Freudenberger ZCRYPT_CEX6, 0, 0, 0, 0); 1837f71fee27SIngo Franzki if (rc) 1838f71fee27SIngo Franzki return rc; 183955d0a513SHarald Freudenberger 184055d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 184155d0a513SHarald Freudenberger 184255d0a513SHarald Freudenberger /* simple try all apqns from the list */ 184355d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 184455d0a513SHarald Freudenberger card = apqns[i] >> 16; 184555d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 184655d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 184755d0a513SHarald Freudenberger if (rc == 0) 184855d0a513SHarald Freudenberger break; 184955d0a513SHarald Freudenberger } 185055d0a513SHarald Freudenberger if (rc) 185155d0a513SHarald Freudenberger return rc; 1852f71fee27SIngo Franzki 1853f71fee27SIngo Franzki if (is_xts) { 1854f71fee27SIngo Franzki keysize = CCACIPHERTOKENSIZE; 185555d0a513SHarald Freudenberger buf += CCACIPHERTOKENSIZE; 185655d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 185755d0a513SHarald Freudenberger if (rc == 0) 1858f71fee27SIngo Franzki return 2 * CCACIPHERTOKENSIZE; 1859f71fee27SIngo Franzki } 1860f71fee27SIngo Franzki 1861f71fee27SIngo Franzki return CCACIPHERTOKENSIZE; 1862f71fee27SIngo Franzki } 1863f71fee27SIngo Franzki 1864f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp, 1865f71fee27SIngo Franzki struct kobject *kobj, 1866f71fee27SIngo Franzki struct bin_attribute *attr, 1867f71fee27SIngo Franzki char *buf, loff_t off, 1868f71fee27SIngo Franzki size_t count) 1869f71fee27SIngo Franzki { 1870f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 1871f71fee27SIngo Franzki off, count); 1872f71fee27SIngo Franzki } 1873f71fee27SIngo Franzki 1874f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp, 1875f71fee27SIngo Franzki struct kobject *kobj, 1876f71fee27SIngo Franzki struct bin_attribute *attr, 1877f71fee27SIngo Franzki char *buf, loff_t off, 1878f71fee27SIngo Franzki size_t count) 1879f71fee27SIngo Franzki { 1880f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 1881f71fee27SIngo Franzki off, count); 1882f71fee27SIngo Franzki } 1883f71fee27SIngo Franzki 1884f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp, 1885f71fee27SIngo Franzki struct kobject *kobj, 1886f71fee27SIngo Franzki struct bin_attribute *attr, 1887f71fee27SIngo Franzki char *buf, loff_t off, 1888f71fee27SIngo Franzki size_t count) 1889f71fee27SIngo Franzki { 1890f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 1891f71fee27SIngo Franzki off, count); 1892f71fee27SIngo Franzki } 1893f71fee27SIngo Franzki 1894f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp, 1895f71fee27SIngo Franzki struct kobject *kobj, 1896f71fee27SIngo Franzki struct bin_attribute *attr, 1897f71fee27SIngo Franzki char *buf, loff_t off, 1898f71fee27SIngo Franzki size_t count) 1899f71fee27SIngo Franzki { 1900f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 1901f71fee27SIngo Franzki off, count); 1902f71fee27SIngo Franzki } 1903f71fee27SIngo Franzki 1904f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_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_256, true, buf, 1911f71fee27SIngo Franzki off, count); 1912f71fee27SIngo Franzki } 1913f71fee27SIngo Franzki 1914f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); 1915f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); 1916f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); 1917f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); 1918f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); 1919f71fee27SIngo Franzki 1920f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = { 1921f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128, 1922f71fee27SIngo Franzki &bin_attr_ccacipher_aes_192, 1923f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256, 1924f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128_xts, 1925f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256_xts, 1926f71fee27SIngo Franzki NULL 1927f71fee27SIngo Franzki }; 1928f71fee27SIngo Franzki 1929f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = { 1930f71fee27SIngo Franzki .name = "ccacipher", 1931f71fee27SIngo Franzki .bin_attrs = ccacipher_attrs, 1932f71fee27SIngo Franzki }; 1933f71fee27SIngo Franzki 193455d0a513SHarald Freudenberger /* 193555d0a513SHarald Freudenberger * Sysfs attribute read function for all ep11 aes key binary attributes. 193655d0a513SHarald Freudenberger * The implementation can not deal with partial reads, because a new random 193755d0a513SHarald Freudenberger * secure key blob is generated with each read. In case of partial reads 193855d0a513SHarald Freudenberger * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 193955d0a513SHarald Freudenberger * This function and the sysfs attributes using it provide EP11 key blobs 194055d0a513SHarald Freudenberger * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently 194155d0a513SHarald Freudenberger * 320 bytes. 194255d0a513SHarald Freudenberger */ 194355d0a513SHarald Freudenberger static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, 194455d0a513SHarald Freudenberger bool is_xts, char *buf, loff_t off, 194555d0a513SHarald Freudenberger size_t count) 194655d0a513SHarald Freudenberger { 194755d0a513SHarald Freudenberger int i, rc, card, dom; 194855d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 194955d0a513SHarald Freudenberger size_t keysize = MAXEP11AESKEYBLOBSIZE; 195055d0a513SHarald Freudenberger 195155d0a513SHarald Freudenberger if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) 195255d0a513SHarald Freudenberger return -EINVAL; 195355d0a513SHarald Freudenberger if (is_xts) 195455d0a513SHarald Freudenberger if (count < 2 * MAXEP11AESKEYBLOBSIZE) 195555d0a513SHarald Freudenberger return -EINVAL; 195655d0a513SHarald Freudenberger 195755d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 195855d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 195955d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 196055d0a513SHarald Freudenberger if (rc) 196155d0a513SHarald Freudenberger return rc; 196255d0a513SHarald Freudenberger 196355d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 196455d0a513SHarald Freudenberger 196555d0a513SHarald Freudenberger /* simple try all apqns from the list */ 196655d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 196755d0a513SHarald Freudenberger card = apqns[i] >> 16; 196855d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 196955d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 197055d0a513SHarald Freudenberger if (rc == 0) 197155d0a513SHarald Freudenberger break; 197255d0a513SHarald Freudenberger } 197355d0a513SHarald Freudenberger if (rc) 197455d0a513SHarald Freudenberger return rc; 197555d0a513SHarald Freudenberger 197655d0a513SHarald Freudenberger if (is_xts) { 197755d0a513SHarald Freudenberger keysize = MAXEP11AESKEYBLOBSIZE; 197855d0a513SHarald Freudenberger buf += MAXEP11AESKEYBLOBSIZE; 197955d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 198055d0a513SHarald Freudenberger if (rc == 0) 198155d0a513SHarald Freudenberger return 2 * MAXEP11AESKEYBLOBSIZE; 198255d0a513SHarald Freudenberger } 198355d0a513SHarald Freudenberger 198455d0a513SHarald Freudenberger return MAXEP11AESKEYBLOBSIZE; 198555d0a513SHarald Freudenberger } 198655d0a513SHarald Freudenberger 198755d0a513SHarald Freudenberger static ssize_t ep11_aes_128_read(struct file *filp, 198855d0a513SHarald Freudenberger struct kobject *kobj, 198955d0a513SHarald Freudenberger struct bin_attribute *attr, 199055d0a513SHarald Freudenberger char *buf, loff_t off, 199155d0a513SHarald Freudenberger size_t count) 199255d0a513SHarald Freudenberger { 199355d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 199455d0a513SHarald Freudenberger off, count); 199555d0a513SHarald Freudenberger } 199655d0a513SHarald Freudenberger 199755d0a513SHarald Freudenberger static ssize_t ep11_aes_192_read(struct file *filp, 199855d0a513SHarald Freudenberger struct kobject *kobj, 199955d0a513SHarald Freudenberger struct bin_attribute *attr, 200055d0a513SHarald Freudenberger char *buf, loff_t off, 200155d0a513SHarald Freudenberger size_t count) 200255d0a513SHarald Freudenberger { 200355d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 200455d0a513SHarald Freudenberger off, count); 200555d0a513SHarald Freudenberger } 200655d0a513SHarald Freudenberger 200755d0a513SHarald Freudenberger static ssize_t ep11_aes_256_read(struct file *filp, 200855d0a513SHarald Freudenberger struct kobject *kobj, 200955d0a513SHarald Freudenberger struct bin_attribute *attr, 201055d0a513SHarald Freudenberger char *buf, loff_t off, 201155d0a513SHarald Freudenberger size_t count) 201255d0a513SHarald Freudenberger { 201355d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 201455d0a513SHarald Freudenberger off, count); 201555d0a513SHarald Freudenberger } 201655d0a513SHarald Freudenberger 201755d0a513SHarald Freudenberger static ssize_t ep11_aes_128_xts_read(struct file *filp, 201855d0a513SHarald Freudenberger struct kobject *kobj, 201955d0a513SHarald Freudenberger struct bin_attribute *attr, 202055d0a513SHarald Freudenberger char *buf, loff_t off, 202155d0a513SHarald Freudenberger size_t count) 202255d0a513SHarald Freudenberger { 202355d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 202455d0a513SHarald Freudenberger off, count); 202555d0a513SHarald Freudenberger } 202655d0a513SHarald Freudenberger 202755d0a513SHarald Freudenberger static ssize_t ep11_aes_256_xts_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_256, true, buf, 203455d0a513SHarald Freudenberger off, count); 203555d0a513SHarald Freudenberger } 203655d0a513SHarald Freudenberger 203755d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE); 203855d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE); 203955d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE); 204055d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE); 204155d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE); 204255d0a513SHarald Freudenberger 204355d0a513SHarald Freudenberger static struct bin_attribute *ep11_attrs[] = { 204455d0a513SHarald Freudenberger &bin_attr_ep11_aes_128, 204555d0a513SHarald Freudenberger &bin_attr_ep11_aes_192, 204655d0a513SHarald Freudenberger &bin_attr_ep11_aes_256, 204755d0a513SHarald Freudenberger &bin_attr_ep11_aes_128_xts, 204855d0a513SHarald Freudenberger &bin_attr_ep11_aes_256_xts, 204955d0a513SHarald Freudenberger NULL 205055d0a513SHarald Freudenberger }; 205155d0a513SHarald Freudenberger 205255d0a513SHarald Freudenberger static struct attribute_group ep11_attr_group = { 205355d0a513SHarald Freudenberger .name = "ep11", 205455d0a513SHarald Freudenberger .bin_attrs = ep11_attrs, 205555d0a513SHarald Freudenberger }; 205655d0a513SHarald Freudenberger 2057d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 2058d632c047SIngo Franzki &protkey_attr_group, 2059af504452SIngo Franzki &ccadata_attr_group, 2060f71fee27SIngo Franzki &ccacipher_attr_group, 206155d0a513SHarald Freudenberger &ep11_attr_group, 2062d632c047SIngo Franzki NULL, 2063d632c047SIngo Franzki }; 2064d632c047SIngo Franzki 2065e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 2066e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 2067e80d4af0SHarald Freudenberger .open = nonseekable_open, 2068e80d4af0SHarald Freudenberger .llseek = no_llseek, 2069e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 2070e80d4af0SHarald Freudenberger }; 2071e80d4af0SHarald Freudenberger 2072e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 2073e80d4af0SHarald Freudenberger .name = "pkey", 2074e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 2075e80d4af0SHarald Freudenberger .mode = 0666, 2076e80d4af0SHarald Freudenberger .fops = &pkey_fops, 2077d632c047SIngo Franzki .groups = pkey_attr_groups, 2078e80d4af0SHarald Freudenberger }; 2079e80d4af0SHarald Freudenberger 2080e80d4af0SHarald Freudenberger /* 2081e80d4af0SHarald Freudenberger * Module init 2082e80d4af0SHarald Freudenberger */ 2083cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 2084e80d4af0SHarald Freudenberger { 20855b35047eSHarald Freudenberger cpacf_mask_t func_mask; 2086e80d4af0SHarald Freudenberger 2087f822ad2cSHarald Freudenberger /* 2088f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 2089f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 2090f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 2091f822ad2cSHarald Freudenberger * are able to work with protected keys. 2092f822ad2cSHarald Freudenberger */ 20935b35047eSHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &func_mask)) 209458443b67SDavid Hildenbrand return -ENODEV; 2095e80d4af0SHarald Freudenberger 2096cb26b9ffSIngo Franzki /* check for kmc instructions available */ 20975b35047eSHarald Freudenberger if (!cpacf_query(CPACF_KMC, &func_mask)) 209858443b67SDavid Hildenbrand return -ENODEV; 20995b35047eSHarald Freudenberger if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) || 21005b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) || 21015b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256)) 210258443b67SDavid Hildenbrand return -ENODEV; 2103cb26b9ffSIngo Franzki 2104e80d4af0SHarald Freudenberger pkey_debug_init(); 2105e80d4af0SHarald Freudenberger 2106e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 2107e80d4af0SHarald Freudenberger } 2108e80d4af0SHarald Freudenberger 2109e80d4af0SHarald Freudenberger /* 2110e80d4af0SHarald Freudenberger * Module exit 2111e80d4af0SHarald Freudenberger */ 2112e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 2113e80d4af0SHarald Freudenberger { 2114e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 2115e80d4af0SHarald Freudenberger pkey_debug_exit(); 2116e80d4af0SHarald Freudenberger } 2117e80d4af0SHarald Freudenberger 2118*0a5f9b38SHeiko Carstens module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init); 2119e80d4af0SHarald Freudenberger module_exit(pkey_exit); 2120