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