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 */ 35f2bbc96eSHarald Freudenberger #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ 36f2bbc96eSHarald Freudenberger 37f822ad2cSHarald Freudenberger /* mask of available pckmo subfunctions, fetched once at module init */ 38f822ad2cSHarald Freudenberger static cpacf_mask_t pckmo_functions; 39f822ad2cSHarald Freudenberger 40e80d4af0SHarald Freudenberger /* 41e80d4af0SHarald Freudenberger * debug feature data and functions 42e80d4af0SHarald Freudenberger */ 43e80d4af0SHarald Freudenberger 44e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 45e80d4af0SHarald Freudenberger 46e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 47e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 48e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 49e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 50e80d4af0SHarald Freudenberger 51e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 52e80d4af0SHarald Freudenberger { 536b1f16baSHarald Freudenberger /* 5 arguments per dbf entry (including the format string ptr) */ 546b1f16baSHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); 55e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 56e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 57e80d4af0SHarald Freudenberger } 58e80d4af0SHarald Freudenberger 59e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 60e80d4af0SHarald Freudenberger { 61e80d4af0SHarald Freudenberger debug_unregister(debug_info); 62e80d4af0SHarald Freudenberger } 63e80d4af0SHarald Freudenberger 640534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */ 650534bde7SIngo Franzki struct protaeskeytoken { 660534bde7SIngo Franzki u8 type; /* 0x00 for PAES specific key tokens */ 670534bde7SIngo Franzki u8 res0[3]; 680534bde7SIngo Franzki u8 version; /* should be 0x01 for protected AES key token */ 690534bde7SIngo Franzki u8 res1[3]; 700534bde7SIngo Franzki u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 710534bde7SIngo Franzki u32 len; /* bytes actually stored in protkey[] */ 720534bde7SIngo Franzki u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 730534bde7SIngo Franzki } __packed; 740534bde7SIngo Franzki 75888edbc4SHarald Freudenberger /* inside view of a clear key token (type 0x00 version 0x02) */ 76888edbc4SHarald Freudenberger struct clearaeskeytoken { 77888edbc4SHarald Freudenberger u8 type; /* 0x00 for PAES specific key tokens */ 78888edbc4SHarald Freudenberger u8 res0[3]; 79888edbc4SHarald Freudenberger u8 version; /* 0x02 for clear AES key token */ 80888edbc4SHarald Freudenberger u8 res1[3]; 81888edbc4SHarald Freudenberger u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 82888edbc4SHarald Freudenberger u32 len; /* bytes actually stored in clearkey[] */ 83888edbc4SHarald Freudenberger u8 clearkey[0]; /* clear key value */ 84888edbc4SHarald Freudenberger } __packed; 85888edbc4SHarald Freudenberger 86e80d4af0SHarald Freudenberger /* 87e80d4af0SHarald Freudenberger * Create a protected key from a clear key value. 88e80d4af0SHarald Freudenberger */ 89183cb469SHarald Freudenberger static int pkey_clr2protkey(u32 keytype, 90e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 91e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 92e80d4af0SHarald Freudenberger { 93e80d4af0SHarald Freudenberger long fc; 94e80d4af0SHarald Freudenberger int keysize; 95e80d4af0SHarald Freudenberger u8 paramblock[64]; 96e80d4af0SHarald Freudenberger 97e80d4af0SHarald Freudenberger switch (keytype) { 98e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 99e80d4af0SHarald Freudenberger keysize = 16; 100e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 101e80d4af0SHarald Freudenberger break; 102e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 103e80d4af0SHarald Freudenberger keysize = 24; 104e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 105e80d4af0SHarald Freudenberger break; 106e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 107e80d4af0SHarald Freudenberger keysize = 32; 108e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 109e80d4af0SHarald Freudenberger break; 110e80d4af0SHarald Freudenberger default: 111ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 112ac2b96f3SHarald Freudenberger __func__, keytype); 113e80d4af0SHarald Freudenberger return -EINVAL; 114e80d4af0SHarald Freudenberger } 115e80d4af0SHarald Freudenberger 116f822ad2cSHarald Freudenberger /* 117f822ad2cSHarald Freudenberger * Check if the needed pckmo subfunction is available. 118f822ad2cSHarald Freudenberger * These subfunctions can be enabled/disabled by customers 119f822ad2cSHarald Freudenberger * in the LPAR profile or may even change on the fly. 120f822ad2cSHarald Freudenberger */ 121f822ad2cSHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, fc)) { 122f822ad2cSHarald Freudenberger DEBUG_ERR("%s pckmo functions not available\n", __func__); 12358443b67SDavid Hildenbrand return -ENODEV; 124f822ad2cSHarald Freudenberger } 125f822ad2cSHarald Freudenberger 126e80d4af0SHarald Freudenberger /* prepare param block */ 127e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 128e80d4af0SHarald Freudenberger memcpy(paramblock, clrkey->clrkey, keysize); 129e80d4af0SHarald Freudenberger 130e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 131e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 132e80d4af0SHarald Freudenberger 133e80d4af0SHarald Freudenberger /* copy created protected key */ 134e80d4af0SHarald Freudenberger protkey->type = keytype; 135e80d4af0SHarald Freudenberger protkey->len = keysize + 32; 136e80d4af0SHarald Freudenberger memcpy(protkey->protkey, paramblock, keysize + 32); 137e80d4af0SHarald Freudenberger 138e80d4af0SHarald Freudenberger return 0; 139e80d4af0SHarald Freudenberger } 140e80d4af0SHarald Freudenberger 141e80d4af0SHarald Freudenberger /* 142e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 143e80d4af0SHarald Freudenberger */ 144f2bbc96eSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) 145e80d4af0SHarald Freudenberger { 146e80d4af0SHarald Freudenberger int rc, verify; 147f2bbc96eSHarald Freudenberger u16 cardnr, domain; 148f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 149e80d4af0SHarald Freudenberger 150e80d4af0SHarald Freudenberger /* 151f2bbc96eSHarald Freudenberger * The cca_xxx2protkey call may fail when a card has been 152e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 153efc598e6SHarald Freudenberger * of the mkvp into the cache. Try 3 times: First witout verify 154efc598e6SHarald Freudenberger * then with verify and last round with verify and old master 155efc598e6SHarald Freudenberger * key verification pattern match not ignored. 156e80d4af0SHarald Freudenberger */ 157efc598e6SHarald Freudenberger for (verify = 0; verify < 3; verify++) { 158f2bbc96eSHarald Freudenberger rc = cca_findcard(key, &cardnr, &domain, verify); 159efc598e6SHarald Freudenberger if (rc < 0) 160e80d4af0SHarald Freudenberger continue; 161efc598e6SHarald Freudenberger if (rc > 0 && verify < 2) 162efc598e6SHarald Freudenberger continue; 163f2bbc96eSHarald Freudenberger switch (hdr->version) { 164f2bbc96eSHarald Freudenberger case TOKVER_CCA_AES: 165f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(cardnr, domain, 166f2bbc96eSHarald Freudenberger key, pkey->protkey, 167f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 168f2bbc96eSHarald Freudenberger break; 169f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 170f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(cardnr, domain, 171f2bbc96eSHarald Freudenberger key, pkey->protkey, 172f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 173f2bbc96eSHarald Freudenberger break; 174f2bbc96eSHarald Freudenberger default: 175f2bbc96eSHarald Freudenberger return -EINVAL; 176f2bbc96eSHarald Freudenberger } 177e80d4af0SHarald Freudenberger if (rc == 0) 178e80d4af0SHarald Freudenberger break; 179e80d4af0SHarald Freudenberger } 180e80d4af0SHarald Freudenberger 181e80d4af0SHarald Freudenberger if (rc) 182ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 183e80d4af0SHarald Freudenberger 184e80d4af0SHarald Freudenberger return rc; 185e80d4af0SHarald Freudenberger } 186e80d4af0SHarald Freudenberger 187e80d4af0SHarald Freudenberger /* 18855d0a513SHarald Freudenberger * Construct EP11 key with given clear key value. 18955d0a513SHarald Freudenberger */ 19055d0a513SHarald Freudenberger static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, 19155d0a513SHarald Freudenberger u8 *keybuf, size_t *keybuflen) 19255d0a513SHarald Freudenberger { 19355d0a513SHarald Freudenberger int i, rc; 19455d0a513SHarald Freudenberger u16 card, dom; 19555d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 19655d0a513SHarald Freudenberger 19755d0a513SHarald Freudenberger /* build a list of apqns suitable for ep11 keys with cpacf support */ 19855d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 19955d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 20055d0a513SHarald Freudenberger if (rc) 20155d0a513SHarald Freudenberger goto out; 20255d0a513SHarald Freudenberger 20355d0a513SHarald Freudenberger /* go through the list of apqns and try to bild an ep11 key */ 20455d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 20555d0a513SHarald Freudenberger card = apqns[i] >> 16; 20655d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 20755d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, clrkeylen * 8, 20855d0a513SHarald Freudenberger 0, clrkey, keybuf, keybuflen); 20955d0a513SHarald Freudenberger if (rc == 0) 21055d0a513SHarald Freudenberger break; 21155d0a513SHarald Freudenberger } 21255d0a513SHarald Freudenberger 21355d0a513SHarald Freudenberger out: 21455d0a513SHarald Freudenberger kfree(apqns); 21555d0a513SHarald Freudenberger if (rc) 21655d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 21755d0a513SHarald Freudenberger return rc; 21855d0a513SHarald Freudenberger } 21955d0a513SHarald Freudenberger 22055d0a513SHarald Freudenberger /* 22155d0a513SHarald Freudenberger * Find card and transform EP11 secure key into protected key. 22255d0a513SHarald Freudenberger */ 22355d0a513SHarald Freudenberger static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) 22455d0a513SHarald Freudenberger { 22555d0a513SHarald Freudenberger int i, rc; 22655d0a513SHarald Freudenberger u16 card, dom; 22755d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 22855d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) key; 22955d0a513SHarald Freudenberger 23055d0a513SHarald Freudenberger /* build a list of apqns suitable for this key */ 23155d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 23255d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 23355d0a513SHarald Freudenberger if (rc) 23455d0a513SHarald Freudenberger goto out; 23555d0a513SHarald Freudenberger 23655d0a513SHarald Freudenberger /* go through the list of apqns and try to derive an pkey */ 23755d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 23855d0a513SHarald Freudenberger card = apqns[i] >> 16; 23955d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 24055d0a513SHarald Freudenberger rc = ep11_key2protkey(card, dom, key, kb->head.len, 24155d0a513SHarald Freudenberger pkey->protkey, &pkey->len, &pkey->type); 24255d0a513SHarald Freudenberger if (rc == 0) 24355d0a513SHarald Freudenberger break; 24455d0a513SHarald Freudenberger } 24555d0a513SHarald Freudenberger 24655d0a513SHarald Freudenberger out: 24755d0a513SHarald Freudenberger kfree(apqns); 24855d0a513SHarald Freudenberger if (rc) 24955d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 25055d0a513SHarald Freudenberger return rc; 25155d0a513SHarald Freudenberger } 25255d0a513SHarald Freudenberger 25355d0a513SHarald Freudenberger /* 254e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 255e61a6134SHarald Freudenberger */ 256183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey, 257e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 258e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 259e61a6134SHarald Freudenberger { 260e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 261e61a6134SHarald Freudenberger u16 cardnr, domain; 262e61a6134SHarald Freudenberger int rc; 263e61a6134SHarald Freudenberger 264e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 265efc598e6SHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *) seckey, 0); 266e61a6134SHarald Freudenberger if (rc) 267e61a6134SHarald Freudenberger goto out; 268e61a6134SHarald Freudenberger if (pattributes) 269e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 270e61a6134SHarald Freudenberger if (pkeysize) 271e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 272e61a6134SHarald Freudenberger 273e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 274efc598e6SHarald Freudenberger rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); 275efc598e6SHarald Freudenberger if (rc < 0) 276e61a6134SHarald Freudenberger goto out; 277e61a6134SHarald Freudenberger 278efc598e6SHarald Freudenberger if (rc > 0) { 279efc598e6SHarald Freudenberger /* key mkvp matches to old master key mkvp */ 280ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 281e61a6134SHarald Freudenberger if (pattributes) 282e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 283efc598e6SHarald Freudenberger rc = 0; 284e61a6134SHarald Freudenberger } 285e61a6134SHarald Freudenberger 286e61a6134SHarald Freudenberger if (pcardnr) 287e61a6134SHarald Freudenberger *pcardnr = cardnr; 288e61a6134SHarald Freudenberger if (pdomain) 289e61a6134SHarald Freudenberger *pdomain = domain; 290e61a6134SHarald Freudenberger 291e61a6134SHarald Freudenberger out: 292ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 293e61a6134SHarald Freudenberger return rc; 294e61a6134SHarald Freudenberger } 295e61a6134SHarald Freudenberger 296e61a6134SHarald Freudenberger /* 297a45a5c7dSIngo Franzki * Generate a random protected key 298a45a5c7dSIngo Franzki */ 299183cb469SHarald Freudenberger static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) 300a45a5c7dSIngo Franzki { 301a45a5c7dSIngo Franzki struct pkey_clrkey clrkey; 302a45a5c7dSIngo Franzki int keysize; 303a45a5c7dSIngo Franzki int rc; 304a45a5c7dSIngo Franzki 305a45a5c7dSIngo Franzki switch (keytype) { 306a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_128: 307a45a5c7dSIngo Franzki keysize = 16; 308a45a5c7dSIngo Franzki break; 309a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_192: 310a45a5c7dSIngo Franzki keysize = 24; 311a45a5c7dSIngo Franzki break; 312a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_256: 313a45a5c7dSIngo Franzki keysize = 32; 314a45a5c7dSIngo Franzki break; 315a45a5c7dSIngo Franzki default: 316a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 317a45a5c7dSIngo Franzki keytype); 318a45a5c7dSIngo Franzki return -EINVAL; 319a45a5c7dSIngo Franzki } 320a45a5c7dSIngo Franzki 321a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 322a45a5c7dSIngo Franzki get_random_bytes(clrkey.clrkey, keysize); 323a45a5c7dSIngo Franzki 324a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 325a45a5c7dSIngo Franzki rc = pkey_clr2protkey(keytype, &clrkey, protkey); 326a45a5c7dSIngo Franzki if (rc) 327a45a5c7dSIngo Franzki return rc; 328a45a5c7dSIngo Franzki 329a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 330a45a5c7dSIngo Franzki get_random_bytes(protkey->protkey, keysize); 331a45a5c7dSIngo Franzki 332a45a5c7dSIngo Franzki return 0; 333a45a5c7dSIngo Franzki } 334a45a5c7dSIngo Franzki 335a45a5c7dSIngo Franzki /* 336cb26b9ffSIngo Franzki * Verify if a protected key is still valid 337cb26b9ffSIngo Franzki */ 338183cb469SHarald Freudenberger static int pkey_verifyprotkey(const struct pkey_protkey *protkey) 339cb26b9ffSIngo Franzki { 340cb26b9ffSIngo Franzki unsigned long fc; 341cb26b9ffSIngo Franzki struct { 342cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 343cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 344cb26b9ffSIngo Franzki } param; 345cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 346cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 347cb26b9ffSIngo Franzki unsigned int k; 348cb26b9ffSIngo Franzki 349cb26b9ffSIngo Franzki switch (protkey->type) { 350cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 351cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 352cb26b9ffSIngo Franzki break; 353cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 354cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 355cb26b9ffSIngo Franzki break; 356cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 357cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 358cb26b9ffSIngo Franzki break; 359cb26b9ffSIngo Franzki default: 360cb26b9ffSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 361cb26b9ffSIngo Franzki protkey->type); 362cb26b9ffSIngo Franzki return -EINVAL; 363cb26b9ffSIngo Franzki } 364cb26b9ffSIngo Franzki 365cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 366cb26b9ffSIngo Franzki 367cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 368cb26b9ffSIngo Franzki memcpy(param.key, protkey->protkey, sizeof(param.key)); 369cb26b9ffSIngo Franzki 370cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 371cb26b9ffSIngo Franzki sizeof(null_msg)); 372cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 373cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 374cb26b9ffSIngo Franzki return -EKEYREJECTED; 375cb26b9ffSIngo Franzki } 376cb26b9ffSIngo Franzki 377cb26b9ffSIngo Franzki return 0; 378cb26b9ffSIngo Franzki } 379cb26b9ffSIngo Franzki 380cb26b9ffSIngo Franzki /* 381fb1136d6SIngo Franzki * Transform a non-CCA key token into a protected key 382fb1136d6SIngo Franzki */ 383183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, 384fb1136d6SIngo Franzki struct pkey_protkey *protkey) 385fb1136d6SIngo Franzki { 386888edbc4SHarald Freudenberger int rc = -EINVAL; 38755d0a513SHarald Freudenberger u8 *tmpbuf = NULL; 388fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 389fb1136d6SIngo Franzki 390fb1136d6SIngo Franzki switch (hdr->version) { 391888edbc4SHarald Freudenberger case TOKVER_PROTECTED_KEY: { 392888edbc4SHarald Freudenberger struct protaeskeytoken *t; 393fb1136d6SIngo Franzki 394888edbc4SHarald Freudenberger if (keylen != sizeof(struct protaeskeytoken)) 395888edbc4SHarald Freudenberger goto out; 396fb1136d6SIngo Franzki t = (struct protaeskeytoken *)key; 397fb1136d6SIngo Franzki protkey->len = t->len; 398fb1136d6SIngo Franzki protkey->type = t->keytype; 399fb1136d6SIngo Franzki memcpy(protkey->protkey, t->protkey, 400fb1136d6SIngo Franzki sizeof(protkey->protkey)); 401888edbc4SHarald Freudenberger rc = pkey_verifyprotkey(protkey); 402888edbc4SHarald Freudenberger break; 403888edbc4SHarald Freudenberger } 404888edbc4SHarald Freudenberger case TOKVER_CLEAR_KEY: { 405888edbc4SHarald Freudenberger struct clearaeskeytoken *t; 406888edbc4SHarald Freudenberger struct pkey_clrkey ckey; 40755d0a513SHarald Freudenberger union u_tmpbuf { 40855d0a513SHarald Freudenberger u8 skey[SECKEYBLOBSIZE]; 40955d0a513SHarald Freudenberger u8 ep11key[MAXEP11AESKEYBLOBSIZE]; 41055d0a513SHarald Freudenberger }; 41155d0a513SHarald Freudenberger size_t tmpbuflen = sizeof(union u_tmpbuf); 412fb1136d6SIngo Franzki 413888edbc4SHarald Freudenberger if (keylen < sizeof(struct clearaeskeytoken)) 414888edbc4SHarald Freudenberger goto out; 415888edbc4SHarald Freudenberger t = (struct clearaeskeytoken *)key; 416888edbc4SHarald Freudenberger if (keylen != sizeof(*t) + t->len) 417888edbc4SHarald Freudenberger goto out; 418888edbc4SHarald Freudenberger if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) 419888edbc4SHarald Freudenberger || (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) 420888edbc4SHarald Freudenberger || (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) 421888edbc4SHarald Freudenberger memcpy(ckey.clrkey, t->clearkey, t->len); 422888edbc4SHarald Freudenberger else 423888edbc4SHarald Freudenberger goto out; 42455d0a513SHarald Freudenberger /* alloc temp key buffer space */ 42555d0a513SHarald Freudenberger tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 42655d0a513SHarald Freudenberger if (!tmpbuf) { 42755d0a513SHarald Freudenberger rc = -ENOMEM; 42855d0a513SHarald Freudenberger goto out; 42955d0a513SHarald Freudenberger } 430888edbc4SHarald Freudenberger /* try direct way with the PCKMO instruction */ 431888edbc4SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, &ckey, protkey); 432888edbc4SHarald Freudenberger if (rc == 0) 433888edbc4SHarald Freudenberger break; 434888edbc4SHarald Freudenberger /* PCKMO failed, so try the CCA secure key way */ 435888edbc4SHarald Freudenberger rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, 43655d0a513SHarald Freudenberger ckey.clrkey, tmpbuf); 437888edbc4SHarald Freudenberger if (rc == 0) 43855d0a513SHarald Freudenberger rc = pkey_skey2pkey(tmpbuf, protkey); 439888edbc4SHarald Freudenberger if (rc == 0) 440888edbc4SHarald Freudenberger break; 44155d0a513SHarald Freudenberger /* if the CCA way also failed, let's try via EP11 */ 44255d0a513SHarald Freudenberger rc = pkey_clr2ep11key(ckey.clrkey, t->len, 44355d0a513SHarald Freudenberger tmpbuf, &tmpbuflen); 44455d0a513SHarald Freudenberger if (rc == 0) 44555d0a513SHarald Freudenberger rc = pkey_ep11key2pkey(tmpbuf, protkey); 44655d0a513SHarald Freudenberger /* now we should really have an protected key */ 447888edbc4SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", 448888edbc4SHarald Freudenberger __func__); 449888edbc4SHarald Freudenberger break; 450888edbc4SHarald Freudenberger } 45155d0a513SHarald Freudenberger case TOKVER_EP11_AES: { 45255d0a513SHarald Freudenberger if (keylen < MINEP11AESKEYBLOBSIZE) 45355d0a513SHarald Freudenberger goto out; 45455d0a513SHarald Freudenberger /* check ep11 key for exportable as protected key */ 45555d0a513SHarald Freudenberger rc = ep11_check_aeskeyblob(debug_info, 3, key, 0, 1); 45655d0a513SHarald Freudenberger if (rc) 45755d0a513SHarald Freudenberger goto out; 45855d0a513SHarald Freudenberger rc = pkey_ep11key2pkey(key, protkey); 45955d0a513SHarald Freudenberger break; 46055d0a513SHarald Freudenberger } 461fb1136d6SIngo Franzki default: 462fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 463fb1136d6SIngo Franzki __func__, hdr->version); 464888edbc4SHarald Freudenberger rc = -EINVAL; 465fb1136d6SIngo Franzki } 466888edbc4SHarald Freudenberger 467888edbc4SHarald Freudenberger out: 46855d0a513SHarald Freudenberger kfree(tmpbuf); 469888edbc4SHarald Freudenberger return rc; 470fb1136d6SIngo Franzki } 471fb1136d6SIngo Franzki 472fb1136d6SIngo Franzki /* 473fb1136d6SIngo Franzki * Transform a CCA internal key token into a protected key 474fb1136d6SIngo Franzki */ 475183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, 476fb1136d6SIngo Franzki struct pkey_protkey *protkey) 477fb1136d6SIngo Franzki { 478fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 479fb1136d6SIngo Franzki 480fb1136d6SIngo Franzki switch (hdr->version) { 481fb1136d6SIngo Franzki case TOKVER_CCA_AES: 482fb1136d6SIngo Franzki if (keylen != sizeof(struct secaeskeytoken)) 483fb1136d6SIngo Franzki return -EINVAL; 484f2bbc96eSHarald Freudenberger break; 485f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 486f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 487f2bbc96eSHarald Freudenberger return -EINVAL; 488f2bbc96eSHarald Freudenberger break; 489fb1136d6SIngo Franzki default: 490fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 491fb1136d6SIngo Franzki __func__, hdr->version); 492fb1136d6SIngo Franzki return -EINVAL; 493fb1136d6SIngo Franzki } 494f2bbc96eSHarald Freudenberger 495f2bbc96eSHarald Freudenberger return pkey_skey2pkey(key, protkey); 496fb1136d6SIngo Franzki } 497fb1136d6SIngo Franzki 498fb1136d6SIngo Franzki /* 499fb1136d6SIngo Franzki * Transform a key blob (of any type) into a protected key 500fb1136d6SIngo Franzki */ 501183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen, 502fb1136d6SIngo Franzki struct pkey_protkey *protkey) 503fb1136d6SIngo Franzki { 504f2bbc96eSHarald Freudenberger int rc; 505fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 506fb1136d6SIngo Franzki 507f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) { 508f2bbc96eSHarald Freudenberger DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); 509f2bbc96eSHarald Freudenberger return -EINVAL; 510f2bbc96eSHarald Freudenberger } 511f2bbc96eSHarald Freudenberger 512f2bbc96eSHarald Freudenberger switch (hdr->type) { 513f2bbc96eSHarald Freudenberger case TOKTYPE_NON_CCA: 514f2bbc96eSHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, protkey); 515f2bbc96eSHarald Freudenberger break; 516f2bbc96eSHarald Freudenberger case TOKTYPE_CCA_INTERNAL: 517f2bbc96eSHarald Freudenberger rc = pkey_ccainttok2pkey(key, keylen, protkey); 518f2bbc96eSHarald Freudenberger break; 519f2bbc96eSHarald Freudenberger default: 520f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 521f2bbc96eSHarald Freudenberger __func__, hdr->type); 522f2bbc96eSHarald Freudenberger return -EINVAL; 523f2bbc96eSHarald Freudenberger } 524f2bbc96eSHarald Freudenberger 525f2bbc96eSHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 526f2bbc96eSHarald Freudenberger return rc; 527f2bbc96eSHarald Freudenberger 528f2bbc96eSHarald Freudenberger } 529f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey); 530f2bbc96eSHarald Freudenberger 531f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 532f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 533f2bbc96eSHarald Freudenberger u32 kflags, u8 *keybuf, size_t *keybufsize) 534f2bbc96eSHarald Freudenberger { 535f2bbc96eSHarald Freudenberger int i, card, dom, rc; 536f2bbc96eSHarald Freudenberger 537f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 538f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 539f2bbc96eSHarald Freudenberger return -EINVAL; 540f2bbc96eSHarald Freudenberger 541f2bbc96eSHarald Freudenberger /* check key type and size */ 542f2bbc96eSHarald Freudenberger switch (ktype) { 543f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 544f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 545f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 546f2bbc96eSHarald Freudenberger return -EINVAL; 547f2bbc96eSHarald Freudenberger break; 54855d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 54955d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 55055d0a513SHarald Freudenberger return -EINVAL; 55155d0a513SHarald Freudenberger break; 552f2bbc96eSHarald Freudenberger default: 553f2bbc96eSHarald Freudenberger return -EINVAL; 554f2bbc96eSHarald Freudenberger } 555f2bbc96eSHarald Freudenberger switch (ksize) { 556f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 557f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 558f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 559f2bbc96eSHarald Freudenberger break; 560f2bbc96eSHarald Freudenberger default: 561f2bbc96eSHarald Freudenberger return -EINVAL; 562f2bbc96eSHarald Freudenberger } 563f2bbc96eSHarald Freudenberger 564f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 565f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 566f2bbc96eSHarald Freudenberger card = apqns[i].card; 567f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 56855d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 56955d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, ksize, kflags, 57055d0a513SHarald Freudenberger keybuf, keybufsize); 57155d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 572f2bbc96eSHarald Freudenberger rc = cca_genseckey(card, dom, ksize, keybuf); 573f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 574f2bbc96eSHarald Freudenberger } else /* TOKVER_CCA_VLSC */ 575f2bbc96eSHarald Freudenberger rc = cca_gencipherkey(card, dom, ksize, kflags, 576f2bbc96eSHarald Freudenberger keybuf, keybufsize); 577f2bbc96eSHarald Freudenberger if (rc == 0) 578f2bbc96eSHarald Freudenberger break; 579f2bbc96eSHarald Freudenberger } 580f2bbc96eSHarald Freudenberger 581f2bbc96eSHarald Freudenberger return rc; 582f2bbc96eSHarald Freudenberger } 583f2bbc96eSHarald Freudenberger 584f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 585f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 586f2bbc96eSHarald Freudenberger u32 kflags, const u8 *clrkey, 587f2bbc96eSHarald Freudenberger u8 *keybuf, size_t *keybufsize) 588f2bbc96eSHarald Freudenberger { 589f2bbc96eSHarald Freudenberger int i, card, dom, rc; 590f2bbc96eSHarald Freudenberger 591f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 592f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 593f2bbc96eSHarald Freudenberger return -EINVAL; 594f2bbc96eSHarald Freudenberger 595f2bbc96eSHarald Freudenberger /* check key type and size */ 596f2bbc96eSHarald Freudenberger switch (ktype) { 597f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 598f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 599f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 600f2bbc96eSHarald Freudenberger return -EINVAL; 601f2bbc96eSHarald Freudenberger break; 60255d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 60355d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 60455d0a513SHarald Freudenberger return -EINVAL; 60555d0a513SHarald Freudenberger break; 606f2bbc96eSHarald Freudenberger default: 607f2bbc96eSHarald Freudenberger return -EINVAL; 608f2bbc96eSHarald Freudenberger } 609f2bbc96eSHarald Freudenberger switch (ksize) { 610f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 611f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 612f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 613f2bbc96eSHarald Freudenberger break; 614f2bbc96eSHarald Freudenberger default: 615f2bbc96eSHarald Freudenberger return -EINVAL; 616f2bbc96eSHarald Freudenberger } 617f2bbc96eSHarald Freudenberger 618f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 619f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 620f2bbc96eSHarald Freudenberger card = apqns[i].card; 621f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 62255d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 62355d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, ksize, kflags, 62455d0a513SHarald Freudenberger clrkey, keybuf, keybufsize); 62555d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 626f2bbc96eSHarald Freudenberger rc = cca_clr2seckey(card, dom, ksize, 627f2bbc96eSHarald Freudenberger clrkey, keybuf); 628f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 629f2bbc96eSHarald Freudenberger } else /* TOKVER_CCA_VLSC */ 630f2bbc96eSHarald Freudenberger rc = cca_clr2cipherkey(card, dom, ksize, kflags, 631f2bbc96eSHarald Freudenberger clrkey, keybuf, keybufsize); 632f2bbc96eSHarald Freudenberger if (rc == 0) 633f2bbc96eSHarald Freudenberger break; 634f2bbc96eSHarald Freudenberger } 635f2bbc96eSHarald Freudenberger 636f2bbc96eSHarald Freudenberger return rc; 637f2bbc96eSHarald Freudenberger } 638f2bbc96eSHarald Freudenberger 639f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen, 640f2bbc96eSHarald Freudenberger u16 *cardnr, u16 *domain, 641f2bbc96eSHarald Freudenberger enum pkey_key_type *ktype, 642f2bbc96eSHarald Freudenberger enum pkey_key_size *ksize, u32 *flags) 643f2bbc96eSHarald Freudenberger { 644f2bbc96eSHarald Freudenberger int rc; 645f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 646f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 647f2bbc96eSHarald Freudenberger 64855d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 649f2bbc96eSHarald Freudenberger return -EINVAL; 650f2bbc96eSHarald Freudenberger 65155d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL 65255d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_AES) { 653f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 654f2bbc96eSHarald Freudenberger 655f2bbc96eSHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 656f2bbc96eSHarald Freudenberger if (rc) 657f2bbc96eSHarald Freudenberger goto out; 658f2bbc96eSHarald Freudenberger if (ktype) 659f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_DATA; 660f2bbc96eSHarald Freudenberger if (ksize) 661f2bbc96eSHarald Freudenberger *ksize = (enum pkey_key_size) t->bitsize; 662f2bbc96eSHarald Freudenberger 663f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 664f2bbc96eSHarald Freudenberger ZCRYPT_CEX3C, t->mkvp, 0, 1); 665f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 666f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 667f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 668f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 669f2bbc96eSHarald Freudenberger *cardnr, *domain, 670f2bbc96eSHarald Freudenberger ZCRYPT_CEX3C, 0, t->mkvp, 1); 671f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 672f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 673f2bbc96eSHarald Freudenberger } 674f2bbc96eSHarald Freudenberger if (rc) 675f2bbc96eSHarald Freudenberger goto out; 676f2bbc96eSHarald Freudenberger 677f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 678f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 679f2bbc96eSHarald Freudenberger 68055d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL 68155d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_VLSC) { 682f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 683f2bbc96eSHarald Freudenberger 684f2bbc96eSHarald Freudenberger rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 685f2bbc96eSHarald Freudenberger if (rc) 686f2bbc96eSHarald Freudenberger goto out; 687f2bbc96eSHarald Freudenberger if (ktype) 688f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_CIPHER; 689f2bbc96eSHarald Freudenberger if (ksize) { 690f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_UNKNOWN; 691f2bbc96eSHarald Freudenberger if (!t->plfver && t->wpllen == 512) 692f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_128; 693f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 694f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_192; 695f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 696f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_256; 697f2bbc96eSHarald Freudenberger } 698f2bbc96eSHarald Freudenberger 699f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 700f2bbc96eSHarald Freudenberger ZCRYPT_CEX6, t->mkvp0, 0, 1); 701f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 702f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 703f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 704f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 705f2bbc96eSHarald Freudenberger *cardnr, *domain, 706f2bbc96eSHarald Freudenberger ZCRYPT_CEX6, 0, t->mkvp0, 1); 707f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 708f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 709f2bbc96eSHarald Freudenberger } 710f2bbc96eSHarald Freudenberger if (rc) 711f2bbc96eSHarald Freudenberger goto out; 712f2bbc96eSHarald Freudenberger 713f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 714f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 715f2bbc96eSHarald Freudenberger 71655d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA 71755d0a513SHarald Freudenberger && hdr->version == TOKVER_EP11_AES) { 71855d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 71955d0a513SHarald Freudenberger 72055d0a513SHarald Freudenberger rc = ep11_check_aeskeyblob(debug_info, 3, key, 0, 1); 72155d0a513SHarald Freudenberger if (rc) 72255d0a513SHarald Freudenberger goto out; 72355d0a513SHarald Freudenberger if (ktype) 72455d0a513SHarald Freudenberger *ktype = PKEY_TYPE_EP11; 72555d0a513SHarald Freudenberger if (ksize) 72655d0a513SHarald Freudenberger *ksize = kb->head.keybitlen; 72755d0a513SHarald Freudenberger 72855d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 72955d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 73055d0a513SHarald Freudenberger if (rc) 73155d0a513SHarald Freudenberger goto out; 73255d0a513SHarald Freudenberger 73355d0a513SHarald Freudenberger if (flags) 73455d0a513SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 73555d0a513SHarald Freudenberger 73655d0a513SHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 73755d0a513SHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 73855d0a513SHarald Freudenberger 739f2bbc96eSHarald Freudenberger } else 740f2bbc96eSHarald Freudenberger rc = -EINVAL; 741f2bbc96eSHarald Freudenberger 742f2bbc96eSHarald Freudenberger out: 743f2bbc96eSHarald Freudenberger kfree(_apqns); 744f2bbc96eSHarald Freudenberger return rc; 745f2bbc96eSHarald Freudenberger } 746f2bbc96eSHarald Freudenberger 747f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 748f2bbc96eSHarald Freudenberger const u8 *key, size_t keylen, 749f2bbc96eSHarald Freudenberger struct pkey_protkey *pkey) 750f2bbc96eSHarald Freudenberger { 751f2bbc96eSHarald Freudenberger int i, card, dom, rc; 752f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 753f2bbc96eSHarald Freudenberger 754f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 755f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 756f2bbc96eSHarald Freudenberger return -EINVAL; 757f2bbc96eSHarald Freudenberger 758fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 759fb1136d6SIngo Franzki return -EINVAL; 760fb1136d6SIngo Franzki 76155d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL) { 76255d0a513SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 763f2bbc96eSHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 764f2bbc96eSHarald Freudenberger return -EINVAL; 765f2bbc96eSHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 766f2bbc96eSHarald Freudenberger return -EINVAL; 76755d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 768f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 769f2bbc96eSHarald Freudenberger return -EINVAL; 770f2bbc96eSHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 771f2bbc96eSHarald Freudenberger return -EINVAL; 77255d0a513SHarald Freudenberger } else { 773f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 774f2bbc96eSHarald Freudenberger __func__, hdr->version); 775fb1136d6SIngo Franzki return -EINVAL; 776fb1136d6SIngo Franzki } 77755d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 77855d0a513SHarald Freudenberger if (hdr->version == TOKVER_EP11_AES) { 77955d0a513SHarald Freudenberger if (keylen < sizeof(struct ep11keyblob)) 78055d0a513SHarald Freudenberger return -EINVAL; 78155d0a513SHarald Freudenberger if (ep11_check_aeskeyblob(debug_info, 3, key, 0, 1)) 78255d0a513SHarald Freudenberger return -EINVAL; 78355d0a513SHarald Freudenberger } else { 78455d0a513SHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, pkey); 78555d0a513SHarald Freudenberger } 78655d0a513SHarald Freudenberger } else { 787f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 788f2bbc96eSHarald Freudenberger __func__, hdr->type); 789f2bbc96eSHarald Freudenberger return -EINVAL; 790fb1136d6SIngo Franzki } 791f2bbc96eSHarald Freudenberger 792f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 793f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 794f2bbc96eSHarald Freudenberger card = apqns[i].card; 795f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 79655d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL 79755d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_AES) 798f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(card, dom, key, pkey->protkey, 799f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 80055d0a513SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL 80155d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_VLSC) 802f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, pkey->protkey, 803f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 80455d0a513SHarald Freudenberger else { /* EP11 AES secure key blob */ 80555d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) key; 80655d0a513SHarald Freudenberger 80755d0a513SHarald Freudenberger rc = ep11_key2protkey(card, dom, key, kb->head.len, 80855d0a513SHarald Freudenberger pkey->protkey, &pkey->len, 80955d0a513SHarald Freudenberger &pkey->type); 81055d0a513SHarald Freudenberger } 811f2bbc96eSHarald Freudenberger if (rc == 0) 812f2bbc96eSHarald Freudenberger break; 813f2bbc96eSHarald Freudenberger } 814f2bbc96eSHarald Freudenberger 815f2bbc96eSHarald Freudenberger return rc; 816f2bbc96eSHarald Freudenberger } 817f2bbc96eSHarald Freudenberger 818f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 819f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 820f2bbc96eSHarald Freudenberger { 821f2bbc96eSHarald Freudenberger int rc = EINVAL; 822f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 823f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 824f2bbc96eSHarald Freudenberger 82555d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || flags == 0) 826f2bbc96eSHarald Freudenberger return -EINVAL; 827f2bbc96eSHarald Freudenberger 82855d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES) { 82955d0a513SHarald Freudenberger int minhwtype = 0, api = 0; 83055d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) key; 83155d0a513SHarald Freudenberger 83255d0a513SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 83355d0a513SHarald Freudenberger return -EINVAL; 83455d0a513SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 83555d0a513SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 83655d0a513SHarald Freudenberger api = EP11_API_V; 83755d0a513SHarald Freudenberger } 83855d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 83955d0a513SHarald Freudenberger minhwtype, api, kb->wkvp); 84055d0a513SHarald Freudenberger if (rc) 84155d0a513SHarald Freudenberger goto out; 84255d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 843f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 844f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 845f2bbc96eSHarald Freudenberger 846f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 847f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 848f2bbc96eSHarald Freudenberger 849f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 850f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp; 851f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 852f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp; 85355d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 854f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 855f2bbc96eSHarald Freudenberger 856f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 857f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 858f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp0; 859f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 860f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp0; 86155d0a513SHarald Freudenberger } else { 86255d0a513SHarald Freudenberger /* unknown cca internal token type */ 86355d0a513SHarald Freudenberger return -EINVAL; 864f2bbc96eSHarald Freudenberger } 865f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 866f2bbc96eSHarald Freudenberger minhwtype, cur_mkvp, old_mkvp, 1); 867f2bbc96eSHarald Freudenberger if (rc) 868f2bbc96eSHarald Freudenberger goto out; 86955d0a513SHarald Freudenberger } else 87055d0a513SHarald Freudenberger return -EINVAL; 87155d0a513SHarald Freudenberger 872f2bbc96eSHarald Freudenberger if (apqns) { 873f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 874f2bbc96eSHarald Freudenberger rc = -ENOSPC; 875f2bbc96eSHarald Freudenberger else 876f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 877f2bbc96eSHarald Freudenberger } 878f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 879f2bbc96eSHarald Freudenberger 880f2bbc96eSHarald Freudenberger out: 881f2bbc96eSHarald Freudenberger kfree(_apqns); 882f2bbc96eSHarald Freudenberger return rc; 883f2bbc96eSHarald Freudenberger } 884f2bbc96eSHarald Freudenberger 885f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype, 886f2bbc96eSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 887f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 888f2bbc96eSHarald Freudenberger { 889f2bbc96eSHarald Freudenberger int rc = -EINVAL; 890f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 891f2bbc96eSHarald Freudenberger 892f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 893f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 894f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 895f2bbc96eSHarald Freudenberger 896f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 897f2bbc96eSHarald Freudenberger cur_mkvp = *((u64 *) cur_mkvp); 898f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 899f2bbc96eSHarald Freudenberger old_mkvp = *((u64 *) alt_mkvp); 900f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 901f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 902f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 903f2bbc96eSHarald Freudenberger minhwtype, cur_mkvp, old_mkvp, 1); 904f2bbc96eSHarald Freudenberger if (rc) 905f2bbc96eSHarald Freudenberger goto out; 90655d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_EP11) { 90755d0a513SHarald Freudenberger u8 *wkvp = NULL; 90855d0a513SHarald Freudenberger 90955d0a513SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 91055d0a513SHarald Freudenberger wkvp = cur_mkvp; 91155d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 91255d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, wkvp); 91355d0a513SHarald Freudenberger if (rc) 91455d0a513SHarald Freudenberger goto out; 91555d0a513SHarald Freudenberger 91655d0a513SHarald Freudenberger } else 91755d0a513SHarald Freudenberger return -EINVAL; 91855d0a513SHarald Freudenberger 919f2bbc96eSHarald Freudenberger if (apqns) { 920f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 921f2bbc96eSHarald Freudenberger rc = -ENOSPC; 922f2bbc96eSHarald Freudenberger else 923f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 924f2bbc96eSHarald Freudenberger } 925f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 926f2bbc96eSHarald Freudenberger 927f2bbc96eSHarald Freudenberger out: 928f2bbc96eSHarald Freudenberger kfree(_apqns); 929f2bbc96eSHarald Freudenberger return rc; 930f2bbc96eSHarald Freudenberger } 931fb1136d6SIngo Franzki 932fb1136d6SIngo Franzki /* 933e80d4af0SHarald Freudenberger * File io functions 934e80d4af0SHarald Freudenberger */ 935e80d4af0SHarald Freudenberger 936f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen) 937f2bbc96eSHarald Freudenberger { 938f2bbc96eSHarald Freudenberger if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) 939f2bbc96eSHarald Freudenberger return ERR_PTR(-EINVAL); 940f2bbc96eSHarald Freudenberger 9418b57e7c8SMarkus Elfring return memdup_user(ukey, keylen); 942f2bbc96eSHarald Freudenberger } 943f2bbc96eSHarald Freudenberger 944f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 945f2bbc96eSHarald Freudenberger { 9468b57e7c8SMarkus Elfring if (!uapqns || nr_apqns == 0) 9478b57e7c8SMarkus Elfring return NULL; 948f2bbc96eSHarald Freudenberger 9498b57e7c8SMarkus Elfring return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); 950f2bbc96eSHarald Freudenberger } 951f2bbc96eSHarald Freudenberger 952e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 953e80d4af0SHarald Freudenberger unsigned long arg) 954e80d4af0SHarald Freudenberger { 955e80d4af0SHarald Freudenberger int rc; 956e80d4af0SHarald Freudenberger 957e80d4af0SHarald Freudenberger switch (cmd) { 958e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 959e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *) arg; 960e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 961e80d4af0SHarald Freudenberger 962e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 963e80d4af0SHarald Freudenberger return -EFAULT; 964efc598e6SHarald Freudenberger rc = cca_genseckey(kgs.cardnr, kgs.domain, 965efc598e6SHarald Freudenberger kgs.keytype, kgs.seckey.seckey); 966efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 967e80d4af0SHarald Freudenberger if (rc) 968e80d4af0SHarald Freudenberger break; 969e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 970e80d4af0SHarald Freudenberger return -EFAULT; 971e80d4af0SHarald Freudenberger break; 972e80d4af0SHarald Freudenberger } 973e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 974e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *) arg; 975e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 976e80d4af0SHarald Freudenberger 977e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 978e80d4af0SHarald Freudenberger return -EFAULT; 979efc598e6SHarald Freudenberger rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 980efc598e6SHarald Freudenberger kcs.clrkey.clrkey, kcs.seckey.seckey); 981efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 982e80d4af0SHarald Freudenberger if (rc) 983e80d4af0SHarald Freudenberger break; 984e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 985e80d4af0SHarald Freudenberger return -EFAULT; 986e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 987e80d4af0SHarald Freudenberger break; 988e80d4af0SHarald Freudenberger } 989e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 990e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *) arg; 991e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 992e80d4af0SHarald Freudenberger 993e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 994e80d4af0SHarald Freudenberger return -EFAULT; 995efc598e6SHarald Freudenberger rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 996efc598e6SHarald Freudenberger ksp.seckey.seckey, ksp.protkey.protkey, 997*aab73d27SHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 998efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 999e80d4af0SHarald Freudenberger if (rc) 1000e80d4af0SHarald Freudenberger break; 1001e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1002e80d4af0SHarald Freudenberger return -EFAULT; 1003e80d4af0SHarald Freudenberger break; 1004e80d4af0SHarald Freudenberger } 1005e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1006e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *) arg; 1007e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1008e80d4af0SHarald Freudenberger 1009e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1010e80d4af0SHarald Freudenberger return -EFAULT; 1011e80d4af0SHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, 1012e80d4af0SHarald Freudenberger &kcp.clrkey, &kcp.protkey); 1013ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1014e80d4af0SHarald Freudenberger if (rc) 1015e80d4af0SHarald Freudenberger break; 1016e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1017e80d4af0SHarald Freudenberger return -EFAULT; 1018e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1019e80d4af0SHarald Freudenberger break; 1020e80d4af0SHarald Freudenberger } 1021e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1022e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *) arg; 1023e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1024e80d4af0SHarald Freudenberger 1025e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1026e80d4af0SHarald Freudenberger return -EFAULT; 1027efc598e6SHarald Freudenberger rc = cca_findcard(kfc.seckey.seckey, 1028e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1029efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 1030efc598e6SHarald Freudenberger if (rc < 0) 1031e80d4af0SHarald Freudenberger break; 1032e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1033e80d4af0SHarald Freudenberger return -EFAULT; 1034e80d4af0SHarald Freudenberger break; 1035e80d4af0SHarald Freudenberger } 1036e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1037e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *) arg; 1038e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1039e80d4af0SHarald Freudenberger 1040e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1041e80d4af0SHarald Freudenberger return -EFAULT; 1042f2bbc96eSHarald Freudenberger rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey); 1043ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1044e80d4af0SHarald Freudenberger if (rc) 1045e80d4af0SHarald Freudenberger break; 1046e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1047e80d4af0SHarald Freudenberger return -EFAULT; 1048e80d4af0SHarald Freudenberger break; 1049e80d4af0SHarald Freudenberger } 1050e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1051e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *) arg; 1052e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1053e61a6134SHarald Freudenberger 1054e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1055e61a6134SHarald Freudenberger return -EFAULT; 1056e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1057e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1058ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1059e61a6134SHarald Freudenberger if (rc) 1060e61a6134SHarald Freudenberger break; 1061e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1062e61a6134SHarald Freudenberger return -EFAULT; 1063e61a6134SHarald Freudenberger break; 1064e61a6134SHarald Freudenberger } 1065a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1066a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *) arg; 1067a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1068a45a5c7dSIngo Franzki 1069a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1070a45a5c7dSIngo Franzki return -EFAULT; 1071a45a5c7dSIngo Franzki rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); 1072a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1073a45a5c7dSIngo Franzki if (rc) 1074a45a5c7dSIngo Franzki break; 1075a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1076a45a5c7dSIngo Franzki return -EFAULT; 1077a45a5c7dSIngo Franzki break; 1078a45a5c7dSIngo Franzki } 1079cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 1080cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *) arg; 1081cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 1082cb26b9ffSIngo Franzki 1083cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 1084cb26b9ffSIngo Franzki return -EFAULT; 1085cb26b9ffSIngo Franzki rc = pkey_verifyprotkey(&kvp.protkey); 1086cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 1087cb26b9ffSIngo Franzki break; 1088cb26b9ffSIngo Franzki } 1089fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 1090fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *) arg; 1091fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 1092183cb469SHarald Freudenberger u8 *kkey; 1093fb1136d6SIngo Franzki 1094fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 1095fb1136d6SIngo Franzki return -EFAULT; 1096f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1097f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1098f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1099fb1136d6SIngo Franzki rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); 1100fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 1101fb1136d6SIngo Franzki kfree(kkey); 1102fb1136d6SIngo Franzki if (rc) 1103fb1136d6SIngo Franzki break; 1104fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 1105fb1136d6SIngo Franzki return -EFAULT; 1106fb1136d6SIngo Franzki break; 1107fb1136d6SIngo Franzki } 1108f2bbc96eSHarald Freudenberger case PKEY_GENSECK2: { 1109f2bbc96eSHarald Freudenberger struct pkey_genseck2 __user *ugs = (void __user *) arg; 1110f2bbc96eSHarald Freudenberger struct pkey_genseck2 kgs; 1111f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1112f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1113f2bbc96eSHarald Freudenberger u8 *kkey; 1114f2bbc96eSHarald Freudenberger 1115f2bbc96eSHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1116f2bbc96eSHarald Freudenberger return -EFAULT; 1117f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 1118f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1119f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1120f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1121f2bbc96eSHarald Freudenberger if (!kkey) { 1122f2bbc96eSHarald Freudenberger kfree(apqns); 1123f2bbc96eSHarald Freudenberger return -ENOMEM; 1124f2bbc96eSHarald Freudenberger } 1125f2bbc96eSHarald Freudenberger rc = pkey_genseckey2(apqns, kgs.apqn_entries, 1126f2bbc96eSHarald Freudenberger kgs.type, kgs.size, kgs.keygenflags, 1127f2bbc96eSHarald Freudenberger kkey, &klen); 1128f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 1129f2bbc96eSHarald Freudenberger kfree(apqns); 1130f2bbc96eSHarald Freudenberger if (rc) { 1131f2bbc96eSHarald Freudenberger kfree(kkey); 1132f2bbc96eSHarald Freudenberger break; 1133f2bbc96eSHarald Freudenberger } 1134f2bbc96eSHarald Freudenberger if (kgs.key) { 1135f2bbc96eSHarald Freudenberger if (kgs.keylen < klen) { 1136f2bbc96eSHarald Freudenberger kfree(kkey); 1137f2bbc96eSHarald Freudenberger return -EINVAL; 1138f2bbc96eSHarald Freudenberger } 1139f2bbc96eSHarald Freudenberger if (copy_to_user(kgs.key, kkey, klen)) { 1140f2bbc96eSHarald Freudenberger kfree(kkey); 1141f2bbc96eSHarald Freudenberger return -EFAULT; 1142f2bbc96eSHarald Freudenberger } 1143f2bbc96eSHarald Freudenberger } 1144f2bbc96eSHarald Freudenberger kgs.keylen = klen; 1145f2bbc96eSHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1146f2bbc96eSHarald Freudenberger rc = -EFAULT; 1147f2bbc96eSHarald Freudenberger kfree(kkey); 1148f2bbc96eSHarald Freudenberger break; 1149f2bbc96eSHarald Freudenberger } 1150f2bbc96eSHarald Freudenberger case PKEY_CLR2SECK2: { 1151f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 __user *ucs = (void __user *) arg; 1152f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 kcs; 1153f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1154f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1155f2bbc96eSHarald Freudenberger u8 *kkey; 1156f2bbc96eSHarald Freudenberger 1157f2bbc96eSHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1158f2bbc96eSHarald Freudenberger return -EFAULT; 1159f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 1160f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1161f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1162f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1163f2bbc96eSHarald Freudenberger if (!kkey) { 1164f2bbc96eSHarald Freudenberger kfree(apqns); 1165f2bbc96eSHarald Freudenberger return -ENOMEM; 1166f2bbc96eSHarald Freudenberger } 1167f2bbc96eSHarald Freudenberger rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 1168f2bbc96eSHarald Freudenberger kcs.type, kcs.size, kcs.keygenflags, 1169f2bbc96eSHarald Freudenberger kcs.clrkey.clrkey, kkey, &klen); 1170f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 1171f2bbc96eSHarald Freudenberger kfree(apqns); 1172f2bbc96eSHarald Freudenberger if (rc) { 1173f2bbc96eSHarald Freudenberger kfree(kkey); 1174f2bbc96eSHarald Freudenberger break; 1175f2bbc96eSHarald Freudenberger } 1176f2bbc96eSHarald Freudenberger if (kcs.key) { 1177f2bbc96eSHarald Freudenberger if (kcs.keylen < klen) { 1178f2bbc96eSHarald Freudenberger kfree(kkey); 1179f2bbc96eSHarald Freudenberger return -EINVAL; 1180f2bbc96eSHarald Freudenberger } 1181f2bbc96eSHarald Freudenberger if (copy_to_user(kcs.key, kkey, klen)) { 1182f2bbc96eSHarald Freudenberger kfree(kkey); 1183f2bbc96eSHarald Freudenberger return -EFAULT; 1184f2bbc96eSHarald Freudenberger } 1185f2bbc96eSHarald Freudenberger } 1186f2bbc96eSHarald Freudenberger kcs.keylen = klen; 1187f2bbc96eSHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1188f2bbc96eSHarald Freudenberger rc = -EFAULT; 1189f2bbc96eSHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1190f2bbc96eSHarald Freudenberger kfree(kkey); 1191f2bbc96eSHarald Freudenberger break; 1192f2bbc96eSHarald Freudenberger } 1193f2bbc96eSHarald Freudenberger case PKEY_VERIFYKEY2: { 1194f2bbc96eSHarald Freudenberger struct pkey_verifykey2 __user *uvk = (void __user *) arg; 1195f2bbc96eSHarald Freudenberger struct pkey_verifykey2 kvk; 1196f2bbc96eSHarald Freudenberger u8 *kkey; 1197f2bbc96eSHarald Freudenberger 1198f2bbc96eSHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1199f2bbc96eSHarald Freudenberger return -EFAULT; 1200f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kvk.key, kvk.keylen); 1201f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1202f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1203f2bbc96eSHarald Freudenberger rc = pkey_verifykey2(kkey, kvk.keylen, 1204f2bbc96eSHarald Freudenberger &kvk.cardnr, &kvk.domain, 1205f2bbc96eSHarald Freudenberger &kvk.type, &kvk.size, &kvk.flags); 1206f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 1207f2bbc96eSHarald Freudenberger kfree(kkey); 1208f2bbc96eSHarald Freudenberger if (rc) 1209f2bbc96eSHarald Freudenberger break; 1210f2bbc96eSHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1211f2bbc96eSHarald Freudenberger return -EFAULT; 1212f2bbc96eSHarald Freudenberger break; 1213f2bbc96eSHarald Freudenberger } 1214f2bbc96eSHarald Freudenberger case PKEY_KBLOB2PROTK2: { 1215f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 __user *utp = (void __user *) arg; 1216f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 ktp; 1217f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1218f2bbc96eSHarald Freudenberger u8 *kkey; 1219f2bbc96eSHarald Freudenberger 1220f2bbc96eSHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1221f2bbc96eSHarald Freudenberger return -EFAULT; 1222f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1223f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1224f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1225f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1226f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1227f2bbc96eSHarald Freudenberger kfree(apqns); 1228f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1229f2bbc96eSHarald Freudenberger } 1230f2bbc96eSHarald Freudenberger rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 1231f2bbc96eSHarald Freudenberger kkey, ktp.keylen, &ktp.protkey); 1232f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 1233f2bbc96eSHarald Freudenberger kfree(apqns); 1234f2bbc96eSHarald Freudenberger kfree(kkey); 1235f2bbc96eSHarald Freudenberger if (rc) 1236f2bbc96eSHarald Freudenberger break; 1237f2bbc96eSHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1238f2bbc96eSHarald Freudenberger return -EFAULT; 1239f2bbc96eSHarald Freudenberger break; 1240f2bbc96eSHarald Freudenberger } 1241f2bbc96eSHarald Freudenberger case PKEY_APQNS4K: { 1242f2bbc96eSHarald Freudenberger struct pkey_apqns4key __user *uak = (void __user *) arg; 1243f2bbc96eSHarald Freudenberger struct pkey_apqns4key kak; 1244f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1245f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1246f2bbc96eSHarald Freudenberger u8 *kkey; 1247f2bbc96eSHarald Freudenberger 1248f2bbc96eSHarald Freudenberger if (copy_from_user(&kak, uak, sizeof(kak))) 1249f2bbc96eSHarald Freudenberger return -EFAULT; 1250f2bbc96eSHarald Freudenberger nr_apqns = kak.apqn_entries; 1251f2bbc96eSHarald Freudenberger if (nr_apqns) { 1252f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1253f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1254f2bbc96eSHarald Freudenberger GFP_KERNEL); 1255f2bbc96eSHarald Freudenberger if (!apqns) 1256f2bbc96eSHarald Freudenberger return -ENOMEM; 1257f2bbc96eSHarald Freudenberger } 1258f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kak.key, kak.keylen); 1259f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1260f2bbc96eSHarald Freudenberger kfree(apqns); 1261f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1262f2bbc96eSHarald Freudenberger } 1263f2bbc96eSHarald Freudenberger rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 1264f2bbc96eSHarald Freudenberger apqns, &nr_apqns); 1265f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 1266f2bbc96eSHarald Freudenberger kfree(kkey); 1267f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1268f2bbc96eSHarald Freudenberger kfree(apqns); 1269f2bbc96eSHarald Freudenberger break; 1270f2bbc96eSHarald Freudenberger } 1271f2bbc96eSHarald Freudenberger if (!rc && kak.apqns) { 1272f2bbc96eSHarald Freudenberger if (nr_apqns > kak.apqn_entries) { 1273f2bbc96eSHarald Freudenberger kfree(apqns); 1274f2bbc96eSHarald Freudenberger return -EINVAL; 1275f2bbc96eSHarald Freudenberger } 1276f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1277f2bbc96eSHarald Freudenberger if (len) { 1278f2bbc96eSHarald Freudenberger if (copy_to_user(kak.apqns, apqns, len)) { 1279f2bbc96eSHarald Freudenberger kfree(apqns); 1280f2bbc96eSHarald Freudenberger return -EFAULT; 1281f2bbc96eSHarald Freudenberger } 1282f2bbc96eSHarald Freudenberger } 1283f2bbc96eSHarald Freudenberger } 1284f2bbc96eSHarald Freudenberger kak.apqn_entries = nr_apqns; 1285f2bbc96eSHarald Freudenberger if (copy_to_user(uak, &kak, sizeof(kak))) 1286f2bbc96eSHarald Freudenberger rc = -EFAULT; 1287f2bbc96eSHarald Freudenberger kfree(apqns); 1288f2bbc96eSHarald Freudenberger break; 1289f2bbc96eSHarald Freudenberger } 1290f2bbc96eSHarald Freudenberger case PKEY_APQNS4KT: { 1291f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype __user *uat = (void __user *) arg; 1292f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype kat; 1293f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1294f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1295f2bbc96eSHarald Freudenberger 1296f2bbc96eSHarald Freudenberger if (copy_from_user(&kat, uat, sizeof(kat))) 1297f2bbc96eSHarald Freudenberger return -EFAULT; 1298f2bbc96eSHarald Freudenberger nr_apqns = kat.apqn_entries; 1299f2bbc96eSHarald Freudenberger if (nr_apqns) { 1300f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1301f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1302f2bbc96eSHarald Freudenberger GFP_KERNEL); 1303f2bbc96eSHarald Freudenberger if (!apqns) 1304f2bbc96eSHarald Freudenberger return -ENOMEM; 1305f2bbc96eSHarald Freudenberger } 1306f2bbc96eSHarald Freudenberger rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 1307f2bbc96eSHarald Freudenberger kat.flags, apqns, &nr_apqns); 1308f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 1309f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1310f2bbc96eSHarald Freudenberger kfree(apqns); 1311f2bbc96eSHarald Freudenberger break; 1312f2bbc96eSHarald Freudenberger } 1313f2bbc96eSHarald Freudenberger if (!rc && kat.apqns) { 1314f2bbc96eSHarald Freudenberger if (nr_apqns > kat.apqn_entries) { 1315f2bbc96eSHarald Freudenberger kfree(apqns); 1316f2bbc96eSHarald Freudenberger return -EINVAL; 1317f2bbc96eSHarald Freudenberger } 1318f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1319f2bbc96eSHarald Freudenberger if (len) { 1320f2bbc96eSHarald Freudenberger if (copy_to_user(kat.apqns, apqns, len)) { 1321f2bbc96eSHarald Freudenberger kfree(apqns); 1322f2bbc96eSHarald Freudenberger return -EFAULT; 1323f2bbc96eSHarald Freudenberger } 1324f2bbc96eSHarald Freudenberger } 1325f2bbc96eSHarald Freudenberger } 1326f2bbc96eSHarald Freudenberger kat.apqn_entries = nr_apqns; 1327f2bbc96eSHarald Freudenberger if (copy_to_user(uat, &kat, sizeof(kat))) 1328f2bbc96eSHarald Freudenberger rc = -EFAULT; 1329f2bbc96eSHarald Freudenberger kfree(apqns); 1330f2bbc96eSHarald Freudenberger break; 1331f2bbc96eSHarald Freudenberger } 1332e80d4af0SHarald Freudenberger default: 1333e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1334e80d4af0SHarald Freudenberger return -ENOTTY; 1335e80d4af0SHarald Freudenberger } 1336e80d4af0SHarald Freudenberger 1337e80d4af0SHarald Freudenberger return rc; 1338e80d4af0SHarald Freudenberger } 1339e80d4af0SHarald Freudenberger 1340e80d4af0SHarald Freudenberger /* 1341e80d4af0SHarald Freudenberger * Sysfs and file io operations 1342e80d4af0SHarald Freudenberger */ 1343d632c047SIngo Franzki 1344d632c047SIngo Franzki /* 1345d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1346d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1347d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1348d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1349d632c047SIngo Franzki */ 1350d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1351d632c047SIngo Franzki loff_t off, size_t count) 1352d632c047SIngo Franzki { 1353d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1354d632c047SIngo Franzki struct pkey_protkey protkey; 1355d632c047SIngo Franzki int rc; 1356d632c047SIngo Franzki 1357d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1358d632c047SIngo Franzki return -EINVAL; 1359d632c047SIngo Franzki if (is_xts) 1360d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1361d632c047SIngo Franzki return -EINVAL; 1362d632c047SIngo Franzki 1363d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1364d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1365d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1366d632c047SIngo Franzki protkeytoken.keytype = keytype; 1367d632c047SIngo Franzki 1368d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1369d632c047SIngo Franzki if (rc) 1370d632c047SIngo Franzki return rc; 1371d632c047SIngo Franzki 1372d632c047SIngo Franzki protkeytoken.len = protkey.len; 1373d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1374d632c047SIngo Franzki 1375d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1376d632c047SIngo Franzki 1377d632c047SIngo Franzki if (is_xts) { 1378d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1379d632c047SIngo Franzki if (rc) 1380d632c047SIngo Franzki return rc; 1381d632c047SIngo Franzki 1382d632c047SIngo Franzki protkeytoken.len = protkey.len; 1383d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1384d632c047SIngo Franzki 1385d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1386d632c047SIngo Franzki sizeof(protkeytoken)); 1387d632c047SIngo Franzki 1388d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1389d632c047SIngo Franzki } 1390d632c047SIngo Franzki 1391d632c047SIngo Franzki return sizeof(protkeytoken); 1392d632c047SIngo Franzki } 1393d632c047SIngo Franzki 1394d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1395d632c047SIngo Franzki struct kobject *kobj, 1396d632c047SIngo Franzki struct bin_attribute *attr, 1397d632c047SIngo Franzki char *buf, loff_t off, 1398d632c047SIngo Franzki size_t count) 1399d632c047SIngo Franzki { 1400d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1401d632c047SIngo Franzki off, count); 1402d632c047SIngo Franzki } 1403d632c047SIngo Franzki 1404d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1405d632c047SIngo Franzki struct kobject *kobj, 1406d632c047SIngo Franzki struct bin_attribute *attr, 1407d632c047SIngo Franzki char *buf, loff_t off, 1408d632c047SIngo Franzki size_t count) 1409d632c047SIngo Franzki { 1410d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1411d632c047SIngo Franzki off, count); 1412d632c047SIngo Franzki } 1413d632c047SIngo Franzki 1414d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1415d632c047SIngo Franzki struct kobject *kobj, 1416d632c047SIngo Franzki struct bin_attribute *attr, 1417d632c047SIngo Franzki char *buf, loff_t off, 1418d632c047SIngo Franzki size_t count) 1419d632c047SIngo Franzki { 1420d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1421d632c047SIngo Franzki off, count); 1422d632c047SIngo Franzki } 1423d632c047SIngo Franzki 1424d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1425d632c047SIngo Franzki struct kobject *kobj, 1426d632c047SIngo Franzki struct bin_attribute *attr, 1427d632c047SIngo Franzki char *buf, loff_t off, 1428d632c047SIngo Franzki size_t count) 1429d632c047SIngo Franzki { 1430d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1431d632c047SIngo Franzki off, count); 1432d632c047SIngo Franzki } 1433d632c047SIngo Franzki 1434d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1435d632c047SIngo Franzki struct kobject *kobj, 1436d632c047SIngo Franzki struct bin_attribute *attr, 1437d632c047SIngo Franzki char *buf, loff_t off, 1438d632c047SIngo Franzki size_t count) 1439d632c047SIngo Franzki { 1440d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1441d632c047SIngo Franzki off, count); 1442d632c047SIngo Franzki } 1443d632c047SIngo Franzki 1444d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1445d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1446d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1447d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1448d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1449d632c047SIngo Franzki 1450d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1451d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1452d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1453d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1454d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1455d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1456d632c047SIngo Franzki NULL 1457d632c047SIngo Franzki }; 1458d632c047SIngo Franzki 1459d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1460d632c047SIngo Franzki .name = "protkey", 1461d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1462d632c047SIngo Franzki }; 1463d632c047SIngo Franzki 1464af504452SIngo Franzki /* 1465af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1466af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1467af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1468af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1469af504452SIngo Franzki */ 1470af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1471af504452SIngo Franzki loff_t off, size_t count) 1472af504452SIngo Franzki { 1473af504452SIngo Franzki int rc; 1474efc598e6SHarald Freudenberger struct pkey_seckey *seckey = (struct pkey_seckey *) buf; 1475af504452SIngo Franzki 1476af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1477af504452SIngo Franzki return -EINVAL; 1478af504452SIngo Franzki if (is_xts) 1479af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1480af504452SIngo Franzki return -EINVAL; 1481af504452SIngo Franzki 1482efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1483af504452SIngo Franzki if (rc) 1484af504452SIngo Franzki return rc; 1485af504452SIngo Franzki 1486af504452SIngo Franzki if (is_xts) { 1487efc598e6SHarald Freudenberger seckey++; 1488efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1489af504452SIngo Franzki if (rc) 1490af504452SIngo Franzki return rc; 1491af504452SIngo Franzki 1492af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1493af504452SIngo Franzki } 1494af504452SIngo Franzki 1495af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1496af504452SIngo Franzki } 1497af504452SIngo Franzki 1498af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1499af504452SIngo Franzki struct kobject *kobj, 1500af504452SIngo Franzki struct bin_attribute *attr, 1501af504452SIngo Franzki char *buf, loff_t off, 1502af504452SIngo Franzki size_t count) 1503af504452SIngo Franzki { 1504af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1505af504452SIngo Franzki off, count); 1506af504452SIngo Franzki } 1507af504452SIngo Franzki 1508af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1509af504452SIngo Franzki struct kobject *kobj, 1510af504452SIngo Franzki struct bin_attribute *attr, 1511af504452SIngo Franzki char *buf, loff_t off, 1512af504452SIngo Franzki size_t count) 1513af504452SIngo Franzki { 1514af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1515af504452SIngo Franzki off, count); 1516af504452SIngo Franzki } 1517af504452SIngo Franzki 1518af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1519af504452SIngo Franzki struct kobject *kobj, 1520af504452SIngo Franzki struct bin_attribute *attr, 1521af504452SIngo Franzki char *buf, loff_t off, 1522af504452SIngo Franzki size_t count) 1523af504452SIngo Franzki { 1524af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1525af504452SIngo Franzki off, count); 1526af504452SIngo Franzki } 1527af504452SIngo Franzki 1528af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1529af504452SIngo Franzki struct kobject *kobj, 1530af504452SIngo Franzki struct bin_attribute *attr, 1531af504452SIngo Franzki char *buf, loff_t off, 1532af504452SIngo Franzki size_t count) 1533af504452SIngo Franzki { 1534af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1535af504452SIngo Franzki off, count); 1536af504452SIngo Franzki } 1537af504452SIngo Franzki 1538af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1539af504452SIngo Franzki struct kobject *kobj, 1540af504452SIngo Franzki struct bin_attribute *attr, 1541af504452SIngo Franzki char *buf, loff_t off, 1542af504452SIngo Franzki size_t count) 1543af504452SIngo Franzki { 1544af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1545af504452SIngo Franzki off, count); 1546af504452SIngo Franzki } 1547af504452SIngo Franzki 1548af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1549af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1550af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1551af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1552af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1553af504452SIngo Franzki 1554af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1555af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1556af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1557af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1558af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1559af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1560af504452SIngo Franzki NULL 1561af504452SIngo Franzki }; 1562af504452SIngo Franzki 1563af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1564af504452SIngo Franzki .name = "ccadata", 1565af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1566af504452SIngo Franzki }; 1567af504452SIngo Franzki 1568f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) 1569f71fee27SIngo Franzki 1570f71fee27SIngo Franzki /* 1571f71fee27SIngo Franzki * Sysfs attribute read function for all secure key ccacipher binary attributes. 1572f71fee27SIngo Franzki * The implementation can not deal with partial reads, because a new random 1573f71fee27SIngo Franzki * secure key blob is generated with each read. In case of partial reads 1574f71fee27SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1575f71fee27SIngo Franzki */ 1576f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, 1577f71fee27SIngo Franzki bool is_xts, char *buf, loff_t off, 1578f71fee27SIngo Franzki size_t count) 1579f71fee27SIngo Franzki { 158055d0a513SHarald Freudenberger int i, rc, card, dom; 158155d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 158255d0a513SHarald Freudenberger size_t keysize = CCACIPHERTOKENSIZE; 1583f71fee27SIngo Franzki 1584f71fee27SIngo Franzki if (off != 0 || count < CCACIPHERTOKENSIZE) 1585f71fee27SIngo Franzki return -EINVAL; 1586f71fee27SIngo Franzki if (is_xts) 1587f71fee27SIngo Franzki if (count < 2 * CCACIPHERTOKENSIZE) 1588f71fee27SIngo Franzki return -EINVAL; 1589f71fee27SIngo Franzki 159055d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 159155d0a513SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 159255d0a513SHarald Freudenberger ZCRYPT_CEX6, 0, 0, 0); 1593f71fee27SIngo Franzki if (rc) 1594f71fee27SIngo Franzki return rc; 159555d0a513SHarald Freudenberger 159655d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 159755d0a513SHarald Freudenberger 159855d0a513SHarald Freudenberger /* simple try all apqns from the list */ 159955d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 160055d0a513SHarald Freudenberger card = apqns[i] >> 16; 160155d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 160255d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 160355d0a513SHarald Freudenberger if (rc == 0) 160455d0a513SHarald Freudenberger break; 160555d0a513SHarald Freudenberger } 160655d0a513SHarald Freudenberger if (rc) 160755d0a513SHarald Freudenberger return rc; 1608f71fee27SIngo Franzki 1609f71fee27SIngo Franzki if (is_xts) { 1610f71fee27SIngo Franzki keysize = CCACIPHERTOKENSIZE; 161155d0a513SHarald Freudenberger buf += CCACIPHERTOKENSIZE; 161255d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 161355d0a513SHarald Freudenberger if (rc == 0) 1614f71fee27SIngo Franzki return 2 * CCACIPHERTOKENSIZE; 1615f71fee27SIngo Franzki } 1616f71fee27SIngo Franzki 1617f71fee27SIngo Franzki return CCACIPHERTOKENSIZE; 1618f71fee27SIngo Franzki } 1619f71fee27SIngo Franzki 1620f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp, 1621f71fee27SIngo Franzki struct kobject *kobj, 1622f71fee27SIngo Franzki struct bin_attribute *attr, 1623f71fee27SIngo Franzki char *buf, loff_t off, 1624f71fee27SIngo Franzki size_t count) 1625f71fee27SIngo Franzki { 1626f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 1627f71fee27SIngo Franzki off, count); 1628f71fee27SIngo Franzki } 1629f71fee27SIngo Franzki 1630f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp, 1631f71fee27SIngo Franzki struct kobject *kobj, 1632f71fee27SIngo Franzki struct bin_attribute *attr, 1633f71fee27SIngo Franzki char *buf, loff_t off, 1634f71fee27SIngo Franzki size_t count) 1635f71fee27SIngo Franzki { 1636f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 1637f71fee27SIngo Franzki off, count); 1638f71fee27SIngo Franzki } 1639f71fee27SIngo Franzki 1640f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp, 1641f71fee27SIngo Franzki struct kobject *kobj, 1642f71fee27SIngo Franzki struct bin_attribute *attr, 1643f71fee27SIngo Franzki char *buf, loff_t off, 1644f71fee27SIngo Franzki size_t count) 1645f71fee27SIngo Franzki { 1646f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 1647f71fee27SIngo Franzki off, count); 1648f71fee27SIngo Franzki } 1649f71fee27SIngo Franzki 1650f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp, 1651f71fee27SIngo Franzki struct kobject *kobj, 1652f71fee27SIngo Franzki struct bin_attribute *attr, 1653f71fee27SIngo Franzki char *buf, loff_t off, 1654f71fee27SIngo Franzki size_t count) 1655f71fee27SIngo Franzki { 1656f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 1657f71fee27SIngo Franzki off, count); 1658f71fee27SIngo Franzki } 1659f71fee27SIngo Franzki 1660f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp, 1661f71fee27SIngo Franzki struct kobject *kobj, 1662f71fee27SIngo Franzki struct bin_attribute *attr, 1663f71fee27SIngo Franzki char *buf, loff_t off, 1664f71fee27SIngo Franzki size_t count) 1665f71fee27SIngo Franzki { 1666f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 1667f71fee27SIngo Franzki off, count); 1668f71fee27SIngo Franzki } 1669f71fee27SIngo Franzki 1670f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); 1671f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); 1672f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); 1673f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); 1674f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); 1675f71fee27SIngo Franzki 1676f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = { 1677f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128, 1678f71fee27SIngo Franzki &bin_attr_ccacipher_aes_192, 1679f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256, 1680f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128_xts, 1681f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256_xts, 1682f71fee27SIngo Franzki NULL 1683f71fee27SIngo Franzki }; 1684f71fee27SIngo Franzki 1685f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = { 1686f71fee27SIngo Franzki .name = "ccacipher", 1687f71fee27SIngo Franzki .bin_attrs = ccacipher_attrs, 1688f71fee27SIngo Franzki }; 1689f71fee27SIngo Franzki 169055d0a513SHarald Freudenberger /* 169155d0a513SHarald Freudenberger * Sysfs attribute read function for all ep11 aes key binary attributes. 169255d0a513SHarald Freudenberger * The implementation can not deal with partial reads, because a new random 169355d0a513SHarald Freudenberger * secure key blob is generated with each read. In case of partial reads 169455d0a513SHarald Freudenberger * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 169555d0a513SHarald Freudenberger * This function and the sysfs attributes using it provide EP11 key blobs 169655d0a513SHarald Freudenberger * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently 169755d0a513SHarald Freudenberger * 320 bytes. 169855d0a513SHarald Freudenberger */ 169955d0a513SHarald Freudenberger static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, 170055d0a513SHarald Freudenberger bool is_xts, char *buf, loff_t off, 170155d0a513SHarald Freudenberger size_t count) 170255d0a513SHarald Freudenberger { 170355d0a513SHarald Freudenberger int i, rc, card, dom; 170455d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 170555d0a513SHarald Freudenberger size_t keysize = MAXEP11AESKEYBLOBSIZE; 170655d0a513SHarald Freudenberger 170755d0a513SHarald Freudenberger if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) 170855d0a513SHarald Freudenberger return -EINVAL; 170955d0a513SHarald Freudenberger if (is_xts) 171055d0a513SHarald Freudenberger if (count < 2 * MAXEP11AESKEYBLOBSIZE) 171155d0a513SHarald Freudenberger return -EINVAL; 171255d0a513SHarald Freudenberger 171355d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 171455d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 171555d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 171655d0a513SHarald Freudenberger if (rc) 171755d0a513SHarald Freudenberger return rc; 171855d0a513SHarald Freudenberger 171955d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 172055d0a513SHarald Freudenberger 172155d0a513SHarald Freudenberger /* simple try all apqns from the list */ 172255d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 172355d0a513SHarald Freudenberger card = apqns[i] >> 16; 172455d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 172555d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 172655d0a513SHarald Freudenberger if (rc == 0) 172755d0a513SHarald Freudenberger break; 172855d0a513SHarald Freudenberger } 172955d0a513SHarald Freudenberger if (rc) 173055d0a513SHarald Freudenberger return rc; 173155d0a513SHarald Freudenberger 173255d0a513SHarald Freudenberger if (is_xts) { 173355d0a513SHarald Freudenberger keysize = MAXEP11AESKEYBLOBSIZE; 173455d0a513SHarald Freudenberger buf += MAXEP11AESKEYBLOBSIZE; 173555d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 173655d0a513SHarald Freudenberger if (rc == 0) 173755d0a513SHarald Freudenberger return 2 * MAXEP11AESKEYBLOBSIZE; 173855d0a513SHarald Freudenberger } 173955d0a513SHarald Freudenberger 174055d0a513SHarald Freudenberger return MAXEP11AESKEYBLOBSIZE; 174155d0a513SHarald Freudenberger } 174255d0a513SHarald Freudenberger 174355d0a513SHarald Freudenberger static ssize_t ep11_aes_128_read(struct file *filp, 174455d0a513SHarald Freudenberger struct kobject *kobj, 174555d0a513SHarald Freudenberger struct bin_attribute *attr, 174655d0a513SHarald Freudenberger char *buf, loff_t off, 174755d0a513SHarald Freudenberger size_t count) 174855d0a513SHarald Freudenberger { 174955d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 175055d0a513SHarald Freudenberger off, count); 175155d0a513SHarald Freudenberger } 175255d0a513SHarald Freudenberger 175355d0a513SHarald Freudenberger static ssize_t ep11_aes_192_read(struct file *filp, 175455d0a513SHarald Freudenberger struct kobject *kobj, 175555d0a513SHarald Freudenberger struct bin_attribute *attr, 175655d0a513SHarald Freudenberger char *buf, loff_t off, 175755d0a513SHarald Freudenberger size_t count) 175855d0a513SHarald Freudenberger { 175955d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 176055d0a513SHarald Freudenberger off, count); 176155d0a513SHarald Freudenberger } 176255d0a513SHarald Freudenberger 176355d0a513SHarald Freudenberger static ssize_t ep11_aes_256_read(struct file *filp, 176455d0a513SHarald Freudenberger struct kobject *kobj, 176555d0a513SHarald Freudenberger struct bin_attribute *attr, 176655d0a513SHarald Freudenberger char *buf, loff_t off, 176755d0a513SHarald Freudenberger size_t count) 176855d0a513SHarald Freudenberger { 176955d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 177055d0a513SHarald Freudenberger off, count); 177155d0a513SHarald Freudenberger } 177255d0a513SHarald Freudenberger 177355d0a513SHarald Freudenberger static ssize_t ep11_aes_128_xts_read(struct file *filp, 177455d0a513SHarald Freudenberger struct kobject *kobj, 177555d0a513SHarald Freudenberger struct bin_attribute *attr, 177655d0a513SHarald Freudenberger char *buf, loff_t off, 177755d0a513SHarald Freudenberger size_t count) 177855d0a513SHarald Freudenberger { 177955d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 178055d0a513SHarald Freudenberger off, count); 178155d0a513SHarald Freudenberger } 178255d0a513SHarald Freudenberger 178355d0a513SHarald Freudenberger static ssize_t ep11_aes_256_xts_read(struct file *filp, 178455d0a513SHarald Freudenberger struct kobject *kobj, 178555d0a513SHarald Freudenberger struct bin_attribute *attr, 178655d0a513SHarald Freudenberger char *buf, loff_t off, 178755d0a513SHarald Freudenberger size_t count) 178855d0a513SHarald Freudenberger { 178955d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 179055d0a513SHarald Freudenberger off, count); 179155d0a513SHarald Freudenberger } 179255d0a513SHarald Freudenberger 179355d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE); 179455d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE); 179555d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE); 179655d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE); 179755d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE); 179855d0a513SHarald Freudenberger 179955d0a513SHarald Freudenberger static struct bin_attribute *ep11_attrs[] = { 180055d0a513SHarald Freudenberger &bin_attr_ep11_aes_128, 180155d0a513SHarald Freudenberger &bin_attr_ep11_aes_192, 180255d0a513SHarald Freudenberger &bin_attr_ep11_aes_256, 180355d0a513SHarald Freudenberger &bin_attr_ep11_aes_128_xts, 180455d0a513SHarald Freudenberger &bin_attr_ep11_aes_256_xts, 180555d0a513SHarald Freudenberger NULL 180655d0a513SHarald Freudenberger }; 180755d0a513SHarald Freudenberger 180855d0a513SHarald Freudenberger static struct attribute_group ep11_attr_group = { 180955d0a513SHarald Freudenberger .name = "ep11", 181055d0a513SHarald Freudenberger .bin_attrs = ep11_attrs, 181155d0a513SHarald Freudenberger }; 181255d0a513SHarald Freudenberger 1813d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 1814d632c047SIngo Franzki &protkey_attr_group, 1815af504452SIngo Franzki &ccadata_attr_group, 1816f71fee27SIngo Franzki &ccacipher_attr_group, 181755d0a513SHarald Freudenberger &ep11_attr_group, 1818d632c047SIngo Franzki NULL, 1819d632c047SIngo Franzki }; 1820d632c047SIngo Franzki 1821e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 1822e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 1823e80d4af0SHarald Freudenberger .open = nonseekable_open, 1824e80d4af0SHarald Freudenberger .llseek = no_llseek, 1825e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 1826e80d4af0SHarald Freudenberger }; 1827e80d4af0SHarald Freudenberger 1828e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 1829e80d4af0SHarald Freudenberger .name = "pkey", 1830e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 1831e80d4af0SHarald Freudenberger .mode = 0666, 1832e80d4af0SHarald Freudenberger .fops = &pkey_fops, 1833d632c047SIngo Franzki .groups = pkey_attr_groups, 1834e80d4af0SHarald Freudenberger }; 1835e80d4af0SHarald Freudenberger 1836e80d4af0SHarald Freudenberger /* 1837e80d4af0SHarald Freudenberger * Module init 1838e80d4af0SHarald Freudenberger */ 1839cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 1840e80d4af0SHarald Freudenberger { 1841f822ad2cSHarald Freudenberger cpacf_mask_t kmc_functions; 1842e80d4af0SHarald Freudenberger 1843f822ad2cSHarald Freudenberger /* 1844f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 1845f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 1846f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 1847f822ad2cSHarald Freudenberger * are able to work with protected keys. 1848f822ad2cSHarald Freudenberger */ 1849e80d4af0SHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 185058443b67SDavid Hildenbrand return -ENODEV; 1851e80d4af0SHarald Freudenberger 1852cb26b9ffSIngo Franzki /* check for kmc instructions available */ 1853cb26b9ffSIngo Franzki if (!cpacf_query(CPACF_KMC, &kmc_functions)) 185458443b67SDavid Hildenbrand return -ENODEV; 1855cb26b9ffSIngo Franzki if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) || 1856cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) || 1857cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) 185858443b67SDavid Hildenbrand return -ENODEV; 1859cb26b9ffSIngo Franzki 1860e80d4af0SHarald Freudenberger pkey_debug_init(); 1861e80d4af0SHarald Freudenberger 1862e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 1863e80d4af0SHarald Freudenberger } 1864e80d4af0SHarald Freudenberger 1865e80d4af0SHarald Freudenberger /* 1866e80d4af0SHarald Freudenberger * Module exit 1867e80d4af0SHarald Freudenberger */ 1868e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 1869e80d4af0SHarald Freudenberger { 1870e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 1871e80d4af0SHarald Freudenberger pkey_debug_exit(); 1872e80d4af0SHarald Freudenberger } 1873e80d4af0SHarald Freudenberger 187463c19be0SIngo Franzki module_cpu_feature_match(MSA, pkey_init); 1875e80d4af0SHarald Freudenberger module_exit(pkey_exit); 1876