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" 28e80d4af0SHarald Freudenberger 29e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL"); 30e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 31e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface"); 32e80d4af0SHarald Freudenberger 33f2bbc96eSHarald Freudenberger #define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ 34f2bbc96eSHarald Freudenberger #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ 35f2bbc96eSHarald Freudenberger 36f822ad2cSHarald Freudenberger /* mask of available pckmo subfunctions, fetched once at module init */ 37f822ad2cSHarald Freudenberger static cpacf_mask_t pckmo_functions; 38f822ad2cSHarald Freudenberger 39e80d4af0SHarald Freudenberger /* 40e80d4af0SHarald Freudenberger * debug feature data and functions 41e80d4af0SHarald Freudenberger */ 42e80d4af0SHarald Freudenberger 43e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 44e80d4af0SHarald Freudenberger 45e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 46e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 47e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 48e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 49e80d4af0SHarald Freudenberger 50e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 51e80d4af0SHarald Freudenberger { 526b1f16baSHarald Freudenberger /* 5 arguments per dbf entry (including the format string ptr) */ 536b1f16baSHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); 54e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 55e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 56e80d4af0SHarald Freudenberger } 57e80d4af0SHarald Freudenberger 58e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 59e80d4af0SHarald Freudenberger { 60e80d4af0SHarald Freudenberger debug_unregister(debug_info); 61e80d4af0SHarald Freudenberger } 62e80d4af0SHarald Freudenberger 630534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */ 640534bde7SIngo Franzki struct protaeskeytoken { 650534bde7SIngo Franzki u8 type; /* 0x00 for PAES specific key tokens */ 660534bde7SIngo Franzki u8 res0[3]; 670534bde7SIngo Franzki u8 version; /* should be 0x01 for protected AES key token */ 680534bde7SIngo Franzki u8 res1[3]; 690534bde7SIngo Franzki u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 700534bde7SIngo Franzki u32 len; /* bytes actually stored in protkey[] */ 710534bde7SIngo Franzki u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 720534bde7SIngo Franzki } __packed; 730534bde7SIngo Franzki 74*888edbc4SHarald Freudenberger /* inside view of a clear key token (type 0x00 version 0x02) */ 75*888edbc4SHarald Freudenberger struct clearaeskeytoken { 76*888edbc4SHarald Freudenberger u8 type; /* 0x00 for PAES specific key tokens */ 77*888edbc4SHarald Freudenberger u8 res0[3]; 78*888edbc4SHarald Freudenberger u8 version; /* 0x02 for clear AES key token */ 79*888edbc4SHarald Freudenberger u8 res1[3]; 80*888edbc4SHarald Freudenberger u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 81*888edbc4SHarald Freudenberger u32 len; /* bytes actually stored in clearkey[] */ 82*888edbc4SHarald Freudenberger u8 clearkey[0]; /* clear key value */ 83*888edbc4SHarald Freudenberger } __packed; 84*888edbc4SHarald Freudenberger 85e80d4af0SHarald Freudenberger /* 86e80d4af0SHarald Freudenberger * Create a protected key from a clear key value. 87e80d4af0SHarald Freudenberger */ 88183cb469SHarald Freudenberger static int pkey_clr2protkey(u32 keytype, 89e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 90e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 91e80d4af0SHarald Freudenberger { 92e80d4af0SHarald Freudenberger long fc; 93e80d4af0SHarald Freudenberger int keysize; 94e80d4af0SHarald Freudenberger u8 paramblock[64]; 95e80d4af0SHarald Freudenberger 96e80d4af0SHarald Freudenberger switch (keytype) { 97e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 98e80d4af0SHarald Freudenberger keysize = 16; 99e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 100e80d4af0SHarald Freudenberger break; 101e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 102e80d4af0SHarald Freudenberger keysize = 24; 103e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 104e80d4af0SHarald Freudenberger break; 105e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 106e80d4af0SHarald Freudenberger keysize = 32; 107e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 108e80d4af0SHarald Freudenberger break; 109e80d4af0SHarald Freudenberger default: 110ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 111ac2b96f3SHarald Freudenberger __func__, keytype); 112e80d4af0SHarald Freudenberger return -EINVAL; 113e80d4af0SHarald Freudenberger } 114e80d4af0SHarald Freudenberger 115f822ad2cSHarald Freudenberger /* 116f822ad2cSHarald Freudenberger * Check if the needed pckmo subfunction is available. 117f822ad2cSHarald Freudenberger * These subfunctions can be enabled/disabled by customers 118f822ad2cSHarald Freudenberger * in the LPAR profile or may even change on the fly. 119f822ad2cSHarald Freudenberger */ 120f822ad2cSHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, fc)) { 121f822ad2cSHarald Freudenberger DEBUG_ERR("%s pckmo functions not available\n", __func__); 12258443b67SDavid Hildenbrand return -ENODEV; 123f822ad2cSHarald Freudenberger } 124f822ad2cSHarald Freudenberger 125e80d4af0SHarald Freudenberger /* prepare param block */ 126e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 127e80d4af0SHarald Freudenberger memcpy(paramblock, clrkey->clrkey, keysize); 128e80d4af0SHarald Freudenberger 129e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 130e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 131e80d4af0SHarald Freudenberger 132e80d4af0SHarald Freudenberger /* copy created protected key */ 133e80d4af0SHarald Freudenberger protkey->type = keytype; 134e80d4af0SHarald Freudenberger protkey->len = keysize + 32; 135e80d4af0SHarald Freudenberger memcpy(protkey->protkey, paramblock, keysize + 32); 136e80d4af0SHarald Freudenberger 137e80d4af0SHarald Freudenberger return 0; 138e80d4af0SHarald Freudenberger } 139e80d4af0SHarald Freudenberger 140e80d4af0SHarald Freudenberger /* 141e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 142e80d4af0SHarald Freudenberger */ 143f2bbc96eSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) 144e80d4af0SHarald Freudenberger { 145e80d4af0SHarald Freudenberger int rc, verify; 146f2bbc96eSHarald Freudenberger u16 cardnr, domain; 147f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 148e80d4af0SHarald Freudenberger 149e80d4af0SHarald Freudenberger /* 150f2bbc96eSHarald Freudenberger * The cca_xxx2protkey call may fail when a card has been 151e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 152efc598e6SHarald Freudenberger * of the mkvp into the cache. Try 3 times: First witout verify 153efc598e6SHarald Freudenberger * then with verify and last round with verify and old master 154efc598e6SHarald Freudenberger * key verification pattern match not ignored. 155e80d4af0SHarald Freudenberger */ 156efc598e6SHarald Freudenberger for (verify = 0; verify < 3; verify++) { 157f2bbc96eSHarald Freudenberger rc = cca_findcard(key, &cardnr, &domain, verify); 158efc598e6SHarald Freudenberger if (rc < 0) 159e80d4af0SHarald Freudenberger continue; 160efc598e6SHarald Freudenberger if (rc > 0 && verify < 2) 161efc598e6SHarald Freudenberger continue; 162f2bbc96eSHarald Freudenberger switch (hdr->version) { 163f2bbc96eSHarald Freudenberger case TOKVER_CCA_AES: 164f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(cardnr, domain, 165f2bbc96eSHarald Freudenberger key, pkey->protkey, 166f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 167f2bbc96eSHarald Freudenberger break; 168f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 169f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(cardnr, domain, 170f2bbc96eSHarald Freudenberger key, pkey->protkey, 171f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 172f2bbc96eSHarald Freudenberger break; 173f2bbc96eSHarald Freudenberger default: 174f2bbc96eSHarald Freudenberger return -EINVAL; 175f2bbc96eSHarald Freudenberger } 176e80d4af0SHarald Freudenberger if (rc == 0) 177e80d4af0SHarald Freudenberger break; 178e80d4af0SHarald Freudenberger } 179e80d4af0SHarald Freudenberger 180e80d4af0SHarald Freudenberger if (rc) 181ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 182e80d4af0SHarald Freudenberger 183e80d4af0SHarald Freudenberger return rc; 184e80d4af0SHarald Freudenberger } 185e80d4af0SHarald Freudenberger 186e80d4af0SHarald Freudenberger /* 187e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 188e61a6134SHarald Freudenberger */ 189183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey, 190e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 191e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 192e61a6134SHarald Freudenberger { 193e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 194e61a6134SHarald Freudenberger u16 cardnr, domain; 195e61a6134SHarald Freudenberger int rc; 196e61a6134SHarald Freudenberger 197e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 198efc598e6SHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *) seckey, 0); 199e61a6134SHarald Freudenberger if (rc) 200e61a6134SHarald Freudenberger goto out; 201e61a6134SHarald Freudenberger if (pattributes) 202e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 203e61a6134SHarald Freudenberger if (pkeysize) 204e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 205e61a6134SHarald Freudenberger 206e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 207efc598e6SHarald Freudenberger rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); 208efc598e6SHarald Freudenberger if (rc < 0) 209e61a6134SHarald Freudenberger goto out; 210e61a6134SHarald Freudenberger 211efc598e6SHarald Freudenberger if (rc > 0) { 212efc598e6SHarald Freudenberger /* key mkvp matches to old master key mkvp */ 213ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 214e61a6134SHarald Freudenberger if (pattributes) 215e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 216efc598e6SHarald Freudenberger rc = 0; 217e61a6134SHarald Freudenberger } 218e61a6134SHarald Freudenberger 219e61a6134SHarald Freudenberger if (pcardnr) 220e61a6134SHarald Freudenberger *pcardnr = cardnr; 221e61a6134SHarald Freudenberger if (pdomain) 222e61a6134SHarald Freudenberger *pdomain = domain; 223e61a6134SHarald Freudenberger 224e61a6134SHarald Freudenberger out: 225ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 226e61a6134SHarald Freudenberger return rc; 227e61a6134SHarald Freudenberger } 228e61a6134SHarald Freudenberger 229e61a6134SHarald Freudenberger /* 230a45a5c7dSIngo Franzki * Generate a random protected key 231a45a5c7dSIngo Franzki */ 232183cb469SHarald Freudenberger static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) 233a45a5c7dSIngo Franzki { 234a45a5c7dSIngo Franzki struct pkey_clrkey clrkey; 235a45a5c7dSIngo Franzki int keysize; 236a45a5c7dSIngo Franzki int rc; 237a45a5c7dSIngo Franzki 238a45a5c7dSIngo Franzki switch (keytype) { 239a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_128: 240a45a5c7dSIngo Franzki keysize = 16; 241a45a5c7dSIngo Franzki break; 242a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_192: 243a45a5c7dSIngo Franzki keysize = 24; 244a45a5c7dSIngo Franzki break; 245a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_256: 246a45a5c7dSIngo Franzki keysize = 32; 247a45a5c7dSIngo Franzki break; 248a45a5c7dSIngo Franzki default: 249a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 250a45a5c7dSIngo Franzki keytype); 251a45a5c7dSIngo Franzki return -EINVAL; 252a45a5c7dSIngo Franzki } 253a45a5c7dSIngo Franzki 254a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 255a45a5c7dSIngo Franzki get_random_bytes(clrkey.clrkey, keysize); 256a45a5c7dSIngo Franzki 257a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 258a45a5c7dSIngo Franzki rc = pkey_clr2protkey(keytype, &clrkey, protkey); 259a45a5c7dSIngo Franzki if (rc) 260a45a5c7dSIngo Franzki return rc; 261a45a5c7dSIngo Franzki 262a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 263a45a5c7dSIngo Franzki get_random_bytes(protkey->protkey, keysize); 264a45a5c7dSIngo Franzki 265a45a5c7dSIngo Franzki return 0; 266a45a5c7dSIngo Franzki } 267a45a5c7dSIngo Franzki 268a45a5c7dSIngo Franzki /* 269cb26b9ffSIngo Franzki * Verify if a protected key is still valid 270cb26b9ffSIngo Franzki */ 271183cb469SHarald Freudenberger static int pkey_verifyprotkey(const struct pkey_protkey *protkey) 272cb26b9ffSIngo Franzki { 273cb26b9ffSIngo Franzki unsigned long fc; 274cb26b9ffSIngo Franzki struct { 275cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 276cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 277cb26b9ffSIngo Franzki } param; 278cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 279cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 280cb26b9ffSIngo Franzki unsigned int k; 281cb26b9ffSIngo Franzki 282cb26b9ffSIngo Franzki switch (protkey->type) { 283cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 284cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 285cb26b9ffSIngo Franzki break; 286cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 287cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 288cb26b9ffSIngo Franzki break; 289cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 290cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 291cb26b9ffSIngo Franzki break; 292cb26b9ffSIngo Franzki default: 293cb26b9ffSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 294cb26b9ffSIngo Franzki protkey->type); 295cb26b9ffSIngo Franzki return -EINVAL; 296cb26b9ffSIngo Franzki } 297cb26b9ffSIngo Franzki 298cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 299cb26b9ffSIngo Franzki 300cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 301cb26b9ffSIngo Franzki memcpy(param.key, protkey->protkey, sizeof(param.key)); 302cb26b9ffSIngo Franzki 303cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 304cb26b9ffSIngo Franzki sizeof(null_msg)); 305cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 306cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 307cb26b9ffSIngo Franzki return -EKEYREJECTED; 308cb26b9ffSIngo Franzki } 309cb26b9ffSIngo Franzki 310cb26b9ffSIngo Franzki return 0; 311cb26b9ffSIngo Franzki } 312cb26b9ffSIngo Franzki 313cb26b9ffSIngo Franzki /* 314fb1136d6SIngo Franzki * Transform a non-CCA key token into a protected key 315fb1136d6SIngo Franzki */ 316183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, 317fb1136d6SIngo Franzki struct pkey_protkey *protkey) 318fb1136d6SIngo Franzki { 319*888edbc4SHarald Freudenberger int rc = -EINVAL; 320fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 321fb1136d6SIngo Franzki 322fb1136d6SIngo Franzki switch (hdr->version) { 323*888edbc4SHarald Freudenberger case TOKVER_PROTECTED_KEY: { 324*888edbc4SHarald Freudenberger struct protaeskeytoken *t; 325fb1136d6SIngo Franzki 326*888edbc4SHarald Freudenberger if (keylen != sizeof(struct protaeskeytoken)) 327*888edbc4SHarald Freudenberger goto out; 328fb1136d6SIngo Franzki t = (struct protaeskeytoken *)key; 329fb1136d6SIngo Franzki protkey->len = t->len; 330fb1136d6SIngo Franzki protkey->type = t->keytype; 331fb1136d6SIngo Franzki memcpy(protkey->protkey, t->protkey, 332fb1136d6SIngo Franzki sizeof(protkey->protkey)); 333*888edbc4SHarald Freudenberger rc = pkey_verifyprotkey(protkey); 334*888edbc4SHarald Freudenberger break; 335*888edbc4SHarald Freudenberger } 336*888edbc4SHarald Freudenberger case TOKVER_CLEAR_KEY: { 337*888edbc4SHarald Freudenberger struct clearaeskeytoken *t; 338*888edbc4SHarald Freudenberger struct pkey_clrkey ckey; 339*888edbc4SHarald Freudenberger struct pkey_seckey skey; 340fb1136d6SIngo Franzki 341*888edbc4SHarald Freudenberger if (keylen < sizeof(struct clearaeskeytoken)) 342*888edbc4SHarald Freudenberger goto out; 343*888edbc4SHarald Freudenberger t = (struct clearaeskeytoken *)key; 344*888edbc4SHarald Freudenberger if (keylen != sizeof(*t) + t->len) 345*888edbc4SHarald Freudenberger goto out; 346*888edbc4SHarald Freudenberger if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) 347*888edbc4SHarald Freudenberger || (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) 348*888edbc4SHarald Freudenberger || (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) 349*888edbc4SHarald Freudenberger memcpy(ckey.clrkey, t->clearkey, t->len); 350*888edbc4SHarald Freudenberger else 351*888edbc4SHarald Freudenberger goto out; 352*888edbc4SHarald Freudenberger /* try direct way with the PCKMO instruction */ 353*888edbc4SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, &ckey, protkey); 354*888edbc4SHarald Freudenberger if (rc == 0) 355*888edbc4SHarald Freudenberger break; 356*888edbc4SHarald Freudenberger /* PCKMO failed, so try the CCA secure key way */ 357*888edbc4SHarald Freudenberger rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, 358*888edbc4SHarald Freudenberger ckey.clrkey, skey.seckey); 359*888edbc4SHarald Freudenberger if (rc == 0) 360*888edbc4SHarald Freudenberger rc = pkey_skey2pkey(skey.seckey, protkey); 361*888edbc4SHarald Freudenberger /* now we should really have an protected key */ 362*888edbc4SHarald Freudenberger if (rc == 0) 363*888edbc4SHarald Freudenberger break; 364*888edbc4SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", 365*888edbc4SHarald Freudenberger __func__); 366*888edbc4SHarald Freudenberger break; 367*888edbc4SHarald Freudenberger } 368fb1136d6SIngo Franzki default: 369fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 370fb1136d6SIngo Franzki __func__, hdr->version); 371*888edbc4SHarald Freudenberger rc = -EINVAL; 372fb1136d6SIngo Franzki } 373*888edbc4SHarald Freudenberger 374*888edbc4SHarald Freudenberger out: 375*888edbc4SHarald Freudenberger return rc; 376fb1136d6SIngo Franzki } 377fb1136d6SIngo Franzki 378fb1136d6SIngo Franzki /* 379fb1136d6SIngo Franzki * Transform a CCA internal key token into a protected key 380fb1136d6SIngo Franzki */ 381183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, 382fb1136d6SIngo Franzki struct pkey_protkey *protkey) 383fb1136d6SIngo Franzki { 384fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 385fb1136d6SIngo Franzki 386fb1136d6SIngo Franzki switch (hdr->version) { 387fb1136d6SIngo Franzki case TOKVER_CCA_AES: 388fb1136d6SIngo Franzki if (keylen != sizeof(struct secaeskeytoken)) 389fb1136d6SIngo Franzki return -EINVAL; 390f2bbc96eSHarald Freudenberger break; 391f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 392f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 393f2bbc96eSHarald Freudenberger return -EINVAL; 394f2bbc96eSHarald Freudenberger break; 395fb1136d6SIngo Franzki default: 396fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 397fb1136d6SIngo Franzki __func__, hdr->version); 398fb1136d6SIngo Franzki return -EINVAL; 399fb1136d6SIngo Franzki } 400f2bbc96eSHarald Freudenberger 401f2bbc96eSHarald Freudenberger return pkey_skey2pkey(key, protkey); 402fb1136d6SIngo Franzki } 403fb1136d6SIngo Franzki 404fb1136d6SIngo Franzki /* 405fb1136d6SIngo Franzki * Transform a key blob (of any type) into a protected key 406fb1136d6SIngo Franzki */ 407183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen, 408fb1136d6SIngo Franzki struct pkey_protkey *protkey) 409fb1136d6SIngo Franzki { 410f2bbc96eSHarald Freudenberger int rc; 411fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 412fb1136d6SIngo Franzki 413f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) { 414f2bbc96eSHarald Freudenberger DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); 415f2bbc96eSHarald Freudenberger return -EINVAL; 416f2bbc96eSHarald Freudenberger } 417f2bbc96eSHarald Freudenberger 418f2bbc96eSHarald Freudenberger switch (hdr->type) { 419f2bbc96eSHarald Freudenberger case TOKTYPE_NON_CCA: 420f2bbc96eSHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, protkey); 421f2bbc96eSHarald Freudenberger break; 422f2bbc96eSHarald Freudenberger case TOKTYPE_CCA_INTERNAL: 423f2bbc96eSHarald Freudenberger rc = pkey_ccainttok2pkey(key, keylen, protkey); 424f2bbc96eSHarald Freudenberger break; 425f2bbc96eSHarald Freudenberger default: 426f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 427f2bbc96eSHarald Freudenberger __func__, hdr->type); 428f2bbc96eSHarald Freudenberger return -EINVAL; 429f2bbc96eSHarald Freudenberger } 430f2bbc96eSHarald Freudenberger 431f2bbc96eSHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 432f2bbc96eSHarald Freudenberger return rc; 433f2bbc96eSHarald Freudenberger 434f2bbc96eSHarald Freudenberger } 435f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey); 436f2bbc96eSHarald Freudenberger 437f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 438f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 439f2bbc96eSHarald Freudenberger u32 kflags, u8 *keybuf, size_t *keybufsize) 440f2bbc96eSHarald Freudenberger { 441f2bbc96eSHarald Freudenberger int i, card, dom, rc; 442f2bbc96eSHarald Freudenberger 443f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 444f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 445f2bbc96eSHarald Freudenberger return -EINVAL; 446f2bbc96eSHarald Freudenberger 447f2bbc96eSHarald Freudenberger /* check key type and size */ 448f2bbc96eSHarald Freudenberger switch (ktype) { 449f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 450f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 451f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 452f2bbc96eSHarald Freudenberger return -EINVAL; 453f2bbc96eSHarald Freudenberger break; 454f2bbc96eSHarald Freudenberger default: 455f2bbc96eSHarald Freudenberger return -EINVAL; 456f2bbc96eSHarald Freudenberger } 457f2bbc96eSHarald Freudenberger switch (ksize) { 458f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 459f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 460f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 461f2bbc96eSHarald Freudenberger break; 462f2bbc96eSHarald Freudenberger default: 463f2bbc96eSHarald Freudenberger return -EINVAL; 464f2bbc96eSHarald Freudenberger } 465f2bbc96eSHarald Freudenberger 466f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 467f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 468f2bbc96eSHarald Freudenberger card = apqns[i].card; 469f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 470f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA) { 471f2bbc96eSHarald Freudenberger rc = cca_genseckey(card, dom, ksize, keybuf); 472f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 473f2bbc96eSHarald Freudenberger } else /* TOKVER_CCA_VLSC */ 474f2bbc96eSHarald Freudenberger rc = cca_gencipherkey(card, dom, ksize, kflags, 475f2bbc96eSHarald Freudenberger keybuf, keybufsize); 476f2bbc96eSHarald Freudenberger if (rc == 0) 477f2bbc96eSHarald Freudenberger break; 478f2bbc96eSHarald Freudenberger } 479f2bbc96eSHarald Freudenberger 480f2bbc96eSHarald Freudenberger return rc; 481f2bbc96eSHarald Freudenberger } 482f2bbc96eSHarald Freudenberger 483f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 484f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 485f2bbc96eSHarald Freudenberger u32 kflags, const u8 *clrkey, 486f2bbc96eSHarald Freudenberger u8 *keybuf, size_t *keybufsize) 487f2bbc96eSHarald Freudenberger { 488f2bbc96eSHarald Freudenberger int i, card, dom, rc; 489f2bbc96eSHarald Freudenberger 490f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 491f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 492f2bbc96eSHarald Freudenberger return -EINVAL; 493f2bbc96eSHarald Freudenberger 494f2bbc96eSHarald Freudenberger /* check key type and size */ 495f2bbc96eSHarald Freudenberger switch (ktype) { 496f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 497f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 498f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 499f2bbc96eSHarald Freudenberger return -EINVAL; 500f2bbc96eSHarald Freudenberger break; 501f2bbc96eSHarald Freudenberger default: 502f2bbc96eSHarald Freudenberger return -EINVAL; 503f2bbc96eSHarald Freudenberger } 504f2bbc96eSHarald Freudenberger switch (ksize) { 505f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 506f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 507f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 508f2bbc96eSHarald Freudenberger break; 509f2bbc96eSHarald Freudenberger default: 510f2bbc96eSHarald Freudenberger return -EINVAL; 511f2bbc96eSHarald Freudenberger } 512f2bbc96eSHarald Freudenberger 513f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 514f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 515f2bbc96eSHarald Freudenberger card = apqns[i].card; 516f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 517f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA) { 518f2bbc96eSHarald Freudenberger rc = cca_clr2seckey(card, dom, ksize, 519f2bbc96eSHarald Freudenberger clrkey, keybuf); 520f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 521f2bbc96eSHarald Freudenberger } else /* TOKVER_CCA_VLSC */ 522f2bbc96eSHarald Freudenberger rc = cca_clr2cipherkey(card, dom, ksize, kflags, 523f2bbc96eSHarald Freudenberger clrkey, keybuf, keybufsize); 524f2bbc96eSHarald Freudenberger if (rc == 0) 525f2bbc96eSHarald Freudenberger break; 526f2bbc96eSHarald Freudenberger } 527f2bbc96eSHarald Freudenberger 528f2bbc96eSHarald Freudenberger return rc; 529f2bbc96eSHarald Freudenberger } 530f2bbc96eSHarald Freudenberger 531f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen, 532f2bbc96eSHarald Freudenberger u16 *cardnr, u16 *domain, 533f2bbc96eSHarald Freudenberger enum pkey_key_type *ktype, 534f2bbc96eSHarald Freudenberger enum pkey_key_size *ksize, u32 *flags) 535f2bbc96eSHarald Freudenberger { 536f2bbc96eSHarald Freudenberger int rc; 537f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 538f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 539f2bbc96eSHarald Freudenberger 540f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || 541f2bbc96eSHarald Freudenberger hdr->type != TOKTYPE_CCA_INTERNAL) 542f2bbc96eSHarald Freudenberger return -EINVAL; 543f2bbc96eSHarald Freudenberger 544f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 545f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 546f2bbc96eSHarald Freudenberger 547f2bbc96eSHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 548f2bbc96eSHarald Freudenberger if (rc) 549f2bbc96eSHarald Freudenberger goto out; 550f2bbc96eSHarald Freudenberger if (ktype) 551f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_DATA; 552f2bbc96eSHarald Freudenberger if (ksize) 553f2bbc96eSHarald Freudenberger *ksize = (enum pkey_key_size) t->bitsize; 554f2bbc96eSHarald Freudenberger 555f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 556f2bbc96eSHarald Freudenberger ZCRYPT_CEX3C, t->mkvp, 0, 1); 557f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 558f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 559f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 560f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 561f2bbc96eSHarald Freudenberger *cardnr, *domain, 562f2bbc96eSHarald Freudenberger ZCRYPT_CEX3C, 0, t->mkvp, 1); 563f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 564f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 565f2bbc96eSHarald Freudenberger } 566f2bbc96eSHarald Freudenberger if (rc) 567f2bbc96eSHarald Freudenberger goto out; 568f2bbc96eSHarald Freudenberger 569f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 570f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 571f2bbc96eSHarald Freudenberger 572f2bbc96eSHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 573f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 574f2bbc96eSHarald Freudenberger 575f2bbc96eSHarald Freudenberger rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 576f2bbc96eSHarald Freudenberger if (rc) 577f2bbc96eSHarald Freudenberger goto out; 578f2bbc96eSHarald Freudenberger if (ktype) 579f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_CIPHER; 580f2bbc96eSHarald Freudenberger if (ksize) { 581f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_UNKNOWN; 582f2bbc96eSHarald Freudenberger if (!t->plfver && t->wpllen == 512) 583f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_128; 584f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 585f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_192; 586f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 587f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_256; 588f2bbc96eSHarald Freudenberger } 589f2bbc96eSHarald Freudenberger 590f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 591f2bbc96eSHarald Freudenberger ZCRYPT_CEX6, t->mkvp0, 0, 1); 592f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 593f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 594f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 595f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 596f2bbc96eSHarald Freudenberger *cardnr, *domain, 597f2bbc96eSHarald Freudenberger ZCRYPT_CEX6, 0, t->mkvp0, 1); 598f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 599f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 600f2bbc96eSHarald Freudenberger } 601f2bbc96eSHarald Freudenberger if (rc) 602f2bbc96eSHarald Freudenberger goto out; 603f2bbc96eSHarald Freudenberger 604f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 605f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 606f2bbc96eSHarald Freudenberger 607f2bbc96eSHarald Freudenberger } else 608f2bbc96eSHarald Freudenberger rc = -EINVAL; 609f2bbc96eSHarald Freudenberger 610f2bbc96eSHarald Freudenberger out: 611f2bbc96eSHarald Freudenberger kfree(_apqns); 612f2bbc96eSHarald Freudenberger return rc; 613f2bbc96eSHarald Freudenberger } 614f2bbc96eSHarald Freudenberger 615f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 616f2bbc96eSHarald Freudenberger const u8 *key, size_t keylen, 617f2bbc96eSHarald Freudenberger struct pkey_protkey *pkey) 618f2bbc96eSHarald Freudenberger { 619f2bbc96eSHarald Freudenberger int i, card, dom, rc; 620f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 621f2bbc96eSHarald Freudenberger 622f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 623f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 624f2bbc96eSHarald Freudenberger return -EINVAL; 625f2bbc96eSHarald Freudenberger 626fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 627fb1136d6SIngo Franzki return -EINVAL; 628fb1136d6SIngo Franzki 629fb1136d6SIngo Franzki switch (hdr->type) { 630fb1136d6SIngo Franzki case TOKTYPE_NON_CCA: 631f2bbc96eSHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, pkey); 632fb1136d6SIngo Franzki case TOKTYPE_CCA_INTERNAL: 633f2bbc96eSHarald Freudenberger switch (hdr->version) { 634f2bbc96eSHarald Freudenberger case TOKVER_CCA_AES: 635f2bbc96eSHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 636f2bbc96eSHarald Freudenberger return -EINVAL; 637f2bbc96eSHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 638f2bbc96eSHarald Freudenberger return -EINVAL; 639f2bbc96eSHarald Freudenberger break; 640f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 641f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 642f2bbc96eSHarald Freudenberger return -EINVAL; 643f2bbc96eSHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 644f2bbc96eSHarald Freudenberger return -EINVAL; 645f2bbc96eSHarald Freudenberger break; 646fb1136d6SIngo Franzki default: 647f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 648f2bbc96eSHarald Freudenberger __func__, hdr->version); 649fb1136d6SIngo Franzki return -EINVAL; 650fb1136d6SIngo Franzki } 651f2bbc96eSHarald Freudenberger break; 652f2bbc96eSHarald Freudenberger default: 653f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 654f2bbc96eSHarald Freudenberger __func__, hdr->type); 655f2bbc96eSHarald Freudenberger return -EINVAL; 656fb1136d6SIngo Franzki } 657f2bbc96eSHarald Freudenberger 658f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 659f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 660f2bbc96eSHarald Freudenberger card = apqns[i].card; 661f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 662f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) 663f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(card, dom, key, pkey->protkey, 664f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 665f2bbc96eSHarald Freudenberger else /* TOKVER_CCA_VLSC */ 666f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, pkey->protkey, 667f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 668f2bbc96eSHarald Freudenberger if (rc == 0) 669f2bbc96eSHarald Freudenberger break; 670f2bbc96eSHarald Freudenberger } 671f2bbc96eSHarald Freudenberger 672f2bbc96eSHarald Freudenberger return rc; 673f2bbc96eSHarald Freudenberger } 674f2bbc96eSHarald Freudenberger 675f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 676f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 677f2bbc96eSHarald Freudenberger { 678f2bbc96eSHarald Freudenberger int rc = EINVAL; 679f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 680f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 681f2bbc96eSHarald Freudenberger 682f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || 683f2bbc96eSHarald Freudenberger hdr->type != TOKTYPE_CCA_INTERNAL || 684f2bbc96eSHarald Freudenberger flags == 0) 685f2bbc96eSHarald Freudenberger return -EINVAL; 686f2bbc96eSHarald Freudenberger 687f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES || hdr->version == TOKVER_CCA_VLSC) { 688f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 689f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 690f2bbc96eSHarald Freudenberger 691f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 692f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 693f2bbc96eSHarald Freudenberger 694f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 695f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp; 696f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 697f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp; 698f2bbc96eSHarald Freudenberger } else { 699f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 700f2bbc96eSHarald Freudenberger 701f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 702f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 703f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp0; 704f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 705f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp0; 706f2bbc96eSHarald Freudenberger } 707f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 708f2bbc96eSHarald Freudenberger minhwtype, cur_mkvp, old_mkvp, 1); 709f2bbc96eSHarald Freudenberger if (rc) 710f2bbc96eSHarald Freudenberger goto out; 711f2bbc96eSHarald Freudenberger if (apqns) { 712f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 713f2bbc96eSHarald Freudenberger rc = -ENOSPC; 714f2bbc96eSHarald Freudenberger else 715f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 716f2bbc96eSHarald Freudenberger } 717f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 718f2bbc96eSHarald Freudenberger } 719f2bbc96eSHarald Freudenberger 720f2bbc96eSHarald Freudenberger out: 721f2bbc96eSHarald Freudenberger kfree(_apqns); 722f2bbc96eSHarald Freudenberger return rc; 723f2bbc96eSHarald Freudenberger } 724f2bbc96eSHarald Freudenberger 725f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype, 726f2bbc96eSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 727f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 728f2bbc96eSHarald Freudenberger { 729f2bbc96eSHarald Freudenberger int rc = -EINVAL; 730f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 731f2bbc96eSHarald Freudenberger 732f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 733f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 734f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 735f2bbc96eSHarald Freudenberger 736f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 737f2bbc96eSHarald Freudenberger cur_mkvp = *((u64 *) cur_mkvp); 738f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 739f2bbc96eSHarald Freudenberger old_mkvp = *((u64 *) alt_mkvp); 740f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 741f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 742f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 743f2bbc96eSHarald Freudenberger minhwtype, cur_mkvp, old_mkvp, 1); 744f2bbc96eSHarald Freudenberger if (rc) 745f2bbc96eSHarald Freudenberger goto out; 746f2bbc96eSHarald Freudenberger if (apqns) { 747f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 748f2bbc96eSHarald Freudenberger rc = -ENOSPC; 749f2bbc96eSHarald Freudenberger else 750f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 751f2bbc96eSHarald Freudenberger } 752f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 753f2bbc96eSHarald Freudenberger } 754f2bbc96eSHarald Freudenberger 755f2bbc96eSHarald Freudenberger out: 756f2bbc96eSHarald Freudenberger kfree(_apqns); 757f2bbc96eSHarald Freudenberger return rc; 758f2bbc96eSHarald Freudenberger } 759fb1136d6SIngo Franzki 760fb1136d6SIngo Franzki /* 761e80d4af0SHarald Freudenberger * File io functions 762e80d4af0SHarald Freudenberger */ 763e80d4af0SHarald Freudenberger 764f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen) 765f2bbc96eSHarald Freudenberger { 766f2bbc96eSHarald Freudenberger if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) 767f2bbc96eSHarald Freudenberger return ERR_PTR(-EINVAL); 768f2bbc96eSHarald Freudenberger 7698b57e7c8SMarkus Elfring return memdup_user(ukey, keylen); 770f2bbc96eSHarald Freudenberger } 771f2bbc96eSHarald Freudenberger 772f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 773f2bbc96eSHarald Freudenberger { 7748b57e7c8SMarkus Elfring if (!uapqns || nr_apqns == 0) 7758b57e7c8SMarkus Elfring return NULL; 776f2bbc96eSHarald Freudenberger 7778b57e7c8SMarkus Elfring return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); 778f2bbc96eSHarald Freudenberger } 779f2bbc96eSHarald Freudenberger 780e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 781e80d4af0SHarald Freudenberger unsigned long arg) 782e80d4af0SHarald Freudenberger { 783e80d4af0SHarald Freudenberger int rc; 784e80d4af0SHarald Freudenberger 785e80d4af0SHarald Freudenberger switch (cmd) { 786e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 787e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *) arg; 788e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 789e80d4af0SHarald Freudenberger 790e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 791e80d4af0SHarald Freudenberger return -EFAULT; 792efc598e6SHarald Freudenberger rc = cca_genseckey(kgs.cardnr, kgs.domain, 793efc598e6SHarald Freudenberger kgs.keytype, kgs.seckey.seckey); 794efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 795e80d4af0SHarald Freudenberger if (rc) 796e80d4af0SHarald Freudenberger break; 797e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 798e80d4af0SHarald Freudenberger return -EFAULT; 799e80d4af0SHarald Freudenberger break; 800e80d4af0SHarald Freudenberger } 801e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 802e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *) arg; 803e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 804e80d4af0SHarald Freudenberger 805e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 806e80d4af0SHarald Freudenberger return -EFAULT; 807efc598e6SHarald Freudenberger rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 808efc598e6SHarald Freudenberger kcs.clrkey.clrkey, kcs.seckey.seckey); 809efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 810e80d4af0SHarald Freudenberger if (rc) 811e80d4af0SHarald Freudenberger break; 812e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 813e80d4af0SHarald Freudenberger return -EFAULT; 814e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 815e80d4af0SHarald Freudenberger break; 816e80d4af0SHarald Freudenberger } 817e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 818e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *) arg; 819e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 820e80d4af0SHarald Freudenberger 821e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 822e80d4af0SHarald Freudenberger return -EFAULT; 823efc598e6SHarald Freudenberger rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 824efc598e6SHarald Freudenberger ksp.seckey.seckey, ksp.protkey.protkey, 825efc598e6SHarald Freudenberger NULL, &ksp.protkey.type); 826efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 827e80d4af0SHarald Freudenberger if (rc) 828e80d4af0SHarald Freudenberger break; 829e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 830e80d4af0SHarald Freudenberger return -EFAULT; 831e80d4af0SHarald Freudenberger break; 832e80d4af0SHarald Freudenberger } 833e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 834e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *) arg; 835e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 836e80d4af0SHarald Freudenberger 837e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 838e80d4af0SHarald Freudenberger return -EFAULT; 839e80d4af0SHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, 840e80d4af0SHarald Freudenberger &kcp.clrkey, &kcp.protkey); 841ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 842e80d4af0SHarald Freudenberger if (rc) 843e80d4af0SHarald Freudenberger break; 844e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 845e80d4af0SHarald Freudenberger return -EFAULT; 846e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 847e80d4af0SHarald Freudenberger break; 848e80d4af0SHarald Freudenberger } 849e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 850e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *) arg; 851e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 852e80d4af0SHarald Freudenberger 853e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 854e80d4af0SHarald Freudenberger return -EFAULT; 855efc598e6SHarald Freudenberger rc = cca_findcard(kfc.seckey.seckey, 856e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 857efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 858efc598e6SHarald Freudenberger if (rc < 0) 859e80d4af0SHarald Freudenberger break; 860e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 861e80d4af0SHarald Freudenberger return -EFAULT; 862e80d4af0SHarald Freudenberger break; 863e80d4af0SHarald Freudenberger } 864e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 865e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *) arg; 866e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 867e80d4af0SHarald Freudenberger 868e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 869e80d4af0SHarald Freudenberger return -EFAULT; 870f2bbc96eSHarald Freudenberger rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey); 871ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 872e80d4af0SHarald Freudenberger if (rc) 873e80d4af0SHarald Freudenberger break; 874e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 875e80d4af0SHarald Freudenberger return -EFAULT; 876e80d4af0SHarald Freudenberger break; 877e80d4af0SHarald Freudenberger } 878e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 879e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *) arg; 880e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 881e61a6134SHarald Freudenberger 882e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 883e61a6134SHarald Freudenberger return -EFAULT; 884e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 885e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 886ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 887e61a6134SHarald Freudenberger if (rc) 888e61a6134SHarald Freudenberger break; 889e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 890e61a6134SHarald Freudenberger return -EFAULT; 891e61a6134SHarald Freudenberger break; 892e61a6134SHarald Freudenberger } 893a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 894a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *) arg; 895a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 896a45a5c7dSIngo Franzki 897a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 898a45a5c7dSIngo Franzki return -EFAULT; 899a45a5c7dSIngo Franzki rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); 900a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 901a45a5c7dSIngo Franzki if (rc) 902a45a5c7dSIngo Franzki break; 903a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 904a45a5c7dSIngo Franzki return -EFAULT; 905a45a5c7dSIngo Franzki break; 906a45a5c7dSIngo Franzki } 907cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 908cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *) arg; 909cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 910cb26b9ffSIngo Franzki 911cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 912cb26b9ffSIngo Franzki return -EFAULT; 913cb26b9ffSIngo Franzki rc = pkey_verifyprotkey(&kvp.protkey); 914cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 915cb26b9ffSIngo Franzki break; 916cb26b9ffSIngo Franzki } 917fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 918fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *) arg; 919fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 920183cb469SHarald Freudenberger u8 *kkey; 921fb1136d6SIngo Franzki 922fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 923fb1136d6SIngo Franzki return -EFAULT; 924f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 925f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 926f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 927fb1136d6SIngo Franzki rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); 928fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 929fb1136d6SIngo Franzki kfree(kkey); 930fb1136d6SIngo Franzki if (rc) 931fb1136d6SIngo Franzki break; 932fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 933fb1136d6SIngo Franzki return -EFAULT; 934fb1136d6SIngo Franzki break; 935fb1136d6SIngo Franzki } 936f2bbc96eSHarald Freudenberger case PKEY_GENSECK2: { 937f2bbc96eSHarald Freudenberger struct pkey_genseck2 __user *ugs = (void __user *) arg; 938f2bbc96eSHarald Freudenberger struct pkey_genseck2 kgs; 939f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 940f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 941f2bbc96eSHarald Freudenberger u8 *kkey; 942f2bbc96eSHarald Freudenberger 943f2bbc96eSHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 944f2bbc96eSHarald Freudenberger return -EFAULT; 945f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 946f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 947f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 948f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 949f2bbc96eSHarald Freudenberger if (!kkey) { 950f2bbc96eSHarald Freudenberger kfree(apqns); 951f2bbc96eSHarald Freudenberger return -ENOMEM; 952f2bbc96eSHarald Freudenberger } 953f2bbc96eSHarald Freudenberger rc = pkey_genseckey2(apqns, kgs.apqn_entries, 954f2bbc96eSHarald Freudenberger kgs.type, kgs.size, kgs.keygenflags, 955f2bbc96eSHarald Freudenberger kkey, &klen); 956f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 957f2bbc96eSHarald Freudenberger kfree(apqns); 958f2bbc96eSHarald Freudenberger if (rc) { 959f2bbc96eSHarald Freudenberger kfree(kkey); 960f2bbc96eSHarald Freudenberger break; 961f2bbc96eSHarald Freudenberger } 962f2bbc96eSHarald Freudenberger if (kgs.key) { 963f2bbc96eSHarald Freudenberger if (kgs.keylen < klen) { 964f2bbc96eSHarald Freudenberger kfree(kkey); 965f2bbc96eSHarald Freudenberger return -EINVAL; 966f2bbc96eSHarald Freudenberger } 967f2bbc96eSHarald Freudenberger if (copy_to_user(kgs.key, kkey, klen)) { 968f2bbc96eSHarald Freudenberger kfree(kkey); 969f2bbc96eSHarald Freudenberger return -EFAULT; 970f2bbc96eSHarald Freudenberger } 971f2bbc96eSHarald Freudenberger } 972f2bbc96eSHarald Freudenberger kgs.keylen = klen; 973f2bbc96eSHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 974f2bbc96eSHarald Freudenberger rc = -EFAULT; 975f2bbc96eSHarald Freudenberger kfree(kkey); 976f2bbc96eSHarald Freudenberger break; 977f2bbc96eSHarald Freudenberger } 978f2bbc96eSHarald Freudenberger case PKEY_CLR2SECK2: { 979f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 __user *ucs = (void __user *) arg; 980f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 kcs; 981f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 982f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 983f2bbc96eSHarald Freudenberger u8 *kkey; 984f2bbc96eSHarald Freudenberger 985f2bbc96eSHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 986f2bbc96eSHarald Freudenberger return -EFAULT; 987f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 988f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 989f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 990f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 991f2bbc96eSHarald Freudenberger if (!kkey) { 992f2bbc96eSHarald Freudenberger kfree(apqns); 993f2bbc96eSHarald Freudenberger return -ENOMEM; 994f2bbc96eSHarald Freudenberger } 995f2bbc96eSHarald Freudenberger rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 996f2bbc96eSHarald Freudenberger kcs.type, kcs.size, kcs.keygenflags, 997f2bbc96eSHarald Freudenberger kcs.clrkey.clrkey, kkey, &klen); 998f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 999f2bbc96eSHarald Freudenberger kfree(apqns); 1000f2bbc96eSHarald Freudenberger if (rc) { 1001f2bbc96eSHarald Freudenberger kfree(kkey); 1002f2bbc96eSHarald Freudenberger break; 1003f2bbc96eSHarald Freudenberger } 1004f2bbc96eSHarald Freudenberger if (kcs.key) { 1005f2bbc96eSHarald Freudenberger if (kcs.keylen < klen) { 1006f2bbc96eSHarald Freudenberger kfree(kkey); 1007f2bbc96eSHarald Freudenberger return -EINVAL; 1008f2bbc96eSHarald Freudenberger } 1009f2bbc96eSHarald Freudenberger if (copy_to_user(kcs.key, kkey, klen)) { 1010f2bbc96eSHarald Freudenberger kfree(kkey); 1011f2bbc96eSHarald Freudenberger return -EFAULT; 1012f2bbc96eSHarald Freudenberger } 1013f2bbc96eSHarald Freudenberger } 1014f2bbc96eSHarald Freudenberger kcs.keylen = klen; 1015f2bbc96eSHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1016f2bbc96eSHarald Freudenberger rc = -EFAULT; 1017f2bbc96eSHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1018f2bbc96eSHarald Freudenberger kfree(kkey); 1019f2bbc96eSHarald Freudenberger break; 1020f2bbc96eSHarald Freudenberger } 1021f2bbc96eSHarald Freudenberger case PKEY_VERIFYKEY2: { 1022f2bbc96eSHarald Freudenberger struct pkey_verifykey2 __user *uvk = (void __user *) arg; 1023f2bbc96eSHarald Freudenberger struct pkey_verifykey2 kvk; 1024f2bbc96eSHarald Freudenberger u8 *kkey; 1025f2bbc96eSHarald Freudenberger 1026f2bbc96eSHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1027f2bbc96eSHarald Freudenberger return -EFAULT; 1028f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kvk.key, kvk.keylen); 1029f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1030f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1031f2bbc96eSHarald Freudenberger rc = pkey_verifykey2(kkey, kvk.keylen, 1032f2bbc96eSHarald Freudenberger &kvk.cardnr, &kvk.domain, 1033f2bbc96eSHarald Freudenberger &kvk.type, &kvk.size, &kvk.flags); 1034f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 1035f2bbc96eSHarald Freudenberger kfree(kkey); 1036f2bbc96eSHarald Freudenberger if (rc) 1037f2bbc96eSHarald Freudenberger break; 1038f2bbc96eSHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1039f2bbc96eSHarald Freudenberger return -EFAULT; 1040f2bbc96eSHarald Freudenberger break; 1041f2bbc96eSHarald Freudenberger } 1042f2bbc96eSHarald Freudenberger case PKEY_KBLOB2PROTK2: { 1043f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 __user *utp = (void __user *) arg; 1044f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 ktp; 1045f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1046f2bbc96eSHarald Freudenberger u8 *kkey; 1047f2bbc96eSHarald Freudenberger 1048f2bbc96eSHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1049f2bbc96eSHarald Freudenberger return -EFAULT; 1050f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1051f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1052f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1053f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1054f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1055f2bbc96eSHarald Freudenberger kfree(apqns); 1056f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1057f2bbc96eSHarald Freudenberger } 1058f2bbc96eSHarald Freudenberger rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 1059f2bbc96eSHarald Freudenberger kkey, ktp.keylen, &ktp.protkey); 1060f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 1061f2bbc96eSHarald Freudenberger kfree(apqns); 1062f2bbc96eSHarald Freudenberger kfree(kkey); 1063f2bbc96eSHarald Freudenberger if (rc) 1064f2bbc96eSHarald Freudenberger break; 1065f2bbc96eSHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1066f2bbc96eSHarald Freudenberger return -EFAULT; 1067f2bbc96eSHarald Freudenberger break; 1068f2bbc96eSHarald Freudenberger } 1069f2bbc96eSHarald Freudenberger case PKEY_APQNS4K: { 1070f2bbc96eSHarald Freudenberger struct pkey_apqns4key __user *uak = (void __user *) arg; 1071f2bbc96eSHarald Freudenberger struct pkey_apqns4key kak; 1072f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1073f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1074f2bbc96eSHarald Freudenberger u8 *kkey; 1075f2bbc96eSHarald Freudenberger 1076f2bbc96eSHarald Freudenberger if (copy_from_user(&kak, uak, sizeof(kak))) 1077f2bbc96eSHarald Freudenberger return -EFAULT; 1078f2bbc96eSHarald Freudenberger nr_apqns = kak.apqn_entries; 1079f2bbc96eSHarald Freudenberger if (nr_apqns) { 1080f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1081f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1082f2bbc96eSHarald Freudenberger GFP_KERNEL); 1083f2bbc96eSHarald Freudenberger if (!apqns) 1084f2bbc96eSHarald Freudenberger return -ENOMEM; 1085f2bbc96eSHarald Freudenberger } 1086f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kak.key, kak.keylen); 1087f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1088f2bbc96eSHarald Freudenberger kfree(apqns); 1089f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1090f2bbc96eSHarald Freudenberger } 1091f2bbc96eSHarald Freudenberger rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 1092f2bbc96eSHarald Freudenberger apqns, &nr_apqns); 1093f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 1094f2bbc96eSHarald Freudenberger kfree(kkey); 1095f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1096f2bbc96eSHarald Freudenberger kfree(apqns); 1097f2bbc96eSHarald Freudenberger break; 1098f2bbc96eSHarald Freudenberger } 1099f2bbc96eSHarald Freudenberger if (!rc && kak.apqns) { 1100f2bbc96eSHarald Freudenberger if (nr_apqns > kak.apqn_entries) { 1101f2bbc96eSHarald Freudenberger kfree(apqns); 1102f2bbc96eSHarald Freudenberger return -EINVAL; 1103f2bbc96eSHarald Freudenberger } 1104f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1105f2bbc96eSHarald Freudenberger if (len) { 1106f2bbc96eSHarald Freudenberger if (copy_to_user(kak.apqns, apqns, len)) { 1107f2bbc96eSHarald Freudenberger kfree(apqns); 1108f2bbc96eSHarald Freudenberger return -EFAULT; 1109f2bbc96eSHarald Freudenberger } 1110f2bbc96eSHarald Freudenberger } 1111f2bbc96eSHarald Freudenberger } 1112f2bbc96eSHarald Freudenberger kak.apqn_entries = nr_apqns; 1113f2bbc96eSHarald Freudenberger if (copy_to_user(uak, &kak, sizeof(kak))) 1114f2bbc96eSHarald Freudenberger rc = -EFAULT; 1115f2bbc96eSHarald Freudenberger kfree(apqns); 1116f2bbc96eSHarald Freudenberger break; 1117f2bbc96eSHarald Freudenberger } 1118f2bbc96eSHarald Freudenberger case PKEY_APQNS4KT: { 1119f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype __user *uat = (void __user *) arg; 1120f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype kat; 1121f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1122f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1123f2bbc96eSHarald Freudenberger 1124f2bbc96eSHarald Freudenberger if (copy_from_user(&kat, uat, sizeof(kat))) 1125f2bbc96eSHarald Freudenberger return -EFAULT; 1126f2bbc96eSHarald Freudenberger nr_apqns = kat.apqn_entries; 1127f2bbc96eSHarald Freudenberger if (nr_apqns) { 1128f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1129f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1130f2bbc96eSHarald Freudenberger GFP_KERNEL); 1131f2bbc96eSHarald Freudenberger if (!apqns) 1132f2bbc96eSHarald Freudenberger return -ENOMEM; 1133f2bbc96eSHarald Freudenberger } 1134f2bbc96eSHarald Freudenberger rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 1135f2bbc96eSHarald Freudenberger kat.flags, apqns, &nr_apqns); 1136f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 1137f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1138f2bbc96eSHarald Freudenberger kfree(apqns); 1139f2bbc96eSHarald Freudenberger break; 1140f2bbc96eSHarald Freudenberger } 1141f2bbc96eSHarald Freudenberger if (!rc && kat.apqns) { 1142f2bbc96eSHarald Freudenberger if (nr_apqns > kat.apqn_entries) { 1143f2bbc96eSHarald Freudenberger kfree(apqns); 1144f2bbc96eSHarald Freudenberger return -EINVAL; 1145f2bbc96eSHarald Freudenberger } 1146f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1147f2bbc96eSHarald Freudenberger if (len) { 1148f2bbc96eSHarald Freudenberger if (copy_to_user(kat.apqns, apqns, len)) { 1149f2bbc96eSHarald Freudenberger kfree(apqns); 1150f2bbc96eSHarald Freudenberger return -EFAULT; 1151f2bbc96eSHarald Freudenberger } 1152f2bbc96eSHarald Freudenberger } 1153f2bbc96eSHarald Freudenberger } 1154f2bbc96eSHarald Freudenberger kat.apqn_entries = nr_apqns; 1155f2bbc96eSHarald Freudenberger if (copy_to_user(uat, &kat, sizeof(kat))) 1156f2bbc96eSHarald Freudenberger rc = -EFAULT; 1157f2bbc96eSHarald Freudenberger kfree(apqns); 1158f2bbc96eSHarald Freudenberger break; 1159f2bbc96eSHarald Freudenberger } 1160e80d4af0SHarald Freudenberger default: 1161e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1162e80d4af0SHarald Freudenberger return -ENOTTY; 1163e80d4af0SHarald Freudenberger } 1164e80d4af0SHarald Freudenberger 1165e80d4af0SHarald Freudenberger return rc; 1166e80d4af0SHarald Freudenberger } 1167e80d4af0SHarald Freudenberger 1168e80d4af0SHarald Freudenberger /* 1169e80d4af0SHarald Freudenberger * Sysfs and file io operations 1170e80d4af0SHarald Freudenberger */ 1171d632c047SIngo Franzki 1172d632c047SIngo Franzki /* 1173d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1174d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1175d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1176d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1177d632c047SIngo Franzki */ 1178d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1179d632c047SIngo Franzki loff_t off, size_t count) 1180d632c047SIngo Franzki { 1181d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1182d632c047SIngo Franzki struct pkey_protkey protkey; 1183d632c047SIngo Franzki int rc; 1184d632c047SIngo Franzki 1185d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1186d632c047SIngo Franzki return -EINVAL; 1187d632c047SIngo Franzki if (is_xts) 1188d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1189d632c047SIngo Franzki return -EINVAL; 1190d632c047SIngo Franzki 1191d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1192d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1193d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1194d632c047SIngo Franzki protkeytoken.keytype = keytype; 1195d632c047SIngo Franzki 1196d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1197d632c047SIngo Franzki if (rc) 1198d632c047SIngo Franzki return rc; 1199d632c047SIngo Franzki 1200d632c047SIngo Franzki protkeytoken.len = protkey.len; 1201d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1202d632c047SIngo Franzki 1203d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1204d632c047SIngo Franzki 1205d632c047SIngo Franzki if (is_xts) { 1206d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1207d632c047SIngo Franzki if (rc) 1208d632c047SIngo Franzki return rc; 1209d632c047SIngo Franzki 1210d632c047SIngo Franzki protkeytoken.len = protkey.len; 1211d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1212d632c047SIngo Franzki 1213d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1214d632c047SIngo Franzki sizeof(protkeytoken)); 1215d632c047SIngo Franzki 1216d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1217d632c047SIngo Franzki } 1218d632c047SIngo Franzki 1219d632c047SIngo Franzki return sizeof(protkeytoken); 1220d632c047SIngo Franzki } 1221d632c047SIngo Franzki 1222d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1223d632c047SIngo Franzki struct kobject *kobj, 1224d632c047SIngo Franzki struct bin_attribute *attr, 1225d632c047SIngo Franzki char *buf, loff_t off, 1226d632c047SIngo Franzki size_t count) 1227d632c047SIngo Franzki { 1228d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1229d632c047SIngo Franzki off, count); 1230d632c047SIngo Franzki } 1231d632c047SIngo Franzki 1232d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1233d632c047SIngo Franzki struct kobject *kobj, 1234d632c047SIngo Franzki struct bin_attribute *attr, 1235d632c047SIngo Franzki char *buf, loff_t off, 1236d632c047SIngo Franzki size_t count) 1237d632c047SIngo Franzki { 1238d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1239d632c047SIngo Franzki off, count); 1240d632c047SIngo Franzki } 1241d632c047SIngo Franzki 1242d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1243d632c047SIngo Franzki struct kobject *kobj, 1244d632c047SIngo Franzki struct bin_attribute *attr, 1245d632c047SIngo Franzki char *buf, loff_t off, 1246d632c047SIngo Franzki size_t count) 1247d632c047SIngo Franzki { 1248d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1249d632c047SIngo Franzki off, count); 1250d632c047SIngo Franzki } 1251d632c047SIngo Franzki 1252d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1253d632c047SIngo Franzki struct kobject *kobj, 1254d632c047SIngo Franzki struct bin_attribute *attr, 1255d632c047SIngo Franzki char *buf, loff_t off, 1256d632c047SIngo Franzki size_t count) 1257d632c047SIngo Franzki { 1258d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1259d632c047SIngo Franzki off, count); 1260d632c047SIngo Franzki } 1261d632c047SIngo Franzki 1262d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1263d632c047SIngo Franzki struct kobject *kobj, 1264d632c047SIngo Franzki struct bin_attribute *attr, 1265d632c047SIngo Franzki char *buf, loff_t off, 1266d632c047SIngo Franzki size_t count) 1267d632c047SIngo Franzki { 1268d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1269d632c047SIngo Franzki off, count); 1270d632c047SIngo Franzki } 1271d632c047SIngo Franzki 1272d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1273d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1274d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1275d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1276d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1277d632c047SIngo Franzki 1278d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1279d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1280d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1281d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1282d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1283d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1284d632c047SIngo Franzki NULL 1285d632c047SIngo Franzki }; 1286d632c047SIngo Franzki 1287d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1288d632c047SIngo Franzki .name = "protkey", 1289d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1290d632c047SIngo Franzki }; 1291d632c047SIngo Franzki 1292af504452SIngo Franzki /* 1293af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1294af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1295af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1296af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1297af504452SIngo Franzki */ 1298af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1299af504452SIngo Franzki loff_t off, size_t count) 1300af504452SIngo Franzki { 1301af504452SIngo Franzki int rc; 1302efc598e6SHarald Freudenberger struct pkey_seckey *seckey = (struct pkey_seckey *) buf; 1303af504452SIngo Franzki 1304af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1305af504452SIngo Franzki return -EINVAL; 1306af504452SIngo Franzki if (is_xts) 1307af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1308af504452SIngo Franzki return -EINVAL; 1309af504452SIngo Franzki 1310efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1311af504452SIngo Franzki if (rc) 1312af504452SIngo Franzki return rc; 1313af504452SIngo Franzki 1314af504452SIngo Franzki if (is_xts) { 1315efc598e6SHarald Freudenberger seckey++; 1316efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1317af504452SIngo Franzki if (rc) 1318af504452SIngo Franzki return rc; 1319af504452SIngo Franzki 1320af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1321af504452SIngo Franzki } 1322af504452SIngo Franzki 1323af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1324af504452SIngo Franzki } 1325af504452SIngo Franzki 1326af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1327af504452SIngo Franzki struct kobject *kobj, 1328af504452SIngo Franzki struct bin_attribute *attr, 1329af504452SIngo Franzki char *buf, loff_t off, 1330af504452SIngo Franzki size_t count) 1331af504452SIngo Franzki { 1332af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1333af504452SIngo Franzki off, count); 1334af504452SIngo Franzki } 1335af504452SIngo Franzki 1336af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1337af504452SIngo Franzki struct kobject *kobj, 1338af504452SIngo Franzki struct bin_attribute *attr, 1339af504452SIngo Franzki char *buf, loff_t off, 1340af504452SIngo Franzki size_t count) 1341af504452SIngo Franzki { 1342af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1343af504452SIngo Franzki off, count); 1344af504452SIngo Franzki } 1345af504452SIngo Franzki 1346af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1347af504452SIngo Franzki struct kobject *kobj, 1348af504452SIngo Franzki struct bin_attribute *attr, 1349af504452SIngo Franzki char *buf, loff_t off, 1350af504452SIngo Franzki size_t count) 1351af504452SIngo Franzki { 1352af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1353af504452SIngo Franzki off, count); 1354af504452SIngo Franzki } 1355af504452SIngo Franzki 1356af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1357af504452SIngo Franzki struct kobject *kobj, 1358af504452SIngo Franzki struct bin_attribute *attr, 1359af504452SIngo Franzki char *buf, loff_t off, 1360af504452SIngo Franzki size_t count) 1361af504452SIngo Franzki { 1362af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1363af504452SIngo Franzki off, count); 1364af504452SIngo Franzki } 1365af504452SIngo Franzki 1366af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1367af504452SIngo Franzki struct kobject *kobj, 1368af504452SIngo Franzki struct bin_attribute *attr, 1369af504452SIngo Franzki char *buf, loff_t off, 1370af504452SIngo Franzki size_t count) 1371af504452SIngo Franzki { 1372af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1373af504452SIngo Franzki off, count); 1374af504452SIngo Franzki } 1375af504452SIngo Franzki 1376af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1377af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1378af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1379af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1380af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1381af504452SIngo Franzki 1382af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1383af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1384af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1385af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1386af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1387af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1388af504452SIngo Franzki NULL 1389af504452SIngo Franzki }; 1390af504452SIngo Franzki 1391af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1392af504452SIngo Franzki .name = "ccadata", 1393af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1394af504452SIngo Franzki }; 1395af504452SIngo Franzki 1396f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) 1397f71fee27SIngo Franzki 1398f71fee27SIngo Franzki /* 1399f71fee27SIngo Franzki * Sysfs attribute read function for all secure key ccacipher binary attributes. 1400f71fee27SIngo Franzki * The implementation can not deal with partial reads, because a new random 1401f71fee27SIngo Franzki * secure key blob is generated with each read. In case of partial reads 1402f71fee27SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1403f71fee27SIngo Franzki */ 1404f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, 1405f71fee27SIngo Franzki bool is_xts, char *buf, loff_t off, 1406f71fee27SIngo Franzki size_t count) 1407f71fee27SIngo Franzki { 1408f71fee27SIngo Franzki size_t keysize; 1409f71fee27SIngo Franzki int rc; 1410f71fee27SIngo Franzki 1411f71fee27SIngo Franzki if (off != 0 || count < CCACIPHERTOKENSIZE) 1412f71fee27SIngo Franzki return -EINVAL; 1413f71fee27SIngo Franzki if (is_xts) 1414f71fee27SIngo Franzki if (count < 2 * CCACIPHERTOKENSIZE) 1415f71fee27SIngo Franzki return -EINVAL; 1416f71fee27SIngo Franzki 1417f71fee27SIngo Franzki keysize = CCACIPHERTOKENSIZE; 1418f71fee27SIngo Franzki rc = cca_gencipherkey(-1, -1, keybits, 0, buf, &keysize); 1419f71fee27SIngo Franzki if (rc) 1420f71fee27SIngo Franzki return rc; 1421f71fee27SIngo Franzki memset(buf + keysize, 0, CCACIPHERTOKENSIZE - keysize); 1422f71fee27SIngo Franzki 1423f71fee27SIngo Franzki if (is_xts) { 1424f71fee27SIngo Franzki keysize = CCACIPHERTOKENSIZE; 1425f71fee27SIngo Franzki rc = cca_gencipherkey(-1, -1, keybits, 0, 1426f71fee27SIngo Franzki buf + CCACIPHERTOKENSIZE, &keysize); 1427f71fee27SIngo Franzki if (rc) 1428f71fee27SIngo Franzki return rc; 1429f71fee27SIngo Franzki memset(buf + CCACIPHERTOKENSIZE + keysize, 0, 1430f71fee27SIngo Franzki CCACIPHERTOKENSIZE - keysize); 1431f71fee27SIngo Franzki 1432f71fee27SIngo Franzki return 2 * CCACIPHERTOKENSIZE; 1433f71fee27SIngo Franzki } 1434f71fee27SIngo Franzki 1435f71fee27SIngo Franzki return CCACIPHERTOKENSIZE; 1436f71fee27SIngo Franzki } 1437f71fee27SIngo Franzki 1438f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp, 1439f71fee27SIngo Franzki struct kobject *kobj, 1440f71fee27SIngo Franzki struct bin_attribute *attr, 1441f71fee27SIngo Franzki char *buf, loff_t off, 1442f71fee27SIngo Franzki size_t count) 1443f71fee27SIngo Franzki { 1444f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 1445f71fee27SIngo Franzki off, count); 1446f71fee27SIngo Franzki } 1447f71fee27SIngo Franzki 1448f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp, 1449f71fee27SIngo Franzki struct kobject *kobj, 1450f71fee27SIngo Franzki struct bin_attribute *attr, 1451f71fee27SIngo Franzki char *buf, loff_t off, 1452f71fee27SIngo Franzki size_t count) 1453f71fee27SIngo Franzki { 1454f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 1455f71fee27SIngo Franzki off, count); 1456f71fee27SIngo Franzki } 1457f71fee27SIngo Franzki 1458f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp, 1459f71fee27SIngo Franzki struct kobject *kobj, 1460f71fee27SIngo Franzki struct bin_attribute *attr, 1461f71fee27SIngo Franzki char *buf, loff_t off, 1462f71fee27SIngo Franzki size_t count) 1463f71fee27SIngo Franzki { 1464f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 1465f71fee27SIngo Franzki off, count); 1466f71fee27SIngo Franzki } 1467f71fee27SIngo Franzki 1468f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp, 1469f71fee27SIngo Franzki struct kobject *kobj, 1470f71fee27SIngo Franzki struct bin_attribute *attr, 1471f71fee27SIngo Franzki char *buf, loff_t off, 1472f71fee27SIngo Franzki size_t count) 1473f71fee27SIngo Franzki { 1474f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 1475f71fee27SIngo Franzki off, count); 1476f71fee27SIngo Franzki } 1477f71fee27SIngo Franzki 1478f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp, 1479f71fee27SIngo Franzki struct kobject *kobj, 1480f71fee27SIngo Franzki struct bin_attribute *attr, 1481f71fee27SIngo Franzki char *buf, loff_t off, 1482f71fee27SIngo Franzki size_t count) 1483f71fee27SIngo Franzki { 1484f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 1485f71fee27SIngo Franzki off, count); 1486f71fee27SIngo Franzki } 1487f71fee27SIngo Franzki 1488f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); 1489f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); 1490f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); 1491f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); 1492f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); 1493f71fee27SIngo Franzki 1494f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = { 1495f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128, 1496f71fee27SIngo Franzki &bin_attr_ccacipher_aes_192, 1497f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256, 1498f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128_xts, 1499f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256_xts, 1500f71fee27SIngo Franzki NULL 1501f71fee27SIngo Franzki }; 1502f71fee27SIngo Franzki 1503f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = { 1504f71fee27SIngo Franzki .name = "ccacipher", 1505f71fee27SIngo Franzki .bin_attrs = ccacipher_attrs, 1506f71fee27SIngo Franzki }; 1507f71fee27SIngo Franzki 1508d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 1509d632c047SIngo Franzki &protkey_attr_group, 1510af504452SIngo Franzki &ccadata_attr_group, 1511f71fee27SIngo Franzki &ccacipher_attr_group, 1512d632c047SIngo Franzki NULL, 1513d632c047SIngo Franzki }; 1514d632c047SIngo Franzki 1515e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 1516e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 1517e80d4af0SHarald Freudenberger .open = nonseekable_open, 1518e80d4af0SHarald Freudenberger .llseek = no_llseek, 1519e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 1520e80d4af0SHarald Freudenberger }; 1521e80d4af0SHarald Freudenberger 1522e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 1523e80d4af0SHarald Freudenberger .name = "pkey", 1524e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 1525e80d4af0SHarald Freudenberger .mode = 0666, 1526e80d4af0SHarald Freudenberger .fops = &pkey_fops, 1527d632c047SIngo Franzki .groups = pkey_attr_groups, 1528e80d4af0SHarald Freudenberger }; 1529e80d4af0SHarald Freudenberger 1530e80d4af0SHarald Freudenberger /* 1531e80d4af0SHarald Freudenberger * Module init 1532e80d4af0SHarald Freudenberger */ 1533cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 1534e80d4af0SHarald Freudenberger { 1535f822ad2cSHarald Freudenberger cpacf_mask_t kmc_functions; 1536e80d4af0SHarald Freudenberger 1537f822ad2cSHarald Freudenberger /* 1538f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 1539f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 1540f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 1541f822ad2cSHarald Freudenberger * are able to work with protected keys. 1542f822ad2cSHarald Freudenberger */ 1543e80d4af0SHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 154458443b67SDavid Hildenbrand return -ENODEV; 1545e80d4af0SHarald Freudenberger 1546cb26b9ffSIngo Franzki /* check for kmc instructions available */ 1547cb26b9ffSIngo Franzki if (!cpacf_query(CPACF_KMC, &kmc_functions)) 154858443b67SDavid Hildenbrand return -ENODEV; 1549cb26b9ffSIngo Franzki if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) || 1550cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) || 1551cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) 155258443b67SDavid Hildenbrand return -ENODEV; 1553cb26b9ffSIngo Franzki 1554e80d4af0SHarald Freudenberger pkey_debug_init(); 1555e80d4af0SHarald Freudenberger 1556e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 1557e80d4af0SHarald Freudenberger } 1558e80d4af0SHarald Freudenberger 1559e80d4af0SHarald Freudenberger /* 1560e80d4af0SHarald Freudenberger * Module exit 1561e80d4af0SHarald Freudenberger */ 1562e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 1563e80d4af0SHarald Freudenberger { 1564e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 1565e80d4af0SHarald Freudenberger pkey_debug_exit(); 1566e80d4af0SHarald Freudenberger } 1567e80d4af0SHarald Freudenberger 156863c19be0SIngo Franzki module_cpu_feature_match(MSA, pkey_init); 1569e80d4af0SHarald Freudenberger module_exit(pkey_exit); 1570