1812141a9SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2e80d4af0SHarald Freudenberger /* 3e80d4af0SHarald Freudenberger * pkey device driver 4e80d4af0SHarald Freudenberger * 5183cb469SHarald Freudenberger * Copyright IBM Corp. 2017,2019 6e80d4af0SHarald Freudenberger * Author(s): Harald Freudenberger 7e80d4af0SHarald Freudenberger */ 8e80d4af0SHarald Freudenberger 9e80d4af0SHarald Freudenberger #define KMSG_COMPONENT "pkey" 10e80d4af0SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 11e80d4af0SHarald Freudenberger 12e80d4af0SHarald Freudenberger #include <linux/fs.h> 13e80d4af0SHarald Freudenberger #include <linux/init.h> 14e80d4af0SHarald Freudenberger #include <linux/miscdevice.h> 15e80d4af0SHarald Freudenberger #include <linux/module.h> 16e80d4af0SHarald Freudenberger #include <linux/slab.h> 17e80d4af0SHarald Freudenberger #include <linux/kallsyms.h> 18e80d4af0SHarald Freudenberger #include <linux/debugfs.h> 19a45a5c7dSIngo Franzki #include <linux/random.h> 2063c19be0SIngo Franzki #include <linux/cpufeature.h> 21e80d4af0SHarald Freudenberger #include <asm/zcrypt.h> 22e80d4af0SHarald Freudenberger #include <asm/cpacf.h> 23e80d4af0SHarald Freudenberger #include <asm/pkey.h> 24cb26b9ffSIngo Franzki #include <crypto/aes.h> 25e80d4af0SHarald Freudenberger 26e80d4af0SHarald Freudenberger #include "zcrypt_api.h" 27efc598e6SHarald Freudenberger #include "zcrypt_ccamisc.h" 2855d0a513SHarald Freudenberger #include "zcrypt_ep11misc.h" 29e80d4af0SHarald Freudenberger 30e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL"); 31e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 32e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface"); 33e80d4af0SHarald Freudenberger 34f2bbc96eSHarald Freudenberger #define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ 35fa6999e3SHarald Freudenberger #define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */ 36f2bbc96eSHarald Freudenberger #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ 37f2bbc96eSHarald Freudenberger 38e80d4af0SHarald Freudenberger /* 39e80d4af0SHarald Freudenberger * debug feature data and functions 40e80d4af0SHarald Freudenberger */ 41e80d4af0SHarald Freudenberger 42e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 43e80d4af0SHarald Freudenberger 44e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 45e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 46e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 47e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 48e80d4af0SHarald Freudenberger 49e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 50e80d4af0SHarald Freudenberger { 516b1f16baSHarald Freudenberger /* 5 arguments per dbf entry (including the format string ptr) */ 526b1f16baSHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); 53e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 54e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 55e80d4af0SHarald Freudenberger } 56e80d4af0SHarald Freudenberger 57e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 58e80d4af0SHarald Freudenberger { 59e80d4af0SHarald Freudenberger debug_unregister(debug_info); 60e80d4af0SHarald Freudenberger } 61e80d4af0SHarald Freudenberger 620534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */ 630534bde7SIngo Franzki struct protaeskeytoken { 640534bde7SIngo Franzki u8 type; /* 0x00 for PAES specific key tokens */ 650534bde7SIngo Franzki u8 res0[3]; 660534bde7SIngo Franzki u8 version; /* should be 0x01 for protected AES key token */ 670534bde7SIngo Franzki u8 res1[3]; 680534bde7SIngo Franzki u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 690534bde7SIngo Franzki u32 len; /* bytes actually stored in protkey[] */ 700534bde7SIngo Franzki u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 710534bde7SIngo Franzki } __packed; 720534bde7SIngo Franzki 73888edbc4SHarald Freudenberger /* inside view of a clear key token (type 0x00 version 0x02) */ 74888edbc4SHarald Freudenberger struct clearaeskeytoken { 75888edbc4SHarald Freudenberger u8 type; /* 0x00 for PAES specific key tokens */ 76888edbc4SHarald Freudenberger u8 res0[3]; 77888edbc4SHarald Freudenberger u8 version; /* 0x02 for clear AES key token */ 78888edbc4SHarald Freudenberger u8 res1[3]; 79888edbc4SHarald Freudenberger u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 80888edbc4SHarald Freudenberger u32 len; /* bytes actually stored in clearkey[] */ 81fa226f1dSGustavo A. R. Silva u8 clearkey[]; /* clear key value */ 82888edbc4SHarald Freudenberger } __packed; 83888edbc4SHarald Freudenberger 84e80d4af0SHarald Freudenberger /* 85e80d4af0SHarald Freudenberger * Create a protected key from a clear key value. 86e80d4af0SHarald Freudenberger */ 87183cb469SHarald Freudenberger static int pkey_clr2protkey(u32 keytype, 88e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 89e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 90e80d4af0SHarald Freudenberger { 91*5b35047eSHarald Freudenberger /* mask of available pckmo subfunctions */ 92*5b35047eSHarald Freudenberger static cpacf_mask_t pckmo_functions; 93*5b35047eSHarald Freudenberger 94e80d4af0SHarald Freudenberger long fc; 95e80d4af0SHarald Freudenberger int keysize; 96e80d4af0SHarald Freudenberger u8 paramblock[64]; 97e80d4af0SHarald Freudenberger 98e80d4af0SHarald Freudenberger switch (keytype) { 99e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 100e80d4af0SHarald Freudenberger keysize = 16; 101e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 102e80d4af0SHarald Freudenberger break; 103e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 104e80d4af0SHarald Freudenberger keysize = 24; 105e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 106e80d4af0SHarald Freudenberger break; 107e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 108e80d4af0SHarald Freudenberger keysize = 32; 109e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 110e80d4af0SHarald Freudenberger break; 111e80d4af0SHarald Freudenberger default: 112ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 113ac2b96f3SHarald Freudenberger __func__, keytype); 114e80d4af0SHarald Freudenberger return -EINVAL; 115e80d4af0SHarald Freudenberger } 116e80d4af0SHarald Freudenberger 117*5b35047eSHarald Freudenberger /* Did we already check for PCKMO ? */ 118*5b35047eSHarald Freudenberger if (!pckmo_functions.bytes[0]) { 119*5b35047eSHarald Freudenberger /* no, so check now */ 120*5b35047eSHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 121*5b35047eSHarald Freudenberger return -ENODEV; 122*5b35047eSHarald Freudenberger } 123*5b35047eSHarald Freudenberger /* check for the pckmo subfunction we need now */ 124f822ad2cSHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, fc)) { 125f822ad2cSHarald Freudenberger DEBUG_ERR("%s pckmo functions not available\n", __func__); 12658443b67SDavid Hildenbrand return -ENODEV; 127f822ad2cSHarald Freudenberger } 128f822ad2cSHarald Freudenberger 129e80d4af0SHarald Freudenberger /* prepare param block */ 130e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 131e80d4af0SHarald Freudenberger memcpy(paramblock, clrkey->clrkey, keysize); 132e80d4af0SHarald Freudenberger 133e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 134e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 135e80d4af0SHarald Freudenberger 136e80d4af0SHarald Freudenberger /* copy created protected key */ 137e80d4af0SHarald Freudenberger protkey->type = keytype; 138e80d4af0SHarald Freudenberger protkey->len = keysize + 32; 139e80d4af0SHarald Freudenberger memcpy(protkey->protkey, paramblock, keysize + 32); 140e80d4af0SHarald Freudenberger 141e80d4af0SHarald Freudenberger return 0; 142e80d4af0SHarald Freudenberger } 143e80d4af0SHarald Freudenberger 144e80d4af0SHarald Freudenberger /* 145e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 146e80d4af0SHarald Freudenberger */ 147f2bbc96eSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) 148e80d4af0SHarald Freudenberger { 149e80d4af0SHarald Freudenberger int rc, verify; 150f2bbc96eSHarald Freudenberger u16 cardnr, domain; 151f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 152e80d4af0SHarald Freudenberger 153e80d4af0SHarald Freudenberger /* 154f2bbc96eSHarald Freudenberger * The cca_xxx2protkey call may fail when a card has been 155e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 156efc598e6SHarald Freudenberger * of the mkvp into the cache. Try 3 times: First witout verify 157efc598e6SHarald Freudenberger * then with verify and last round with verify and old master 158efc598e6SHarald Freudenberger * key verification pattern match not ignored. 159e80d4af0SHarald Freudenberger */ 160efc598e6SHarald Freudenberger for (verify = 0; verify < 3; verify++) { 161f2bbc96eSHarald Freudenberger rc = cca_findcard(key, &cardnr, &domain, verify); 162efc598e6SHarald Freudenberger if (rc < 0) 163e80d4af0SHarald Freudenberger continue; 164efc598e6SHarald Freudenberger if (rc > 0 && verify < 2) 165efc598e6SHarald Freudenberger continue; 166f2bbc96eSHarald Freudenberger switch (hdr->version) { 167f2bbc96eSHarald Freudenberger case TOKVER_CCA_AES: 168f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(cardnr, domain, 169f2bbc96eSHarald Freudenberger key, pkey->protkey, 170f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 171f2bbc96eSHarald Freudenberger break; 172f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 173f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(cardnr, domain, 174f2bbc96eSHarald Freudenberger key, pkey->protkey, 175f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 176f2bbc96eSHarald Freudenberger break; 177f2bbc96eSHarald Freudenberger default: 178f2bbc96eSHarald Freudenberger return -EINVAL; 179f2bbc96eSHarald Freudenberger } 180e80d4af0SHarald Freudenberger if (rc == 0) 181e80d4af0SHarald Freudenberger break; 182e80d4af0SHarald Freudenberger } 183e80d4af0SHarald Freudenberger 184e80d4af0SHarald Freudenberger if (rc) 185ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 186e80d4af0SHarald Freudenberger 187e80d4af0SHarald Freudenberger return rc; 188e80d4af0SHarald Freudenberger } 189e80d4af0SHarald Freudenberger 190e80d4af0SHarald Freudenberger /* 19155d0a513SHarald Freudenberger * Construct EP11 key with given clear key value. 19255d0a513SHarald Freudenberger */ 19355d0a513SHarald Freudenberger static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, 19455d0a513SHarald Freudenberger u8 *keybuf, size_t *keybuflen) 19555d0a513SHarald Freudenberger { 19655d0a513SHarald Freudenberger int i, rc; 19755d0a513SHarald Freudenberger u16 card, dom; 19855d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 19955d0a513SHarald Freudenberger 20055d0a513SHarald Freudenberger /* build a list of apqns suitable for ep11 keys with cpacf support */ 20155d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 20255d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 20355d0a513SHarald Freudenberger if (rc) 20455d0a513SHarald Freudenberger goto out; 20555d0a513SHarald Freudenberger 20655d0a513SHarald Freudenberger /* go through the list of apqns and try to bild an ep11 key */ 20755d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 20855d0a513SHarald Freudenberger card = apqns[i] >> 16; 20955d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 21055d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, clrkeylen * 8, 21155d0a513SHarald Freudenberger 0, clrkey, keybuf, keybuflen); 21255d0a513SHarald Freudenberger if (rc == 0) 21355d0a513SHarald Freudenberger break; 21455d0a513SHarald Freudenberger } 21555d0a513SHarald Freudenberger 21655d0a513SHarald Freudenberger out: 21755d0a513SHarald Freudenberger kfree(apqns); 21855d0a513SHarald Freudenberger if (rc) 21955d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 22055d0a513SHarald Freudenberger return rc; 22155d0a513SHarald Freudenberger } 22255d0a513SHarald Freudenberger 22355d0a513SHarald Freudenberger /* 22455d0a513SHarald Freudenberger * Find card and transform EP11 secure key into protected key. 22555d0a513SHarald Freudenberger */ 22655d0a513SHarald Freudenberger static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) 22755d0a513SHarald Freudenberger { 22855d0a513SHarald Freudenberger int i, rc; 22955d0a513SHarald Freudenberger u16 card, dom; 23055d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 23155d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) key; 23255d0a513SHarald Freudenberger 23355d0a513SHarald Freudenberger /* build a list of apqns suitable for this key */ 23455d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 23555d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 23655d0a513SHarald Freudenberger if (rc) 23755d0a513SHarald Freudenberger goto out; 23855d0a513SHarald Freudenberger 23955d0a513SHarald Freudenberger /* go through the list of apqns and try to derive an pkey */ 24055d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 24155d0a513SHarald Freudenberger card = apqns[i] >> 16; 24255d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 243fa6999e3SHarald Freudenberger pkey->len = sizeof(pkey->protkey); 244fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 24555d0a513SHarald Freudenberger pkey->protkey, &pkey->len, &pkey->type); 24655d0a513SHarald Freudenberger if (rc == 0) 24755d0a513SHarald Freudenberger break; 24855d0a513SHarald Freudenberger } 24955d0a513SHarald Freudenberger 25055d0a513SHarald Freudenberger out: 25155d0a513SHarald Freudenberger kfree(apqns); 25255d0a513SHarald Freudenberger if (rc) 25355d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 25455d0a513SHarald Freudenberger return rc; 25555d0a513SHarald Freudenberger } 25655d0a513SHarald Freudenberger 25755d0a513SHarald Freudenberger /* 258e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 259e61a6134SHarald Freudenberger */ 260183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey, 261e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 262e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 263e61a6134SHarald Freudenberger { 264e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 265e61a6134SHarald Freudenberger u16 cardnr, domain; 266e61a6134SHarald Freudenberger int rc; 267e61a6134SHarald Freudenberger 268e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 269efc598e6SHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *) seckey, 0); 270e61a6134SHarald Freudenberger if (rc) 271e61a6134SHarald Freudenberger goto out; 272e61a6134SHarald Freudenberger if (pattributes) 273e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 274e61a6134SHarald Freudenberger if (pkeysize) 275e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 276e61a6134SHarald Freudenberger 277e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 278efc598e6SHarald Freudenberger rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); 279efc598e6SHarald Freudenberger if (rc < 0) 280e61a6134SHarald Freudenberger goto out; 281e61a6134SHarald Freudenberger 282efc598e6SHarald Freudenberger if (rc > 0) { 283efc598e6SHarald Freudenberger /* key mkvp matches to old master key mkvp */ 284ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 285e61a6134SHarald Freudenberger if (pattributes) 286e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 287efc598e6SHarald Freudenberger rc = 0; 288e61a6134SHarald Freudenberger } 289e61a6134SHarald Freudenberger 290e61a6134SHarald Freudenberger if (pcardnr) 291e61a6134SHarald Freudenberger *pcardnr = cardnr; 292e61a6134SHarald Freudenberger if (pdomain) 293e61a6134SHarald Freudenberger *pdomain = domain; 294e61a6134SHarald Freudenberger 295e61a6134SHarald Freudenberger out: 296ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 297e61a6134SHarald Freudenberger return rc; 298e61a6134SHarald Freudenberger } 299e61a6134SHarald Freudenberger 300e61a6134SHarald Freudenberger /* 301a45a5c7dSIngo Franzki * Generate a random protected key 302a45a5c7dSIngo Franzki */ 303183cb469SHarald Freudenberger static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) 304a45a5c7dSIngo Franzki { 305a45a5c7dSIngo Franzki struct pkey_clrkey clrkey; 306a45a5c7dSIngo Franzki int keysize; 307a45a5c7dSIngo Franzki int rc; 308a45a5c7dSIngo Franzki 309a45a5c7dSIngo Franzki switch (keytype) { 310a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_128: 311a45a5c7dSIngo Franzki keysize = 16; 312a45a5c7dSIngo Franzki break; 313a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_192: 314a45a5c7dSIngo Franzki keysize = 24; 315a45a5c7dSIngo Franzki break; 316a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_256: 317a45a5c7dSIngo Franzki keysize = 32; 318a45a5c7dSIngo Franzki break; 319a45a5c7dSIngo Franzki default: 320a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 321a45a5c7dSIngo Franzki keytype); 322a45a5c7dSIngo Franzki return -EINVAL; 323a45a5c7dSIngo Franzki } 324a45a5c7dSIngo Franzki 325a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 326a45a5c7dSIngo Franzki get_random_bytes(clrkey.clrkey, keysize); 327a45a5c7dSIngo Franzki 328a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 329a45a5c7dSIngo Franzki rc = pkey_clr2protkey(keytype, &clrkey, protkey); 330a45a5c7dSIngo Franzki if (rc) 331a45a5c7dSIngo Franzki return rc; 332a45a5c7dSIngo Franzki 333a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 334a45a5c7dSIngo Franzki get_random_bytes(protkey->protkey, keysize); 335a45a5c7dSIngo Franzki 336a45a5c7dSIngo Franzki return 0; 337a45a5c7dSIngo Franzki } 338a45a5c7dSIngo Franzki 339a45a5c7dSIngo Franzki /* 340cb26b9ffSIngo Franzki * Verify if a protected key is still valid 341cb26b9ffSIngo Franzki */ 342183cb469SHarald Freudenberger static int pkey_verifyprotkey(const struct pkey_protkey *protkey) 343cb26b9ffSIngo Franzki { 344cb26b9ffSIngo Franzki unsigned long fc; 345cb26b9ffSIngo Franzki struct { 346cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 347cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 348cb26b9ffSIngo Franzki } param; 349cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 350cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 351cb26b9ffSIngo Franzki unsigned int k; 352cb26b9ffSIngo Franzki 353cb26b9ffSIngo Franzki switch (protkey->type) { 354cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 355cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 356cb26b9ffSIngo Franzki break; 357cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 358cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 359cb26b9ffSIngo Franzki break; 360cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 361cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 362cb26b9ffSIngo Franzki break; 363cb26b9ffSIngo Franzki default: 364cb26b9ffSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 365cb26b9ffSIngo Franzki protkey->type); 366cb26b9ffSIngo Franzki return -EINVAL; 367cb26b9ffSIngo Franzki } 368cb26b9ffSIngo Franzki 369cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 370cb26b9ffSIngo Franzki 371cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 372cb26b9ffSIngo Franzki memcpy(param.key, protkey->protkey, sizeof(param.key)); 373cb26b9ffSIngo Franzki 374cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 375cb26b9ffSIngo Franzki sizeof(null_msg)); 376cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 377cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 378cb26b9ffSIngo Franzki return -EKEYREJECTED; 379cb26b9ffSIngo Franzki } 380cb26b9ffSIngo Franzki 381cb26b9ffSIngo Franzki return 0; 382cb26b9ffSIngo Franzki } 383cb26b9ffSIngo Franzki 384cb26b9ffSIngo Franzki /* 385fb1136d6SIngo Franzki * Transform a non-CCA key token into a protected key 386fb1136d6SIngo Franzki */ 387183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, 388fb1136d6SIngo Franzki struct pkey_protkey *protkey) 389fb1136d6SIngo Franzki { 390888edbc4SHarald Freudenberger int rc = -EINVAL; 39155d0a513SHarald Freudenberger u8 *tmpbuf = NULL; 392fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 393fb1136d6SIngo Franzki 394fb1136d6SIngo Franzki switch (hdr->version) { 395888edbc4SHarald Freudenberger case TOKVER_PROTECTED_KEY: { 396888edbc4SHarald Freudenberger struct protaeskeytoken *t; 397fb1136d6SIngo Franzki 398888edbc4SHarald Freudenberger if (keylen != sizeof(struct protaeskeytoken)) 399888edbc4SHarald Freudenberger goto out; 400fb1136d6SIngo Franzki t = (struct protaeskeytoken *)key; 401fb1136d6SIngo Franzki protkey->len = t->len; 402fb1136d6SIngo Franzki protkey->type = t->keytype; 403fb1136d6SIngo Franzki memcpy(protkey->protkey, t->protkey, 404fb1136d6SIngo Franzki sizeof(protkey->protkey)); 405888edbc4SHarald Freudenberger rc = pkey_verifyprotkey(protkey); 406888edbc4SHarald Freudenberger break; 407888edbc4SHarald Freudenberger } 408888edbc4SHarald Freudenberger case TOKVER_CLEAR_KEY: { 409888edbc4SHarald Freudenberger struct clearaeskeytoken *t; 410888edbc4SHarald Freudenberger struct pkey_clrkey ckey; 41155d0a513SHarald Freudenberger union u_tmpbuf { 41255d0a513SHarald Freudenberger u8 skey[SECKEYBLOBSIZE]; 41355d0a513SHarald Freudenberger u8 ep11key[MAXEP11AESKEYBLOBSIZE]; 41455d0a513SHarald Freudenberger }; 41555d0a513SHarald Freudenberger size_t tmpbuflen = sizeof(union u_tmpbuf); 416fb1136d6SIngo Franzki 417888edbc4SHarald Freudenberger if (keylen < sizeof(struct clearaeskeytoken)) 418888edbc4SHarald Freudenberger goto out; 419888edbc4SHarald Freudenberger t = (struct clearaeskeytoken *)key; 420888edbc4SHarald Freudenberger if (keylen != sizeof(*t) + t->len) 421888edbc4SHarald Freudenberger goto out; 422888edbc4SHarald Freudenberger if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) 423888edbc4SHarald Freudenberger || (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) 424888edbc4SHarald Freudenberger || (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) 425888edbc4SHarald Freudenberger memcpy(ckey.clrkey, t->clearkey, t->len); 426888edbc4SHarald Freudenberger else 427888edbc4SHarald Freudenberger goto out; 42855d0a513SHarald Freudenberger /* alloc temp key buffer space */ 42955d0a513SHarald Freudenberger tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 43055d0a513SHarald Freudenberger if (!tmpbuf) { 43155d0a513SHarald Freudenberger rc = -ENOMEM; 43255d0a513SHarald Freudenberger goto out; 43355d0a513SHarald Freudenberger } 434888edbc4SHarald Freudenberger /* try direct way with the PCKMO instruction */ 435888edbc4SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, &ckey, protkey); 436888edbc4SHarald Freudenberger if (rc == 0) 437888edbc4SHarald Freudenberger break; 438888edbc4SHarald Freudenberger /* PCKMO failed, so try the CCA secure key way */ 439888edbc4SHarald Freudenberger rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, 44055d0a513SHarald Freudenberger ckey.clrkey, tmpbuf); 441888edbc4SHarald Freudenberger if (rc == 0) 44255d0a513SHarald Freudenberger rc = pkey_skey2pkey(tmpbuf, protkey); 443888edbc4SHarald Freudenberger if (rc == 0) 444888edbc4SHarald Freudenberger break; 44555d0a513SHarald Freudenberger /* if the CCA way also failed, let's try via EP11 */ 44655d0a513SHarald Freudenberger rc = pkey_clr2ep11key(ckey.clrkey, t->len, 44755d0a513SHarald Freudenberger tmpbuf, &tmpbuflen); 44855d0a513SHarald Freudenberger if (rc == 0) 44955d0a513SHarald Freudenberger rc = pkey_ep11key2pkey(tmpbuf, protkey); 45055d0a513SHarald Freudenberger /* now we should really have an protected key */ 451888edbc4SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", 452888edbc4SHarald Freudenberger __func__); 453888edbc4SHarald Freudenberger break; 454888edbc4SHarald Freudenberger } 45555d0a513SHarald Freudenberger case TOKVER_EP11_AES: { 45655d0a513SHarald Freudenberger /* check ep11 key for exportable as protected key */ 457fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 45855d0a513SHarald Freudenberger if (rc) 45955d0a513SHarald Freudenberger goto out; 46055d0a513SHarald Freudenberger rc = pkey_ep11key2pkey(key, protkey); 46155d0a513SHarald Freudenberger break; 46255d0a513SHarald Freudenberger } 463fa6999e3SHarald Freudenberger case TOKVER_EP11_AES_WITH_HEADER: 464fa6999e3SHarald Freudenberger /* check ep11 key with header for exportable as protected key */ 465fa6999e3SHarald Freudenberger rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1); 466fa6999e3SHarald Freudenberger if (rc) 467fa6999e3SHarald Freudenberger goto out; 468fa6999e3SHarald Freudenberger rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header), 469fa6999e3SHarald Freudenberger protkey); 470fa6999e3SHarald Freudenberger break; 471fb1136d6SIngo Franzki default: 472fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 473fb1136d6SIngo Franzki __func__, hdr->version); 474888edbc4SHarald Freudenberger rc = -EINVAL; 475fb1136d6SIngo Franzki } 476888edbc4SHarald Freudenberger 477888edbc4SHarald Freudenberger out: 47855d0a513SHarald Freudenberger kfree(tmpbuf); 479888edbc4SHarald Freudenberger return rc; 480fb1136d6SIngo Franzki } 481fb1136d6SIngo Franzki 482fb1136d6SIngo Franzki /* 483fb1136d6SIngo Franzki * Transform a CCA internal key token into a protected key 484fb1136d6SIngo Franzki */ 485183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, 486fb1136d6SIngo Franzki struct pkey_protkey *protkey) 487fb1136d6SIngo Franzki { 488fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 489fb1136d6SIngo Franzki 490fb1136d6SIngo Franzki switch (hdr->version) { 491fb1136d6SIngo Franzki case TOKVER_CCA_AES: 492fb1136d6SIngo Franzki if (keylen != sizeof(struct secaeskeytoken)) 493fb1136d6SIngo Franzki return -EINVAL; 494f2bbc96eSHarald Freudenberger break; 495f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 496f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 497f2bbc96eSHarald Freudenberger return -EINVAL; 498f2bbc96eSHarald Freudenberger break; 499fb1136d6SIngo Franzki default: 500fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 501fb1136d6SIngo Franzki __func__, hdr->version); 502fb1136d6SIngo Franzki return -EINVAL; 503fb1136d6SIngo Franzki } 504f2bbc96eSHarald Freudenberger 505f2bbc96eSHarald Freudenberger return pkey_skey2pkey(key, protkey); 506fb1136d6SIngo Franzki } 507fb1136d6SIngo Franzki 508fb1136d6SIngo Franzki /* 509fb1136d6SIngo Franzki * Transform a key blob (of any type) into a protected key 510fb1136d6SIngo Franzki */ 511183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen, 512fb1136d6SIngo Franzki struct pkey_protkey *protkey) 513fb1136d6SIngo Franzki { 514f2bbc96eSHarald Freudenberger int rc; 515fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 516fb1136d6SIngo Franzki 517f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) { 518f2bbc96eSHarald Freudenberger DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); 519f2bbc96eSHarald Freudenberger return -EINVAL; 520f2bbc96eSHarald Freudenberger } 521f2bbc96eSHarald Freudenberger 522f2bbc96eSHarald Freudenberger switch (hdr->type) { 523f2bbc96eSHarald Freudenberger case TOKTYPE_NON_CCA: 524f2bbc96eSHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, protkey); 525f2bbc96eSHarald Freudenberger break; 526f2bbc96eSHarald Freudenberger case TOKTYPE_CCA_INTERNAL: 527f2bbc96eSHarald Freudenberger rc = pkey_ccainttok2pkey(key, keylen, protkey); 528f2bbc96eSHarald Freudenberger break; 529f2bbc96eSHarald Freudenberger default: 530f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 531f2bbc96eSHarald Freudenberger __func__, hdr->type); 532f2bbc96eSHarald Freudenberger return -EINVAL; 533f2bbc96eSHarald Freudenberger } 534f2bbc96eSHarald Freudenberger 535f2bbc96eSHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 536f2bbc96eSHarald Freudenberger return rc; 537f2bbc96eSHarald Freudenberger 538f2bbc96eSHarald Freudenberger } 539f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey); 540f2bbc96eSHarald Freudenberger 541f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 542f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 543f2bbc96eSHarald Freudenberger u32 kflags, u8 *keybuf, size_t *keybufsize) 544f2bbc96eSHarald Freudenberger { 545f2bbc96eSHarald Freudenberger int i, card, dom, rc; 546f2bbc96eSHarald Freudenberger 547f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 548f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 549f2bbc96eSHarald Freudenberger return -EINVAL; 550f2bbc96eSHarald Freudenberger 551f2bbc96eSHarald Freudenberger /* check key type and size */ 552f2bbc96eSHarald Freudenberger switch (ktype) { 553f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 554f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 555f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 556f2bbc96eSHarald Freudenberger return -EINVAL; 557f2bbc96eSHarald Freudenberger break; 55855d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 55955d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 56055d0a513SHarald Freudenberger return -EINVAL; 56155d0a513SHarald Freudenberger break; 562f2bbc96eSHarald Freudenberger default: 563f2bbc96eSHarald Freudenberger return -EINVAL; 564f2bbc96eSHarald Freudenberger } 565f2bbc96eSHarald Freudenberger switch (ksize) { 566f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 567f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 568f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 569f2bbc96eSHarald Freudenberger break; 570f2bbc96eSHarald Freudenberger default: 571f2bbc96eSHarald Freudenberger return -EINVAL; 572f2bbc96eSHarald Freudenberger } 573f2bbc96eSHarald Freudenberger 574f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 575f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 576f2bbc96eSHarald Freudenberger card = apqns[i].card; 577f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 57855d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 57955d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, ksize, kflags, 58055d0a513SHarald Freudenberger keybuf, keybufsize); 58155d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 582f2bbc96eSHarald Freudenberger rc = cca_genseckey(card, dom, ksize, keybuf); 583f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 584f2bbc96eSHarald Freudenberger } else /* TOKVER_CCA_VLSC */ 585f2bbc96eSHarald Freudenberger rc = cca_gencipherkey(card, dom, ksize, kflags, 586f2bbc96eSHarald Freudenberger keybuf, keybufsize); 587f2bbc96eSHarald Freudenberger if (rc == 0) 588f2bbc96eSHarald Freudenberger break; 589f2bbc96eSHarald Freudenberger } 590f2bbc96eSHarald Freudenberger 591f2bbc96eSHarald Freudenberger return rc; 592f2bbc96eSHarald Freudenberger } 593f2bbc96eSHarald Freudenberger 594f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 595f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 596f2bbc96eSHarald Freudenberger u32 kflags, const u8 *clrkey, 597f2bbc96eSHarald Freudenberger u8 *keybuf, size_t *keybufsize) 598f2bbc96eSHarald Freudenberger { 599f2bbc96eSHarald Freudenberger int i, card, dom, rc; 600f2bbc96eSHarald Freudenberger 601f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 602f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 603f2bbc96eSHarald Freudenberger return -EINVAL; 604f2bbc96eSHarald Freudenberger 605f2bbc96eSHarald Freudenberger /* check key type and size */ 606f2bbc96eSHarald Freudenberger switch (ktype) { 607f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 608f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 609f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 610f2bbc96eSHarald Freudenberger return -EINVAL; 611f2bbc96eSHarald Freudenberger break; 61255d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 61355d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 61455d0a513SHarald Freudenberger return -EINVAL; 61555d0a513SHarald Freudenberger break; 616f2bbc96eSHarald Freudenberger default: 617f2bbc96eSHarald Freudenberger return -EINVAL; 618f2bbc96eSHarald Freudenberger } 619f2bbc96eSHarald Freudenberger switch (ksize) { 620f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 621f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 622f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 623f2bbc96eSHarald Freudenberger break; 624f2bbc96eSHarald Freudenberger default: 625f2bbc96eSHarald Freudenberger return -EINVAL; 626f2bbc96eSHarald Freudenberger } 627f2bbc96eSHarald Freudenberger 628f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 629f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 630f2bbc96eSHarald Freudenberger card = apqns[i].card; 631f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 63255d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 63355d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, ksize, kflags, 63455d0a513SHarald Freudenberger clrkey, keybuf, keybufsize); 63555d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 636f2bbc96eSHarald Freudenberger rc = cca_clr2seckey(card, dom, ksize, 637f2bbc96eSHarald Freudenberger clrkey, keybuf); 638f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 639f2bbc96eSHarald Freudenberger } else /* TOKVER_CCA_VLSC */ 640f2bbc96eSHarald Freudenberger rc = cca_clr2cipherkey(card, dom, ksize, kflags, 641f2bbc96eSHarald Freudenberger clrkey, keybuf, keybufsize); 642f2bbc96eSHarald Freudenberger if (rc == 0) 643f2bbc96eSHarald Freudenberger break; 644f2bbc96eSHarald Freudenberger } 645f2bbc96eSHarald Freudenberger 646f2bbc96eSHarald Freudenberger return rc; 647f2bbc96eSHarald Freudenberger } 648f2bbc96eSHarald Freudenberger 649f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen, 650f2bbc96eSHarald Freudenberger u16 *cardnr, u16 *domain, 651f2bbc96eSHarald Freudenberger enum pkey_key_type *ktype, 652f2bbc96eSHarald Freudenberger enum pkey_key_size *ksize, u32 *flags) 653f2bbc96eSHarald Freudenberger { 654f2bbc96eSHarald Freudenberger int rc; 655f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 656f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 657f2bbc96eSHarald Freudenberger 65855d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 659f2bbc96eSHarald Freudenberger return -EINVAL; 660f2bbc96eSHarald Freudenberger 66155d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL 66255d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_AES) { 663f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 664f2bbc96eSHarald Freudenberger 665f2bbc96eSHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 666f2bbc96eSHarald Freudenberger if (rc) 667f2bbc96eSHarald Freudenberger goto out; 668f2bbc96eSHarald Freudenberger if (ktype) 669f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_DATA; 670f2bbc96eSHarald Freudenberger if (ksize) 671f2bbc96eSHarald Freudenberger *ksize = (enum pkey_key_size) t->bitsize; 672f2bbc96eSHarald Freudenberger 673f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 67432ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); 675f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 676f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 677f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 678f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 679f2bbc96eSHarald Freudenberger *cardnr, *domain, 68032ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, 68132ca04bbSHarald Freudenberger 0, t->mkvp, 1); 682f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 683f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 684f2bbc96eSHarald Freudenberger } 685f2bbc96eSHarald Freudenberger if (rc) 686f2bbc96eSHarald Freudenberger goto out; 687f2bbc96eSHarald Freudenberger 688f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 689f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 690f2bbc96eSHarald Freudenberger 69155d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL 69255d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_VLSC) { 693f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 694f2bbc96eSHarald Freudenberger 695f2bbc96eSHarald Freudenberger rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 696f2bbc96eSHarald Freudenberger if (rc) 697f2bbc96eSHarald Freudenberger goto out; 698f2bbc96eSHarald Freudenberger if (ktype) 699f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_CIPHER; 700f2bbc96eSHarald Freudenberger if (ksize) { 701f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_UNKNOWN; 702f2bbc96eSHarald Freudenberger if (!t->plfver && t->wpllen == 512) 703f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_128; 704f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 705f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_192; 706f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 707f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_256; 708f2bbc96eSHarald Freudenberger } 709f2bbc96eSHarald Freudenberger 710f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 71132ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); 712f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 713f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 714f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 715f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 716f2bbc96eSHarald Freudenberger *cardnr, *domain, 71732ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, 71832ca04bbSHarald Freudenberger 0, t->mkvp0, 1); 719f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 720f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 721f2bbc96eSHarald Freudenberger } 722f2bbc96eSHarald Freudenberger if (rc) 723f2bbc96eSHarald Freudenberger goto out; 724f2bbc96eSHarald Freudenberger 725f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 726f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 727f2bbc96eSHarald Freudenberger 72855d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA 72955d0a513SHarald Freudenberger && hdr->version == TOKVER_EP11_AES) { 73055d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 73155d0a513SHarald Freudenberger 732fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 73355d0a513SHarald Freudenberger if (rc) 73455d0a513SHarald Freudenberger goto out; 73555d0a513SHarald Freudenberger if (ktype) 73655d0a513SHarald Freudenberger *ktype = PKEY_TYPE_EP11; 73755d0a513SHarald Freudenberger if (ksize) 73855d0a513SHarald Freudenberger *ksize = kb->head.keybitlen; 73955d0a513SHarald Freudenberger 74055d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 74155d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 74255d0a513SHarald Freudenberger if (rc) 74355d0a513SHarald Freudenberger goto out; 74455d0a513SHarald Freudenberger 74555d0a513SHarald Freudenberger if (flags) 74655d0a513SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 74755d0a513SHarald Freudenberger 74855d0a513SHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 74955d0a513SHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 75055d0a513SHarald Freudenberger 751f2bbc96eSHarald Freudenberger } else 752f2bbc96eSHarald Freudenberger rc = -EINVAL; 753f2bbc96eSHarald Freudenberger 754f2bbc96eSHarald Freudenberger out: 755f2bbc96eSHarald Freudenberger kfree(_apqns); 756f2bbc96eSHarald Freudenberger return rc; 757f2bbc96eSHarald Freudenberger } 758f2bbc96eSHarald Freudenberger 759f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 760f2bbc96eSHarald Freudenberger const u8 *key, size_t keylen, 761f2bbc96eSHarald Freudenberger struct pkey_protkey *pkey) 762f2bbc96eSHarald Freudenberger { 763f2bbc96eSHarald Freudenberger int i, card, dom, rc; 764f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 765f2bbc96eSHarald Freudenberger 766f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 767f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 768f2bbc96eSHarald Freudenberger return -EINVAL; 769f2bbc96eSHarald Freudenberger 770fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 771fb1136d6SIngo Franzki return -EINVAL; 772fb1136d6SIngo Franzki 77355d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL) { 77455d0a513SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 775f2bbc96eSHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 776f2bbc96eSHarald Freudenberger return -EINVAL; 777f2bbc96eSHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 778f2bbc96eSHarald Freudenberger return -EINVAL; 77955d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 780f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 781f2bbc96eSHarald Freudenberger return -EINVAL; 782f2bbc96eSHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 783f2bbc96eSHarald Freudenberger return -EINVAL; 78455d0a513SHarald Freudenberger } else { 785f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 786f2bbc96eSHarald Freudenberger __func__, hdr->version); 787fb1136d6SIngo Franzki return -EINVAL; 788fb1136d6SIngo Franzki } 78955d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 79055d0a513SHarald Freudenberger if (hdr->version == TOKVER_EP11_AES) { 79155d0a513SHarald Freudenberger if (keylen < sizeof(struct ep11keyblob)) 79255d0a513SHarald Freudenberger return -EINVAL; 793fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 79455d0a513SHarald Freudenberger return -EINVAL; 79555d0a513SHarald Freudenberger } else { 79655d0a513SHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, pkey); 79755d0a513SHarald Freudenberger } 79855d0a513SHarald Freudenberger } else { 799f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 800f2bbc96eSHarald Freudenberger __func__, hdr->type); 801f2bbc96eSHarald Freudenberger return -EINVAL; 802fb1136d6SIngo Franzki } 803f2bbc96eSHarald Freudenberger 804f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 805f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 806f2bbc96eSHarald Freudenberger card = apqns[i].card; 807f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 80855d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL 80955d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_AES) 810f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(card, dom, key, pkey->protkey, 811f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 81255d0a513SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL 81355d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_VLSC) 814f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, pkey->protkey, 815f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 81655d0a513SHarald Freudenberger else { /* EP11 AES secure key blob */ 81755d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) key; 81855d0a513SHarald Freudenberger 819fa6999e3SHarald Freudenberger pkey->len = sizeof(pkey->protkey); 820fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 82155d0a513SHarald Freudenberger pkey->protkey, &pkey->len, 82255d0a513SHarald Freudenberger &pkey->type); 82355d0a513SHarald Freudenberger } 824f2bbc96eSHarald Freudenberger if (rc == 0) 825f2bbc96eSHarald Freudenberger break; 826f2bbc96eSHarald Freudenberger } 827f2bbc96eSHarald Freudenberger 828f2bbc96eSHarald Freudenberger return rc; 829f2bbc96eSHarald Freudenberger } 830f2bbc96eSHarald Freudenberger 831f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 832f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 833f2bbc96eSHarald Freudenberger { 83475be6b98STianjia Zhang int rc; 835f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 836f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 837f2bbc96eSHarald Freudenberger 83855d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || flags == 0) 839f2bbc96eSHarald Freudenberger return -EINVAL; 840f2bbc96eSHarald Freudenberger 841fa6999e3SHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA 842fa6999e3SHarald Freudenberger && (hdr->version == TOKVER_EP11_AES_WITH_HEADER 843fa6999e3SHarald Freudenberger || hdr->version == TOKVER_EP11_ECC_WITH_HEADER) 844fa6999e3SHarald Freudenberger && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 845fa6999e3SHarald Freudenberger int minhwtype = 0, api = 0; 846fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) 847fa6999e3SHarald Freudenberger (key + sizeof(struct ep11kblob_header)); 848fa6999e3SHarald Freudenberger 849fa6999e3SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 850fa6999e3SHarald Freudenberger return -EINVAL; 851fa6999e3SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 852fa6999e3SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 853fa6999e3SHarald Freudenberger api = EP11_API_V; 854fa6999e3SHarald Freudenberger } 855fa6999e3SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 856fa6999e3SHarald Freudenberger minhwtype, api, kb->wkvp); 857fa6999e3SHarald Freudenberger if (rc) 858fa6999e3SHarald Freudenberger goto out; 859fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA 860fa6999e3SHarald Freudenberger && hdr->version == TOKVER_EP11_AES 861fa6999e3SHarald Freudenberger && is_ep11_keyblob(key)) { 86255d0a513SHarald Freudenberger int minhwtype = 0, api = 0; 86355d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) key; 86455d0a513SHarald Freudenberger 86555d0a513SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 86655d0a513SHarald Freudenberger return -EINVAL; 86755d0a513SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 86855d0a513SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 86955d0a513SHarald Freudenberger api = EP11_API_V; 87055d0a513SHarald Freudenberger } 87155d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 87255d0a513SHarald Freudenberger minhwtype, api, kb->wkvp); 87355d0a513SHarald Freudenberger if (rc) 87455d0a513SHarald Freudenberger goto out; 87555d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 876f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 877f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 878f2bbc96eSHarald Freudenberger 879f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 880f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 881f2bbc96eSHarald Freudenberger 882f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 883f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp; 884f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 885f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp; 88655d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 887f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 888f2bbc96eSHarald Freudenberger 889f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 890f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 891f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp0; 892f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 893f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp0; 89455d0a513SHarald Freudenberger } else { 89555d0a513SHarald Freudenberger /* unknown cca internal token type */ 89655d0a513SHarald Freudenberger return -EINVAL; 897f2bbc96eSHarald Freudenberger } 898f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 89932ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 90032ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 901f2bbc96eSHarald Freudenberger if (rc) 902f2bbc96eSHarald Freudenberger goto out; 903fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 904fa6999e3SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 905fa6999e3SHarald Freudenberger struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; 906fa6999e3SHarald Freudenberger 907fa6999e3SHarald Freudenberger if (t->secid == 0x20) { 908fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 909fa6999e3SHarald Freudenberger cur_mkvp = t->mkvp; 910fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 911fa6999e3SHarald Freudenberger old_mkvp = t->mkvp; 912fa6999e3SHarald Freudenberger } else { 913fa6999e3SHarald Freudenberger /* unknown cca internal 2 token type */ 914fa6999e3SHarald Freudenberger return -EINVAL; 915fa6999e3SHarald Freudenberger } 916fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 917fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 918fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 919fa6999e3SHarald Freudenberger if (rc) 920fa6999e3SHarald Freudenberger goto out; 92155d0a513SHarald Freudenberger } else 92255d0a513SHarald Freudenberger return -EINVAL; 92355d0a513SHarald Freudenberger 924f2bbc96eSHarald Freudenberger if (apqns) { 925f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 926f2bbc96eSHarald Freudenberger rc = -ENOSPC; 927f2bbc96eSHarald Freudenberger else 928f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 929f2bbc96eSHarald Freudenberger } 930f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 931f2bbc96eSHarald Freudenberger 932f2bbc96eSHarald Freudenberger out: 933f2bbc96eSHarald Freudenberger kfree(_apqns); 934f2bbc96eSHarald Freudenberger return rc; 935f2bbc96eSHarald Freudenberger } 936f2bbc96eSHarald Freudenberger 937f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype, 938f2bbc96eSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 939f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 940f2bbc96eSHarald Freudenberger { 94175be6b98STianjia Zhang int rc; 942f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 943f2bbc96eSHarald Freudenberger 944f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 945f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 946f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 947f2bbc96eSHarald Freudenberger 948f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 949f2bbc96eSHarald Freudenberger cur_mkvp = *((u64 *) cur_mkvp); 950f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 951f2bbc96eSHarald Freudenberger old_mkvp = *((u64 *) alt_mkvp); 952f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 953f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 954f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 95532ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 95632ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 957f2bbc96eSHarald Freudenberger if (rc) 958f2bbc96eSHarald Freudenberger goto out; 959fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_ECC) { 960fa6999e3SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 961fa6999e3SHarald Freudenberger 962fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 963fa6999e3SHarald Freudenberger cur_mkvp = *((u64 *) cur_mkvp); 964fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 965fa6999e3SHarald Freudenberger old_mkvp = *((u64 *) alt_mkvp); 966fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 967fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 968fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 969fa6999e3SHarald Freudenberger if (rc) 970fa6999e3SHarald Freudenberger goto out; 971fa6999e3SHarald Freudenberger 972fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_EP11 || 973fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_AES || 974fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_ECC) { 97555d0a513SHarald Freudenberger u8 *wkvp = NULL; 97655d0a513SHarald Freudenberger 97755d0a513SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 97855d0a513SHarald Freudenberger wkvp = cur_mkvp; 97955d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 98055d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, wkvp); 98155d0a513SHarald Freudenberger if (rc) 98255d0a513SHarald Freudenberger goto out; 98355d0a513SHarald Freudenberger 98455d0a513SHarald Freudenberger } else 98555d0a513SHarald Freudenberger return -EINVAL; 98655d0a513SHarald Freudenberger 987f2bbc96eSHarald Freudenberger if (apqns) { 988f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 989f2bbc96eSHarald Freudenberger rc = -ENOSPC; 990f2bbc96eSHarald Freudenberger else 991f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 992f2bbc96eSHarald Freudenberger } 993f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 994f2bbc96eSHarald Freudenberger 995f2bbc96eSHarald Freudenberger out: 996f2bbc96eSHarald Freudenberger kfree(_apqns); 997f2bbc96eSHarald Freudenberger return rc; 998f2bbc96eSHarald Freudenberger } 999fb1136d6SIngo Franzki 1000fa6999e3SHarald Freudenberger static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, 1001fa6999e3SHarald Freudenberger const u8 *key, size_t keylen, u32 *protkeytype, 1002fa6999e3SHarald Freudenberger u8 *protkey, u32 *protkeylen) 1003fa6999e3SHarald Freudenberger { 1004fa6999e3SHarald Freudenberger int i, card, dom, rc; 1005fa6999e3SHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 1006fa6999e3SHarald Freudenberger 1007fa6999e3SHarald Freudenberger /* check for at least one apqn given */ 1008fa6999e3SHarald Freudenberger if (!apqns || !nr_apqns) 1009fa6999e3SHarald Freudenberger return -EINVAL; 1010fa6999e3SHarald Freudenberger 1011fa6999e3SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 1012fa6999e3SHarald Freudenberger return -EINVAL; 1013fa6999e3SHarald Freudenberger 1014fa6999e3SHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA 1015fa6999e3SHarald Freudenberger && hdr->version == TOKVER_EP11_AES_WITH_HEADER 1016fa6999e3SHarald Freudenberger && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1017fa6999e3SHarald Freudenberger /* EP11 AES key blob with header */ 1018fa6999e3SHarald Freudenberger if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1)) 1019fa6999e3SHarald Freudenberger return -EINVAL; 1020fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA 1021fa6999e3SHarald Freudenberger && hdr->version == TOKVER_EP11_ECC_WITH_HEADER 1022fa6999e3SHarald Freudenberger && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1023fa6999e3SHarald Freudenberger /* EP11 ECC key blob with header */ 1024fa6999e3SHarald Freudenberger if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1)) 1025fa6999e3SHarald Freudenberger return -EINVAL; 1026fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA 1027fa6999e3SHarald Freudenberger && hdr->version == TOKVER_EP11_AES 1028fa6999e3SHarald Freudenberger && is_ep11_keyblob(key)) { 1029fa6999e3SHarald Freudenberger /* EP11 AES key blob with header in session field */ 1030fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 1031fa6999e3SHarald Freudenberger return -EINVAL; 1032fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 1033fa6999e3SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 1034fa6999e3SHarald Freudenberger /* CCA AES data key */ 1035fa6999e3SHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 1036fa6999e3SHarald Freudenberger return -EINVAL; 1037fa6999e3SHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 1038fa6999e3SHarald Freudenberger return -EINVAL; 1039fa6999e3SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1040fa6999e3SHarald Freudenberger /* CCA AES cipher key */ 1041fa6999e3SHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 1042fa6999e3SHarald Freudenberger return -EINVAL; 1043fa6999e3SHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 1044fa6999e3SHarald Freudenberger return -EINVAL; 1045fa6999e3SHarald Freudenberger } else { 1046fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 1047fa6999e3SHarald Freudenberger __func__, hdr->version); 1048fa6999e3SHarald Freudenberger return -EINVAL; 1049fa6999e3SHarald Freudenberger } 1050fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1051fa6999e3SHarald Freudenberger /* CCA ECC (private) key */ 1052fa6999e3SHarald Freudenberger if (keylen < sizeof(struct eccprivkeytoken)) 1053fa6999e3SHarald Freudenberger return -EINVAL; 1054fa6999e3SHarald Freudenberger if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) 1055fa6999e3SHarald Freudenberger return -EINVAL; 1056fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 1057fa6999e3SHarald Freudenberger struct pkey_protkey pkey; 1058fa6999e3SHarald Freudenberger 1059fa6999e3SHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, &pkey); 1060fa6999e3SHarald Freudenberger if (rc) 1061fa6999e3SHarald Freudenberger return rc; 1062fa6999e3SHarald Freudenberger memcpy(protkey, pkey.protkey, pkey.len); 1063fa6999e3SHarald Freudenberger *protkeylen = pkey.len; 1064fa6999e3SHarald Freudenberger *protkeytype = pkey.type; 1065fa6999e3SHarald Freudenberger return 0; 1066fa6999e3SHarald Freudenberger } else { 1067fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 1068fa6999e3SHarald Freudenberger __func__, hdr->type); 1069fa6999e3SHarald Freudenberger return -EINVAL; 1070fa6999e3SHarald Freudenberger } 1071fa6999e3SHarald Freudenberger 1072fa6999e3SHarald Freudenberger /* simple try all apqns from the list */ 1073fa6999e3SHarald Freudenberger for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 1074fa6999e3SHarald Freudenberger card = apqns[i].card; 1075fa6999e3SHarald Freudenberger dom = apqns[i].domain; 1076fa6999e3SHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA 1077fa6999e3SHarald Freudenberger && (hdr->version == TOKVER_EP11_AES_WITH_HEADER 1078fa6999e3SHarald Freudenberger || hdr->version == TOKVER_EP11_ECC_WITH_HEADER) 1079fa6999e3SHarald Freudenberger && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) 1080fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1081fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 1082fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_NON_CCA 1083fa6999e3SHarald Freudenberger && hdr->version == TOKVER_EP11_AES 1084fa6999e3SHarald Freudenberger && is_ep11_keyblob(key)) 1085fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1086fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 1087fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1088fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_AES) 1089fa6999e3SHarald Freudenberger rc = cca_sec2protkey(card, dom, key, protkey, 1090fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1091fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1092fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) 1093fa6999e3SHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, protkey, 1094fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1095fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) 1096fa6999e3SHarald Freudenberger rc = cca_ecc2protkey(card, dom, key, protkey, 1097fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1098fa6999e3SHarald Freudenberger else 1099fa6999e3SHarald Freudenberger return -EINVAL; 1100fa6999e3SHarald Freudenberger } 1101fa6999e3SHarald Freudenberger 1102fa6999e3SHarald Freudenberger return rc; 1103fa6999e3SHarald Freudenberger } 1104fa6999e3SHarald Freudenberger 1105fb1136d6SIngo Franzki /* 1106e80d4af0SHarald Freudenberger * File io functions 1107e80d4af0SHarald Freudenberger */ 1108e80d4af0SHarald Freudenberger 1109f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen) 1110f2bbc96eSHarald Freudenberger { 1111f2bbc96eSHarald Freudenberger if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) 1112f2bbc96eSHarald Freudenberger return ERR_PTR(-EINVAL); 1113f2bbc96eSHarald Freudenberger 11148b57e7c8SMarkus Elfring return memdup_user(ukey, keylen); 1115f2bbc96eSHarald Freudenberger } 1116f2bbc96eSHarald Freudenberger 1117f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 1118f2bbc96eSHarald Freudenberger { 11198b57e7c8SMarkus Elfring if (!uapqns || nr_apqns == 0) 11208b57e7c8SMarkus Elfring return NULL; 1121f2bbc96eSHarald Freudenberger 11228b57e7c8SMarkus Elfring return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); 1123f2bbc96eSHarald Freudenberger } 1124f2bbc96eSHarald Freudenberger 1125e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 1126e80d4af0SHarald Freudenberger unsigned long arg) 1127e80d4af0SHarald Freudenberger { 1128e80d4af0SHarald Freudenberger int rc; 1129e80d4af0SHarald Freudenberger 1130e80d4af0SHarald Freudenberger switch (cmd) { 1131e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1132e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *) arg; 1133e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1134e80d4af0SHarald Freudenberger 1135e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1136e80d4af0SHarald Freudenberger return -EFAULT; 1137efc598e6SHarald Freudenberger rc = cca_genseckey(kgs.cardnr, kgs.domain, 1138efc598e6SHarald Freudenberger kgs.keytype, kgs.seckey.seckey); 1139efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 1140e80d4af0SHarald Freudenberger if (rc) 1141e80d4af0SHarald Freudenberger break; 1142e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1143e80d4af0SHarald Freudenberger return -EFAULT; 1144e80d4af0SHarald Freudenberger break; 1145e80d4af0SHarald Freudenberger } 1146e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1147e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *) arg; 1148e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1149e80d4af0SHarald Freudenberger 1150e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1151e80d4af0SHarald Freudenberger return -EFAULT; 1152efc598e6SHarald Freudenberger rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1153efc598e6SHarald Freudenberger kcs.clrkey.clrkey, kcs.seckey.seckey); 1154efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 1155e80d4af0SHarald Freudenberger if (rc) 1156e80d4af0SHarald Freudenberger break; 1157e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1158e80d4af0SHarald Freudenberger return -EFAULT; 1159e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1160e80d4af0SHarald Freudenberger break; 1161e80d4af0SHarald Freudenberger } 1162e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1163e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *) arg; 1164e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1165e80d4af0SHarald Freudenberger 1166e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1167e80d4af0SHarald Freudenberger return -EFAULT; 1168efc598e6SHarald Freudenberger rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 1169efc598e6SHarald Freudenberger ksp.seckey.seckey, ksp.protkey.protkey, 1170aab73d27SHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1171efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 1172e80d4af0SHarald Freudenberger if (rc) 1173e80d4af0SHarald Freudenberger break; 1174e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1175e80d4af0SHarald Freudenberger return -EFAULT; 1176e80d4af0SHarald Freudenberger break; 1177e80d4af0SHarald Freudenberger } 1178e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1179e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *) arg; 1180e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1181e80d4af0SHarald Freudenberger 1182e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1183e80d4af0SHarald Freudenberger return -EFAULT; 1184e80d4af0SHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, 1185e80d4af0SHarald Freudenberger &kcp.clrkey, &kcp.protkey); 1186ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1187e80d4af0SHarald Freudenberger if (rc) 1188e80d4af0SHarald Freudenberger break; 1189e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1190e80d4af0SHarald Freudenberger return -EFAULT; 1191e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1192e80d4af0SHarald Freudenberger break; 1193e80d4af0SHarald Freudenberger } 1194e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1195e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *) arg; 1196e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1197e80d4af0SHarald Freudenberger 1198e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1199e80d4af0SHarald Freudenberger return -EFAULT; 1200efc598e6SHarald Freudenberger rc = cca_findcard(kfc.seckey.seckey, 1201e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1202efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 1203efc598e6SHarald Freudenberger if (rc < 0) 1204e80d4af0SHarald Freudenberger break; 1205e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1206e80d4af0SHarald Freudenberger return -EFAULT; 1207e80d4af0SHarald Freudenberger break; 1208e80d4af0SHarald Freudenberger } 1209e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1210e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *) arg; 1211e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1212e80d4af0SHarald Freudenberger 1213e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1214e80d4af0SHarald Freudenberger return -EFAULT; 1215f2bbc96eSHarald Freudenberger rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey); 1216ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1217e80d4af0SHarald Freudenberger if (rc) 1218e80d4af0SHarald Freudenberger break; 1219e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1220e80d4af0SHarald Freudenberger return -EFAULT; 1221e80d4af0SHarald Freudenberger break; 1222e80d4af0SHarald Freudenberger } 1223e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1224e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *) arg; 1225e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1226e61a6134SHarald Freudenberger 1227e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1228e61a6134SHarald Freudenberger return -EFAULT; 1229e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1230e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1231ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1232e61a6134SHarald Freudenberger if (rc) 1233e61a6134SHarald Freudenberger break; 1234e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1235e61a6134SHarald Freudenberger return -EFAULT; 1236e61a6134SHarald Freudenberger break; 1237e61a6134SHarald Freudenberger } 1238a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1239a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *) arg; 1240a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1241a45a5c7dSIngo Franzki 1242a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1243a45a5c7dSIngo Franzki return -EFAULT; 1244a45a5c7dSIngo Franzki rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); 1245a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1246a45a5c7dSIngo Franzki if (rc) 1247a45a5c7dSIngo Franzki break; 1248a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1249a45a5c7dSIngo Franzki return -EFAULT; 1250a45a5c7dSIngo Franzki break; 1251a45a5c7dSIngo Franzki } 1252cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 1253cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *) arg; 1254cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 1255cb26b9ffSIngo Franzki 1256cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 1257cb26b9ffSIngo Franzki return -EFAULT; 1258cb26b9ffSIngo Franzki rc = pkey_verifyprotkey(&kvp.protkey); 1259cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 1260cb26b9ffSIngo Franzki break; 1261cb26b9ffSIngo Franzki } 1262fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 1263fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *) arg; 1264fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 1265183cb469SHarald Freudenberger u8 *kkey; 1266fb1136d6SIngo Franzki 1267fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 1268fb1136d6SIngo Franzki return -EFAULT; 1269f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1270f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1271f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1272fb1136d6SIngo Franzki rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); 1273fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 1274fb1136d6SIngo Franzki kfree(kkey); 1275fb1136d6SIngo Franzki if (rc) 1276fb1136d6SIngo Franzki break; 1277fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 1278fb1136d6SIngo Franzki return -EFAULT; 1279fb1136d6SIngo Franzki break; 1280fb1136d6SIngo Franzki } 1281f2bbc96eSHarald Freudenberger case PKEY_GENSECK2: { 1282f2bbc96eSHarald Freudenberger struct pkey_genseck2 __user *ugs = (void __user *) arg; 1283f2bbc96eSHarald Freudenberger struct pkey_genseck2 kgs; 1284f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1285f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1286f2bbc96eSHarald Freudenberger u8 *kkey; 1287f2bbc96eSHarald Freudenberger 1288f2bbc96eSHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1289f2bbc96eSHarald Freudenberger return -EFAULT; 1290f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 1291f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1292f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1293f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1294f2bbc96eSHarald Freudenberger if (!kkey) { 1295f2bbc96eSHarald Freudenberger kfree(apqns); 1296f2bbc96eSHarald Freudenberger return -ENOMEM; 1297f2bbc96eSHarald Freudenberger } 1298f2bbc96eSHarald Freudenberger rc = pkey_genseckey2(apqns, kgs.apqn_entries, 1299f2bbc96eSHarald Freudenberger kgs.type, kgs.size, kgs.keygenflags, 1300f2bbc96eSHarald Freudenberger kkey, &klen); 1301f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 1302f2bbc96eSHarald Freudenberger kfree(apqns); 1303f2bbc96eSHarald Freudenberger if (rc) { 1304f2bbc96eSHarald Freudenberger kfree(kkey); 1305f2bbc96eSHarald Freudenberger break; 1306f2bbc96eSHarald Freudenberger } 1307f2bbc96eSHarald Freudenberger if (kgs.key) { 1308f2bbc96eSHarald Freudenberger if (kgs.keylen < klen) { 1309f2bbc96eSHarald Freudenberger kfree(kkey); 1310f2bbc96eSHarald Freudenberger return -EINVAL; 1311f2bbc96eSHarald Freudenberger } 1312f2bbc96eSHarald Freudenberger if (copy_to_user(kgs.key, kkey, klen)) { 1313f2bbc96eSHarald Freudenberger kfree(kkey); 1314f2bbc96eSHarald Freudenberger return -EFAULT; 1315f2bbc96eSHarald Freudenberger } 1316f2bbc96eSHarald Freudenberger } 1317f2bbc96eSHarald Freudenberger kgs.keylen = klen; 1318f2bbc96eSHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1319f2bbc96eSHarald Freudenberger rc = -EFAULT; 1320f2bbc96eSHarald Freudenberger kfree(kkey); 1321f2bbc96eSHarald Freudenberger break; 1322f2bbc96eSHarald Freudenberger } 1323f2bbc96eSHarald Freudenberger case PKEY_CLR2SECK2: { 1324f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 __user *ucs = (void __user *) arg; 1325f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 kcs; 1326f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1327f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1328f2bbc96eSHarald Freudenberger u8 *kkey; 1329f2bbc96eSHarald Freudenberger 1330f2bbc96eSHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1331f2bbc96eSHarald Freudenberger return -EFAULT; 1332f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 1333f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1334f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1335f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1336f2bbc96eSHarald Freudenberger if (!kkey) { 1337f2bbc96eSHarald Freudenberger kfree(apqns); 1338f2bbc96eSHarald Freudenberger return -ENOMEM; 1339f2bbc96eSHarald Freudenberger } 1340f2bbc96eSHarald Freudenberger rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 1341f2bbc96eSHarald Freudenberger kcs.type, kcs.size, kcs.keygenflags, 1342f2bbc96eSHarald Freudenberger kcs.clrkey.clrkey, kkey, &klen); 1343f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 1344f2bbc96eSHarald Freudenberger kfree(apqns); 1345f2bbc96eSHarald Freudenberger if (rc) { 1346f2bbc96eSHarald Freudenberger kfree(kkey); 1347f2bbc96eSHarald Freudenberger break; 1348f2bbc96eSHarald Freudenberger } 1349f2bbc96eSHarald Freudenberger if (kcs.key) { 1350f2bbc96eSHarald Freudenberger if (kcs.keylen < klen) { 1351f2bbc96eSHarald Freudenberger kfree(kkey); 1352f2bbc96eSHarald Freudenberger return -EINVAL; 1353f2bbc96eSHarald Freudenberger } 1354f2bbc96eSHarald Freudenberger if (copy_to_user(kcs.key, kkey, klen)) { 1355f2bbc96eSHarald Freudenberger kfree(kkey); 1356f2bbc96eSHarald Freudenberger return -EFAULT; 1357f2bbc96eSHarald Freudenberger } 1358f2bbc96eSHarald Freudenberger } 1359f2bbc96eSHarald Freudenberger kcs.keylen = klen; 1360f2bbc96eSHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1361f2bbc96eSHarald Freudenberger rc = -EFAULT; 1362f2bbc96eSHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1363f2bbc96eSHarald Freudenberger kfree(kkey); 1364f2bbc96eSHarald Freudenberger break; 1365f2bbc96eSHarald Freudenberger } 1366f2bbc96eSHarald Freudenberger case PKEY_VERIFYKEY2: { 1367f2bbc96eSHarald Freudenberger struct pkey_verifykey2 __user *uvk = (void __user *) arg; 1368f2bbc96eSHarald Freudenberger struct pkey_verifykey2 kvk; 1369f2bbc96eSHarald Freudenberger u8 *kkey; 1370f2bbc96eSHarald Freudenberger 1371f2bbc96eSHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1372f2bbc96eSHarald Freudenberger return -EFAULT; 1373f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kvk.key, kvk.keylen); 1374f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1375f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1376f2bbc96eSHarald Freudenberger rc = pkey_verifykey2(kkey, kvk.keylen, 1377f2bbc96eSHarald Freudenberger &kvk.cardnr, &kvk.domain, 1378f2bbc96eSHarald Freudenberger &kvk.type, &kvk.size, &kvk.flags); 1379f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 1380f2bbc96eSHarald Freudenberger kfree(kkey); 1381f2bbc96eSHarald Freudenberger if (rc) 1382f2bbc96eSHarald Freudenberger break; 1383f2bbc96eSHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1384f2bbc96eSHarald Freudenberger return -EFAULT; 1385f2bbc96eSHarald Freudenberger break; 1386f2bbc96eSHarald Freudenberger } 1387f2bbc96eSHarald Freudenberger case PKEY_KBLOB2PROTK2: { 1388f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 __user *utp = (void __user *) arg; 1389f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 ktp; 1390f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1391f2bbc96eSHarald Freudenberger u8 *kkey; 1392f2bbc96eSHarald Freudenberger 1393f2bbc96eSHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1394f2bbc96eSHarald Freudenberger return -EFAULT; 1395f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1396f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1397f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1398f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1399f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1400f2bbc96eSHarald Freudenberger kfree(apqns); 1401f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1402f2bbc96eSHarald Freudenberger } 1403f2bbc96eSHarald Freudenberger rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 1404f2bbc96eSHarald Freudenberger kkey, ktp.keylen, &ktp.protkey); 1405f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 1406f2bbc96eSHarald Freudenberger kfree(apqns); 1407f2bbc96eSHarald Freudenberger kfree(kkey); 1408f2bbc96eSHarald Freudenberger if (rc) 1409f2bbc96eSHarald Freudenberger break; 1410f2bbc96eSHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1411f2bbc96eSHarald Freudenberger return -EFAULT; 1412f2bbc96eSHarald Freudenberger break; 1413f2bbc96eSHarald Freudenberger } 1414f2bbc96eSHarald Freudenberger case PKEY_APQNS4K: { 1415f2bbc96eSHarald Freudenberger struct pkey_apqns4key __user *uak = (void __user *) arg; 1416f2bbc96eSHarald Freudenberger struct pkey_apqns4key kak; 1417f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1418f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1419f2bbc96eSHarald Freudenberger u8 *kkey; 1420f2bbc96eSHarald Freudenberger 1421f2bbc96eSHarald Freudenberger if (copy_from_user(&kak, uak, sizeof(kak))) 1422f2bbc96eSHarald Freudenberger return -EFAULT; 1423f2bbc96eSHarald Freudenberger nr_apqns = kak.apqn_entries; 1424f2bbc96eSHarald Freudenberger if (nr_apqns) { 1425f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1426f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1427f2bbc96eSHarald Freudenberger GFP_KERNEL); 1428f2bbc96eSHarald Freudenberger if (!apqns) 1429f2bbc96eSHarald Freudenberger return -ENOMEM; 1430f2bbc96eSHarald Freudenberger } 1431f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kak.key, kak.keylen); 1432f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1433f2bbc96eSHarald Freudenberger kfree(apqns); 1434f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1435f2bbc96eSHarald Freudenberger } 1436f2bbc96eSHarald Freudenberger rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 1437f2bbc96eSHarald Freudenberger apqns, &nr_apqns); 1438f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 1439f2bbc96eSHarald Freudenberger kfree(kkey); 1440f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1441f2bbc96eSHarald Freudenberger kfree(apqns); 1442f2bbc96eSHarald Freudenberger break; 1443f2bbc96eSHarald Freudenberger } 1444f2bbc96eSHarald Freudenberger if (!rc && kak.apqns) { 1445f2bbc96eSHarald Freudenberger if (nr_apqns > kak.apqn_entries) { 1446f2bbc96eSHarald Freudenberger kfree(apqns); 1447f2bbc96eSHarald Freudenberger return -EINVAL; 1448f2bbc96eSHarald Freudenberger } 1449f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1450f2bbc96eSHarald Freudenberger if (len) { 1451f2bbc96eSHarald Freudenberger if (copy_to_user(kak.apqns, apqns, len)) { 1452f2bbc96eSHarald Freudenberger kfree(apqns); 1453f2bbc96eSHarald Freudenberger return -EFAULT; 1454f2bbc96eSHarald Freudenberger } 1455f2bbc96eSHarald Freudenberger } 1456f2bbc96eSHarald Freudenberger } 1457f2bbc96eSHarald Freudenberger kak.apqn_entries = nr_apqns; 1458f2bbc96eSHarald Freudenberger if (copy_to_user(uak, &kak, sizeof(kak))) 1459f2bbc96eSHarald Freudenberger rc = -EFAULT; 1460f2bbc96eSHarald Freudenberger kfree(apqns); 1461f2bbc96eSHarald Freudenberger break; 1462f2bbc96eSHarald Freudenberger } 1463f2bbc96eSHarald Freudenberger case PKEY_APQNS4KT: { 1464f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype __user *uat = (void __user *) arg; 1465f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype kat; 1466f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1467f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1468f2bbc96eSHarald Freudenberger 1469f2bbc96eSHarald Freudenberger if (copy_from_user(&kat, uat, sizeof(kat))) 1470f2bbc96eSHarald Freudenberger return -EFAULT; 1471f2bbc96eSHarald Freudenberger nr_apqns = kat.apqn_entries; 1472f2bbc96eSHarald Freudenberger if (nr_apqns) { 1473f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1474f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1475f2bbc96eSHarald Freudenberger GFP_KERNEL); 1476f2bbc96eSHarald Freudenberger if (!apqns) 1477f2bbc96eSHarald Freudenberger return -ENOMEM; 1478f2bbc96eSHarald Freudenberger } 1479f2bbc96eSHarald Freudenberger rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 1480f2bbc96eSHarald Freudenberger kat.flags, apqns, &nr_apqns); 1481f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 1482f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1483f2bbc96eSHarald Freudenberger kfree(apqns); 1484f2bbc96eSHarald Freudenberger break; 1485f2bbc96eSHarald Freudenberger } 1486f2bbc96eSHarald Freudenberger if (!rc && kat.apqns) { 1487f2bbc96eSHarald Freudenberger if (nr_apqns > kat.apqn_entries) { 1488f2bbc96eSHarald Freudenberger kfree(apqns); 1489f2bbc96eSHarald Freudenberger return -EINVAL; 1490f2bbc96eSHarald Freudenberger } 1491f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1492f2bbc96eSHarald Freudenberger if (len) { 1493f2bbc96eSHarald Freudenberger if (copy_to_user(kat.apqns, apqns, len)) { 1494f2bbc96eSHarald Freudenberger kfree(apqns); 1495f2bbc96eSHarald Freudenberger return -EFAULT; 1496f2bbc96eSHarald Freudenberger } 1497f2bbc96eSHarald Freudenberger } 1498f2bbc96eSHarald Freudenberger } 1499f2bbc96eSHarald Freudenberger kat.apqn_entries = nr_apqns; 1500f2bbc96eSHarald Freudenberger if (copy_to_user(uat, &kat, sizeof(kat))) 1501f2bbc96eSHarald Freudenberger rc = -EFAULT; 1502f2bbc96eSHarald Freudenberger kfree(apqns); 1503f2bbc96eSHarald Freudenberger break; 1504f2bbc96eSHarald Freudenberger } 1505fa6999e3SHarald Freudenberger case PKEY_KBLOB2PROTK3: { 1506fa6999e3SHarald Freudenberger struct pkey_kblob2pkey3 __user *utp = (void __user *) arg; 1507fa6999e3SHarald Freudenberger struct pkey_kblob2pkey3 ktp; 1508fa6999e3SHarald Freudenberger struct pkey_apqn *apqns = NULL; 1509fa6999e3SHarald Freudenberger u32 protkeylen = PROTKEYBLOBBUFSIZE; 1510fa6999e3SHarald Freudenberger u8 *kkey, *protkey; 1511fa6999e3SHarald Freudenberger 1512fa6999e3SHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1513fa6999e3SHarald Freudenberger return -EFAULT; 1514fa6999e3SHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1515fa6999e3SHarald Freudenberger if (IS_ERR(apqns)) 1516fa6999e3SHarald Freudenberger return PTR_ERR(apqns); 1517fa6999e3SHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1518fa6999e3SHarald Freudenberger if (IS_ERR(kkey)) { 1519fa6999e3SHarald Freudenberger kfree(apqns); 1520fa6999e3SHarald Freudenberger return PTR_ERR(kkey); 1521fa6999e3SHarald Freudenberger } 1522fa6999e3SHarald Freudenberger protkey = kmalloc(protkeylen, GFP_KERNEL); 1523fa6999e3SHarald Freudenberger if (!protkey) { 1524fa6999e3SHarald Freudenberger kfree(apqns); 1525fa6999e3SHarald Freudenberger kfree(kkey); 1526fa6999e3SHarald Freudenberger return -ENOMEM; 1527fa6999e3SHarald Freudenberger } 1528fa6999e3SHarald Freudenberger rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, kkey, 1529fa6999e3SHarald Freudenberger ktp.keylen, &ktp.pkeytype, 1530fa6999e3SHarald Freudenberger protkey, &protkeylen); 1531fa6999e3SHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); 1532fa6999e3SHarald Freudenberger kfree(apqns); 1533fa6999e3SHarald Freudenberger kfree(kkey); 1534fa6999e3SHarald Freudenberger if (rc) { 1535fa6999e3SHarald Freudenberger kfree(protkey); 1536fa6999e3SHarald Freudenberger break; 1537fa6999e3SHarald Freudenberger } 1538fa6999e3SHarald Freudenberger if (ktp.pkey && ktp.pkeylen) { 1539fa6999e3SHarald Freudenberger if (protkeylen > ktp.pkeylen) { 1540fa6999e3SHarald Freudenberger kfree(protkey); 1541fa6999e3SHarald Freudenberger return -EINVAL; 1542fa6999e3SHarald Freudenberger } 1543fa6999e3SHarald Freudenberger if (copy_to_user(ktp.pkey, protkey, protkeylen)) { 1544fa6999e3SHarald Freudenberger kfree(protkey); 1545fa6999e3SHarald Freudenberger return -EFAULT; 1546fa6999e3SHarald Freudenberger } 1547fa6999e3SHarald Freudenberger } 1548fa6999e3SHarald Freudenberger kfree(protkey); 1549fa6999e3SHarald Freudenberger ktp.pkeylen = protkeylen; 1550fa6999e3SHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1551fa6999e3SHarald Freudenberger return -EFAULT; 1552fa6999e3SHarald Freudenberger break; 1553fa6999e3SHarald Freudenberger } 1554e80d4af0SHarald Freudenberger default: 1555e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1556e80d4af0SHarald Freudenberger return -ENOTTY; 1557e80d4af0SHarald Freudenberger } 1558e80d4af0SHarald Freudenberger 1559e80d4af0SHarald Freudenberger return rc; 1560e80d4af0SHarald Freudenberger } 1561e80d4af0SHarald Freudenberger 1562e80d4af0SHarald Freudenberger /* 1563e80d4af0SHarald Freudenberger * Sysfs and file io operations 1564e80d4af0SHarald Freudenberger */ 1565d632c047SIngo Franzki 1566d632c047SIngo Franzki /* 1567d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1568d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1569d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1570d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1571d632c047SIngo Franzki */ 1572d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1573d632c047SIngo Franzki loff_t off, size_t count) 1574d632c047SIngo Franzki { 1575d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1576d632c047SIngo Franzki struct pkey_protkey protkey; 1577d632c047SIngo Franzki int rc; 1578d632c047SIngo Franzki 1579d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1580d632c047SIngo Franzki return -EINVAL; 1581d632c047SIngo Franzki if (is_xts) 1582d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1583d632c047SIngo Franzki return -EINVAL; 1584d632c047SIngo Franzki 1585d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1586d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1587d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1588d632c047SIngo Franzki protkeytoken.keytype = keytype; 1589d632c047SIngo Franzki 1590d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1591d632c047SIngo Franzki if (rc) 1592d632c047SIngo Franzki return rc; 1593d632c047SIngo Franzki 1594d632c047SIngo Franzki protkeytoken.len = protkey.len; 1595d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1596d632c047SIngo Franzki 1597d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1598d632c047SIngo Franzki 1599d632c047SIngo Franzki if (is_xts) { 1600d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1601d632c047SIngo Franzki if (rc) 1602d632c047SIngo Franzki return rc; 1603d632c047SIngo Franzki 1604d632c047SIngo Franzki protkeytoken.len = protkey.len; 1605d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1606d632c047SIngo Franzki 1607d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1608d632c047SIngo Franzki sizeof(protkeytoken)); 1609d632c047SIngo Franzki 1610d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1611d632c047SIngo Franzki } 1612d632c047SIngo Franzki 1613d632c047SIngo Franzki return sizeof(protkeytoken); 1614d632c047SIngo Franzki } 1615d632c047SIngo Franzki 1616d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1617d632c047SIngo Franzki struct kobject *kobj, 1618d632c047SIngo Franzki struct bin_attribute *attr, 1619d632c047SIngo Franzki char *buf, loff_t off, 1620d632c047SIngo Franzki size_t count) 1621d632c047SIngo Franzki { 1622d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1623d632c047SIngo Franzki off, count); 1624d632c047SIngo Franzki } 1625d632c047SIngo Franzki 1626d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1627d632c047SIngo Franzki struct kobject *kobj, 1628d632c047SIngo Franzki struct bin_attribute *attr, 1629d632c047SIngo Franzki char *buf, loff_t off, 1630d632c047SIngo Franzki size_t count) 1631d632c047SIngo Franzki { 1632d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1633d632c047SIngo Franzki off, count); 1634d632c047SIngo Franzki } 1635d632c047SIngo Franzki 1636d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1637d632c047SIngo Franzki struct kobject *kobj, 1638d632c047SIngo Franzki struct bin_attribute *attr, 1639d632c047SIngo Franzki char *buf, loff_t off, 1640d632c047SIngo Franzki size_t count) 1641d632c047SIngo Franzki { 1642d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1643d632c047SIngo Franzki off, count); 1644d632c047SIngo Franzki } 1645d632c047SIngo Franzki 1646d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1647d632c047SIngo Franzki struct kobject *kobj, 1648d632c047SIngo Franzki struct bin_attribute *attr, 1649d632c047SIngo Franzki char *buf, loff_t off, 1650d632c047SIngo Franzki size_t count) 1651d632c047SIngo Franzki { 1652d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1653d632c047SIngo Franzki off, count); 1654d632c047SIngo Franzki } 1655d632c047SIngo Franzki 1656d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1657d632c047SIngo Franzki struct kobject *kobj, 1658d632c047SIngo Franzki struct bin_attribute *attr, 1659d632c047SIngo Franzki char *buf, loff_t off, 1660d632c047SIngo Franzki size_t count) 1661d632c047SIngo Franzki { 1662d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1663d632c047SIngo Franzki off, count); 1664d632c047SIngo Franzki } 1665d632c047SIngo Franzki 1666d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1667d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1668d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1669d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1670d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1671d632c047SIngo Franzki 1672d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1673d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1674d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1675d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1676d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1677d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1678d632c047SIngo Franzki NULL 1679d632c047SIngo Franzki }; 1680d632c047SIngo Franzki 1681d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1682d632c047SIngo Franzki .name = "protkey", 1683d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1684d632c047SIngo Franzki }; 1685d632c047SIngo Franzki 1686af504452SIngo Franzki /* 1687af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1688af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1689af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1690af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1691af504452SIngo Franzki */ 1692af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1693af504452SIngo Franzki loff_t off, size_t count) 1694af504452SIngo Franzki { 1695af504452SIngo Franzki int rc; 1696efc598e6SHarald Freudenberger struct pkey_seckey *seckey = (struct pkey_seckey *) buf; 1697af504452SIngo Franzki 1698af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1699af504452SIngo Franzki return -EINVAL; 1700af504452SIngo Franzki if (is_xts) 1701af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1702af504452SIngo Franzki return -EINVAL; 1703af504452SIngo Franzki 1704efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1705af504452SIngo Franzki if (rc) 1706af504452SIngo Franzki return rc; 1707af504452SIngo Franzki 1708af504452SIngo Franzki if (is_xts) { 1709efc598e6SHarald Freudenberger seckey++; 1710efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1711af504452SIngo Franzki if (rc) 1712af504452SIngo Franzki return rc; 1713af504452SIngo Franzki 1714af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1715af504452SIngo Franzki } 1716af504452SIngo Franzki 1717af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1718af504452SIngo Franzki } 1719af504452SIngo Franzki 1720af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1721af504452SIngo Franzki struct kobject *kobj, 1722af504452SIngo Franzki struct bin_attribute *attr, 1723af504452SIngo Franzki char *buf, loff_t off, 1724af504452SIngo Franzki size_t count) 1725af504452SIngo Franzki { 1726af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1727af504452SIngo Franzki off, count); 1728af504452SIngo Franzki } 1729af504452SIngo Franzki 1730af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1731af504452SIngo Franzki struct kobject *kobj, 1732af504452SIngo Franzki struct bin_attribute *attr, 1733af504452SIngo Franzki char *buf, loff_t off, 1734af504452SIngo Franzki size_t count) 1735af504452SIngo Franzki { 1736af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1737af504452SIngo Franzki off, count); 1738af504452SIngo Franzki } 1739af504452SIngo Franzki 1740af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1741af504452SIngo Franzki struct kobject *kobj, 1742af504452SIngo Franzki struct bin_attribute *attr, 1743af504452SIngo Franzki char *buf, loff_t off, 1744af504452SIngo Franzki size_t count) 1745af504452SIngo Franzki { 1746af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1747af504452SIngo Franzki off, count); 1748af504452SIngo Franzki } 1749af504452SIngo Franzki 1750af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1751af504452SIngo Franzki struct kobject *kobj, 1752af504452SIngo Franzki struct bin_attribute *attr, 1753af504452SIngo Franzki char *buf, loff_t off, 1754af504452SIngo Franzki size_t count) 1755af504452SIngo Franzki { 1756af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1757af504452SIngo Franzki off, count); 1758af504452SIngo Franzki } 1759af504452SIngo Franzki 1760af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1761af504452SIngo Franzki struct kobject *kobj, 1762af504452SIngo Franzki struct bin_attribute *attr, 1763af504452SIngo Franzki char *buf, loff_t off, 1764af504452SIngo Franzki size_t count) 1765af504452SIngo Franzki { 1766af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1767af504452SIngo Franzki off, count); 1768af504452SIngo Franzki } 1769af504452SIngo Franzki 1770af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1771af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1772af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1773af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1774af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1775af504452SIngo Franzki 1776af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1777af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1778af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1779af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1780af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1781af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1782af504452SIngo Franzki NULL 1783af504452SIngo Franzki }; 1784af504452SIngo Franzki 1785af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1786af504452SIngo Franzki .name = "ccadata", 1787af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1788af504452SIngo Franzki }; 1789af504452SIngo Franzki 1790f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) 1791f71fee27SIngo Franzki 1792f71fee27SIngo Franzki /* 1793f71fee27SIngo Franzki * Sysfs attribute read function for all secure key ccacipher binary attributes. 1794f71fee27SIngo Franzki * The implementation can not deal with partial reads, because a new random 1795f71fee27SIngo Franzki * secure key blob is generated with each read. In case of partial reads 1796f71fee27SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1797f71fee27SIngo Franzki */ 1798f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, 1799f71fee27SIngo Franzki bool is_xts, char *buf, loff_t off, 1800f71fee27SIngo Franzki size_t count) 1801f71fee27SIngo Franzki { 180255d0a513SHarald Freudenberger int i, rc, card, dom; 180355d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 180455d0a513SHarald Freudenberger size_t keysize = CCACIPHERTOKENSIZE; 1805f71fee27SIngo Franzki 1806f71fee27SIngo Franzki if (off != 0 || count < CCACIPHERTOKENSIZE) 1807f71fee27SIngo Franzki return -EINVAL; 1808f71fee27SIngo Franzki if (is_xts) 1809f71fee27SIngo Franzki if (count < 2 * CCACIPHERTOKENSIZE) 1810f71fee27SIngo Franzki return -EINVAL; 1811f71fee27SIngo Franzki 181255d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 181355d0a513SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 181432ca04bbSHarald Freudenberger ZCRYPT_CEX6, 0, 0, 0, 0); 1815f71fee27SIngo Franzki if (rc) 1816f71fee27SIngo Franzki return rc; 181755d0a513SHarald Freudenberger 181855d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 181955d0a513SHarald Freudenberger 182055d0a513SHarald Freudenberger /* simple try all apqns from the list */ 182155d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 182255d0a513SHarald Freudenberger card = apqns[i] >> 16; 182355d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 182455d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 182555d0a513SHarald Freudenberger if (rc == 0) 182655d0a513SHarald Freudenberger break; 182755d0a513SHarald Freudenberger } 182855d0a513SHarald Freudenberger if (rc) 182955d0a513SHarald Freudenberger return rc; 1830f71fee27SIngo Franzki 1831f71fee27SIngo Franzki if (is_xts) { 1832f71fee27SIngo Franzki keysize = CCACIPHERTOKENSIZE; 183355d0a513SHarald Freudenberger buf += CCACIPHERTOKENSIZE; 183455d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 183555d0a513SHarald Freudenberger if (rc == 0) 1836f71fee27SIngo Franzki return 2 * CCACIPHERTOKENSIZE; 1837f71fee27SIngo Franzki } 1838f71fee27SIngo Franzki 1839f71fee27SIngo Franzki return CCACIPHERTOKENSIZE; 1840f71fee27SIngo Franzki } 1841f71fee27SIngo Franzki 1842f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp, 1843f71fee27SIngo Franzki struct kobject *kobj, 1844f71fee27SIngo Franzki struct bin_attribute *attr, 1845f71fee27SIngo Franzki char *buf, loff_t off, 1846f71fee27SIngo Franzki size_t count) 1847f71fee27SIngo Franzki { 1848f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 1849f71fee27SIngo Franzki off, count); 1850f71fee27SIngo Franzki } 1851f71fee27SIngo Franzki 1852f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp, 1853f71fee27SIngo Franzki struct kobject *kobj, 1854f71fee27SIngo Franzki struct bin_attribute *attr, 1855f71fee27SIngo Franzki char *buf, loff_t off, 1856f71fee27SIngo Franzki size_t count) 1857f71fee27SIngo Franzki { 1858f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 1859f71fee27SIngo Franzki off, count); 1860f71fee27SIngo Franzki } 1861f71fee27SIngo Franzki 1862f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp, 1863f71fee27SIngo Franzki struct kobject *kobj, 1864f71fee27SIngo Franzki struct bin_attribute *attr, 1865f71fee27SIngo Franzki char *buf, loff_t off, 1866f71fee27SIngo Franzki size_t count) 1867f71fee27SIngo Franzki { 1868f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 1869f71fee27SIngo Franzki off, count); 1870f71fee27SIngo Franzki } 1871f71fee27SIngo Franzki 1872f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp, 1873f71fee27SIngo Franzki struct kobject *kobj, 1874f71fee27SIngo Franzki struct bin_attribute *attr, 1875f71fee27SIngo Franzki char *buf, loff_t off, 1876f71fee27SIngo Franzki size_t count) 1877f71fee27SIngo Franzki { 1878f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 1879f71fee27SIngo Franzki off, count); 1880f71fee27SIngo Franzki } 1881f71fee27SIngo Franzki 1882f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp, 1883f71fee27SIngo Franzki struct kobject *kobj, 1884f71fee27SIngo Franzki struct bin_attribute *attr, 1885f71fee27SIngo Franzki char *buf, loff_t off, 1886f71fee27SIngo Franzki size_t count) 1887f71fee27SIngo Franzki { 1888f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 1889f71fee27SIngo Franzki off, count); 1890f71fee27SIngo Franzki } 1891f71fee27SIngo Franzki 1892f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); 1893f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); 1894f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); 1895f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); 1896f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); 1897f71fee27SIngo Franzki 1898f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = { 1899f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128, 1900f71fee27SIngo Franzki &bin_attr_ccacipher_aes_192, 1901f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256, 1902f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128_xts, 1903f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256_xts, 1904f71fee27SIngo Franzki NULL 1905f71fee27SIngo Franzki }; 1906f71fee27SIngo Franzki 1907f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = { 1908f71fee27SIngo Franzki .name = "ccacipher", 1909f71fee27SIngo Franzki .bin_attrs = ccacipher_attrs, 1910f71fee27SIngo Franzki }; 1911f71fee27SIngo Franzki 191255d0a513SHarald Freudenberger /* 191355d0a513SHarald Freudenberger * Sysfs attribute read function for all ep11 aes key binary attributes. 191455d0a513SHarald Freudenberger * The implementation can not deal with partial reads, because a new random 191555d0a513SHarald Freudenberger * secure key blob is generated with each read. In case of partial reads 191655d0a513SHarald Freudenberger * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 191755d0a513SHarald Freudenberger * This function and the sysfs attributes using it provide EP11 key blobs 191855d0a513SHarald Freudenberger * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently 191955d0a513SHarald Freudenberger * 320 bytes. 192055d0a513SHarald Freudenberger */ 192155d0a513SHarald Freudenberger static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, 192255d0a513SHarald Freudenberger bool is_xts, char *buf, loff_t off, 192355d0a513SHarald Freudenberger size_t count) 192455d0a513SHarald Freudenberger { 192555d0a513SHarald Freudenberger int i, rc, card, dom; 192655d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 192755d0a513SHarald Freudenberger size_t keysize = MAXEP11AESKEYBLOBSIZE; 192855d0a513SHarald Freudenberger 192955d0a513SHarald Freudenberger if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) 193055d0a513SHarald Freudenberger return -EINVAL; 193155d0a513SHarald Freudenberger if (is_xts) 193255d0a513SHarald Freudenberger if (count < 2 * MAXEP11AESKEYBLOBSIZE) 193355d0a513SHarald Freudenberger return -EINVAL; 193455d0a513SHarald Freudenberger 193555d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 193655d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 193755d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 193855d0a513SHarald Freudenberger if (rc) 193955d0a513SHarald Freudenberger return rc; 194055d0a513SHarald Freudenberger 194155d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 194255d0a513SHarald Freudenberger 194355d0a513SHarald Freudenberger /* simple try all apqns from the list */ 194455d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 194555d0a513SHarald Freudenberger card = apqns[i] >> 16; 194655d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 194755d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 194855d0a513SHarald Freudenberger if (rc == 0) 194955d0a513SHarald Freudenberger break; 195055d0a513SHarald Freudenberger } 195155d0a513SHarald Freudenberger if (rc) 195255d0a513SHarald Freudenberger return rc; 195355d0a513SHarald Freudenberger 195455d0a513SHarald Freudenberger if (is_xts) { 195555d0a513SHarald Freudenberger keysize = MAXEP11AESKEYBLOBSIZE; 195655d0a513SHarald Freudenberger buf += MAXEP11AESKEYBLOBSIZE; 195755d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 195855d0a513SHarald Freudenberger if (rc == 0) 195955d0a513SHarald Freudenberger return 2 * MAXEP11AESKEYBLOBSIZE; 196055d0a513SHarald Freudenberger } 196155d0a513SHarald Freudenberger 196255d0a513SHarald Freudenberger return MAXEP11AESKEYBLOBSIZE; 196355d0a513SHarald Freudenberger } 196455d0a513SHarald Freudenberger 196555d0a513SHarald Freudenberger static ssize_t ep11_aes_128_read(struct file *filp, 196655d0a513SHarald Freudenberger struct kobject *kobj, 196755d0a513SHarald Freudenberger struct bin_attribute *attr, 196855d0a513SHarald Freudenberger char *buf, loff_t off, 196955d0a513SHarald Freudenberger size_t count) 197055d0a513SHarald Freudenberger { 197155d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 197255d0a513SHarald Freudenberger off, count); 197355d0a513SHarald Freudenberger } 197455d0a513SHarald Freudenberger 197555d0a513SHarald Freudenberger static ssize_t ep11_aes_192_read(struct file *filp, 197655d0a513SHarald Freudenberger struct kobject *kobj, 197755d0a513SHarald Freudenberger struct bin_attribute *attr, 197855d0a513SHarald Freudenberger char *buf, loff_t off, 197955d0a513SHarald Freudenberger size_t count) 198055d0a513SHarald Freudenberger { 198155d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 198255d0a513SHarald Freudenberger off, count); 198355d0a513SHarald Freudenberger } 198455d0a513SHarald Freudenberger 198555d0a513SHarald Freudenberger static ssize_t ep11_aes_256_read(struct file *filp, 198655d0a513SHarald Freudenberger struct kobject *kobj, 198755d0a513SHarald Freudenberger struct bin_attribute *attr, 198855d0a513SHarald Freudenberger char *buf, loff_t off, 198955d0a513SHarald Freudenberger size_t count) 199055d0a513SHarald Freudenberger { 199155d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 199255d0a513SHarald Freudenberger off, count); 199355d0a513SHarald Freudenberger } 199455d0a513SHarald Freudenberger 199555d0a513SHarald Freudenberger static ssize_t ep11_aes_128_xts_read(struct file *filp, 199655d0a513SHarald Freudenberger struct kobject *kobj, 199755d0a513SHarald Freudenberger struct bin_attribute *attr, 199855d0a513SHarald Freudenberger char *buf, loff_t off, 199955d0a513SHarald Freudenberger size_t count) 200055d0a513SHarald Freudenberger { 200155d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 200255d0a513SHarald Freudenberger off, count); 200355d0a513SHarald Freudenberger } 200455d0a513SHarald Freudenberger 200555d0a513SHarald Freudenberger static ssize_t ep11_aes_256_xts_read(struct file *filp, 200655d0a513SHarald Freudenberger struct kobject *kobj, 200755d0a513SHarald Freudenberger struct bin_attribute *attr, 200855d0a513SHarald Freudenberger char *buf, loff_t off, 200955d0a513SHarald Freudenberger size_t count) 201055d0a513SHarald Freudenberger { 201155d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 201255d0a513SHarald Freudenberger off, count); 201355d0a513SHarald Freudenberger } 201455d0a513SHarald Freudenberger 201555d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE); 201655d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE); 201755d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE); 201855d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE); 201955d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE); 202055d0a513SHarald Freudenberger 202155d0a513SHarald Freudenberger static struct bin_attribute *ep11_attrs[] = { 202255d0a513SHarald Freudenberger &bin_attr_ep11_aes_128, 202355d0a513SHarald Freudenberger &bin_attr_ep11_aes_192, 202455d0a513SHarald Freudenberger &bin_attr_ep11_aes_256, 202555d0a513SHarald Freudenberger &bin_attr_ep11_aes_128_xts, 202655d0a513SHarald Freudenberger &bin_attr_ep11_aes_256_xts, 202755d0a513SHarald Freudenberger NULL 202855d0a513SHarald Freudenberger }; 202955d0a513SHarald Freudenberger 203055d0a513SHarald Freudenberger static struct attribute_group ep11_attr_group = { 203155d0a513SHarald Freudenberger .name = "ep11", 203255d0a513SHarald Freudenberger .bin_attrs = ep11_attrs, 203355d0a513SHarald Freudenberger }; 203455d0a513SHarald Freudenberger 2035d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 2036d632c047SIngo Franzki &protkey_attr_group, 2037af504452SIngo Franzki &ccadata_attr_group, 2038f71fee27SIngo Franzki &ccacipher_attr_group, 203955d0a513SHarald Freudenberger &ep11_attr_group, 2040d632c047SIngo Franzki NULL, 2041d632c047SIngo Franzki }; 2042d632c047SIngo Franzki 2043e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 2044e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 2045e80d4af0SHarald Freudenberger .open = nonseekable_open, 2046e80d4af0SHarald Freudenberger .llseek = no_llseek, 2047e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 2048e80d4af0SHarald Freudenberger }; 2049e80d4af0SHarald Freudenberger 2050e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 2051e80d4af0SHarald Freudenberger .name = "pkey", 2052e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 2053e80d4af0SHarald Freudenberger .mode = 0666, 2054e80d4af0SHarald Freudenberger .fops = &pkey_fops, 2055d632c047SIngo Franzki .groups = pkey_attr_groups, 2056e80d4af0SHarald Freudenberger }; 2057e80d4af0SHarald Freudenberger 2058e80d4af0SHarald Freudenberger /* 2059e80d4af0SHarald Freudenberger * Module init 2060e80d4af0SHarald Freudenberger */ 2061cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 2062e80d4af0SHarald Freudenberger { 2063*5b35047eSHarald Freudenberger cpacf_mask_t func_mask; 2064e80d4af0SHarald Freudenberger 2065f822ad2cSHarald Freudenberger /* 2066f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 2067f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 2068f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 2069f822ad2cSHarald Freudenberger * are able to work with protected keys. 2070f822ad2cSHarald Freudenberger */ 2071*5b35047eSHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &func_mask)) 207258443b67SDavid Hildenbrand return -ENODEV; 2073e80d4af0SHarald Freudenberger 2074cb26b9ffSIngo Franzki /* check for kmc instructions available */ 2075*5b35047eSHarald Freudenberger if (!cpacf_query(CPACF_KMC, &func_mask)) 207658443b67SDavid Hildenbrand return -ENODEV; 2077*5b35047eSHarald Freudenberger if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) || 2078*5b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) || 2079*5b35047eSHarald Freudenberger !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256)) 208058443b67SDavid Hildenbrand return -ENODEV; 2081cb26b9ffSIngo Franzki 2082e80d4af0SHarald Freudenberger pkey_debug_init(); 2083e80d4af0SHarald Freudenberger 2084e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 2085e80d4af0SHarald Freudenberger } 2086e80d4af0SHarald Freudenberger 2087e80d4af0SHarald Freudenberger /* 2088e80d4af0SHarald Freudenberger * Module exit 2089e80d4af0SHarald Freudenberger */ 2090e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 2091e80d4af0SHarald Freudenberger { 2092e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 2093e80d4af0SHarald Freudenberger pkey_debug_exit(); 2094e80d4af0SHarald Freudenberger } 2095e80d4af0SHarald Freudenberger 209663c19be0SIngo Franzki module_cpu_feature_match(MSA, pkey_init); 2097e80d4af0SHarald Freudenberger module_exit(pkey_exit); 2098