1812141a9SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2e80d4af0SHarald Freudenberger /* 3e80d4af0SHarald Freudenberger * pkey device driver 4e80d4af0SHarald Freudenberger * 5e80d4af0SHarald Freudenberger * Copyright IBM Corp. 2017 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> 20e80d4af0SHarald Freudenberger #include <asm/zcrypt.h> 21e80d4af0SHarald Freudenberger #include <asm/cpacf.h> 22e80d4af0SHarald Freudenberger #include <asm/pkey.h> 23*cb26b9ffSIngo Franzki #include <crypto/aes.h> 24e80d4af0SHarald Freudenberger 25e80d4af0SHarald Freudenberger #include "zcrypt_api.h" 26e80d4af0SHarald Freudenberger 27e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL"); 28e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 29e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface"); 30e80d4af0SHarald Freudenberger 31e80d4af0SHarald Freudenberger /* Size of parameter block used for all cca requests/replies */ 32e80d4af0SHarald Freudenberger #define PARMBSIZE 512 33e80d4af0SHarald Freudenberger 34e80d4af0SHarald Freudenberger /* Size of vardata block used for some of the cca requests/replies */ 35e80d4af0SHarald Freudenberger #define VARDATASIZE 4096 36e80d4af0SHarald Freudenberger 37e80d4af0SHarald Freudenberger /* 38e80d4af0SHarald Freudenberger * debug feature data and functions 39e80d4af0SHarald Freudenberger */ 40e80d4af0SHarald Freudenberger 41e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 42e80d4af0SHarald Freudenberger 43e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 44e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 45e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 46e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 47e80d4af0SHarald Freudenberger 48e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 49e80d4af0SHarald Freudenberger { 50e80d4af0SHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 4 * sizeof(long)); 51e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 52e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 53e80d4af0SHarald Freudenberger } 54e80d4af0SHarald Freudenberger 55e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 56e80d4af0SHarald Freudenberger { 57e80d4af0SHarald Freudenberger debug_unregister(debug_info); 58e80d4af0SHarald Freudenberger } 59e80d4af0SHarald Freudenberger 600534bde7SIngo Franzki /* Key token types */ 610534bde7SIngo Franzki #define TOKTYPE_NON_CCA 0x00 /* Non-CCA key token */ 620534bde7SIngo Franzki #define TOKTYPE_CCA_INTERNAL 0x01 /* CCA internal key token */ 630534bde7SIngo Franzki 640534bde7SIngo Franzki /* For TOKTYPE_NON_CCA: */ 650534bde7SIngo Franzki #define TOKVER_PROTECTED_KEY 0x01 /* Protected key token */ 660534bde7SIngo Franzki 670534bde7SIngo Franzki /* For TOKTYPE_CCA_INTERNAL: */ 680534bde7SIngo Franzki #define TOKVER_CCA_AES 0x04 /* CCA AES key token */ 690534bde7SIngo Franzki 70e80d4af0SHarald Freudenberger /* inside view of a secure key token (only type 0x01 version 0x04) */ 71e80d4af0SHarald Freudenberger struct secaeskeytoken { 72e80d4af0SHarald Freudenberger u8 type; /* 0x01 for internal key token */ 73e80d4af0SHarald Freudenberger u8 res0[3]; 74e80d4af0SHarald Freudenberger u8 version; /* should be 0x04 */ 75e80d4af0SHarald Freudenberger u8 res1[1]; 76e80d4af0SHarald Freudenberger u8 flag; /* key flags */ 77e80d4af0SHarald Freudenberger u8 res2[1]; 78e80d4af0SHarald Freudenberger u64 mkvp; /* master key verification pattern */ 79e80d4af0SHarald Freudenberger u8 key[32]; /* key value (encrypted) */ 80e80d4af0SHarald Freudenberger u8 cv[8]; /* control vector */ 81e80d4af0SHarald Freudenberger u16 bitsize; /* key bit size */ 82e80d4af0SHarald Freudenberger u16 keysize; /* key byte size */ 83e80d4af0SHarald Freudenberger u8 tvv[4]; /* token validation value */ 84e80d4af0SHarald Freudenberger } __packed; 85e80d4af0SHarald Freudenberger 860534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */ 870534bde7SIngo Franzki struct protaeskeytoken { 880534bde7SIngo Franzki u8 type; /* 0x00 for PAES specific key tokens */ 890534bde7SIngo Franzki u8 res0[3]; 900534bde7SIngo Franzki u8 version; /* should be 0x01 for protected AES key token */ 910534bde7SIngo Franzki u8 res1[3]; 920534bde7SIngo Franzki u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 930534bde7SIngo Franzki u32 len; /* bytes actually stored in protkey[] */ 940534bde7SIngo Franzki u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 950534bde7SIngo Franzki } __packed; 960534bde7SIngo Franzki 97e80d4af0SHarald Freudenberger /* 98e80d4af0SHarald Freudenberger * Simple check if the token is a valid CCA secure AES key 99e80d4af0SHarald Freudenberger * token. If keybitsize is given, the bitsize of the key is 100e80d4af0SHarald Freudenberger * also checked. Returns 0 on success or errno value on failure. 101e80d4af0SHarald Freudenberger */ 102e61a6134SHarald Freudenberger static int check_secaeskeytoken(const u8 *token, int keybitsize) 103e80d4af0SHarald Freudenberger { 104e80d4af0SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) token; 105e80d4af0SHarald Freudenberger 1060534bde7SIngo Franzki if (t->type != TOKTYPE_CCA_INTERNAL) { 107e80d4af0SHarald Freudenberger DEBUG_ERR( 1080534bde7SIngo Franzki "%s secure token check failed, type mismatch 0x%02x != 0x%02x\n", 1090534bde7SIngo Franzki __func__, (int) t->type, TOKTYPE_CCA_INTERNAL); 110e80d4af0SHarald Freudenberger return -EINVAL; 111e80d4af0SHarald Freudenberger } 1120534bde7SIngo Franzki if (t->version != TOKVER_CCA_AES) { 113e80d4af0SHarald Freudenberger DEBUG_ERR( 1140534bde7SIngo Franzki "%s secure token check failed, version mismatch 0x%02x != 0x%02x\n", 1150534bde7SIngo Franzki __func__, (int) t->version, TOKVER_CCA_AES); 116e80d4af0SHarald Freudenberger return -EINVAL; 117e80d4af0SHarald Freudenberger } 118e80d4af0SHarald Freudenberger if (keybitsize > 0 && t->bitsize != keybitsize) { 119e80d4af0SHarald Freudenberger DEBUG_ERR( 120ac2b96f3SHarald Freudenberger "%s secure token check failed, bitsize mismatch %d != %d\n", 121ac2b96f3SHarald Freudenberger __func__, (int) t->bitsize, keybitsize); 122e80d4af0SHarald Freudenberger return -EINVAL; 123e80d4af0SHarald Freudenberger } 124e80d4af0SHarald Freudenberger 125e80d4af0SHarald Freudenberger return 0; 126e80d4af0SHarald Freudenberger } 127e80d4af0SHarald Freudenberger 128e80d4af0SHarald Freudenberger /* 129e80d4af0SHarald Freudenberger * Allocate consecutive memory for request CPRB, request param 130e80d4af0SHarald Freudenberger * block, reply CPRB and reply param block and fill in values 131e80d4af0SHarald Freudenberger * for the common fields. Returns 0 on success or errno value 132e80d4af0SHarald Freudenberger * on failure. 133e80d4af0SHarald Freudenberger */ 134e80d4af0SHarald Freudenberger static int alloc_and_prep_cprbmem(size_t paramblen, 135e80d4af0SHarald Freudenberger u8 **pcprbmem, 136e80d4af0SHarald Freudenberger struct CPRBX **preqCPRB, 137e80d4af0SHarald Freudenberger struct CPRBX **prepCPRB) 138e80d4af0SHarald Freudenberger { 139e80d4af0SHarald Freudenberger u8 *cprbmem; 140e80d4af0SHarald Freudenberger size_t cprbplusparamblen = sizeof(struct CPRBX) + paramblen; 141e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 142e80d4af0SHarald Freudenberger 143e80d4af0SHarald Freudenberger /* 144e80d4af0SHarald Freudenberger * allocate consecutive memory for request CPRB, request param 145e80d4af0SHarald Freudenberger * block, reply CPRB and reply param block 146e80d4af0SHarald Freudenberger */ 1476396bb22SKees Cook cprbmem = kcalloc(2, cprbplusparamblen, GFP_KERNEL); 148e80d4af0SHarald Freudenberger if (!cprbmem) 149e80d4af0SHarald Freudenberger return -ENOMEM; 150e80d4af0SHarald Freudenberger 151e80d4af0SHarald Freudenberger preqcblk = (struct CPRBX *) cprbmem; 152e80d4af0SHarald Freudenberger prepcblk = (struct CPRBX *) (cprbmem + cprbplusparamblen); 153e80d4af0SHarald Freudenberger 154e80d4af0SHarald Freudenberger /* fill request cprb struct */ 155e80d4af0SHarald Freudenberger preqcblk->cprb_len = sizeof(struct CPRBX); 156e80d4af0SHarald Freudenberger preqcblk->cprb_ver_id = 0x02; 157e80d4af0SHarald Freudenberger memcpy(preqcblk->func_id, "T2", 2); 158e80d4af0SHarald Freudenberger preqcblk->rpl_msgbl = cprbplusparamblen; 159e80d4af0SHarald Freudenberger if (paramblen) { 160e80d4af0SHarald Freudenberger preqcblk->req_parmb = 161e80d4af0SHarald Freudenberger ((u8 *) preqcblk) + sizeof(struct CPRBX); 162e80d4af0SHarald Freudenberger preqcblk->rpl_parmb = 163e80d4af0SHarald Freudenberger ((u8 *) prepcblk) + sizeof(struct CPRBX); 164e80d4af0SHarald Freudenberger } 165e80d4af0SHarald Freudenberger 166e80d4af0SHarald Freudenberger *pcprbmem = cprbmem; 167e80d4af0SHarald Freudenberger *preqCPRB = preqcblk; 168e80d4af0SHarald Freudenberger *prepCPRB = prepcblk; 169e80d4af0SHarald Freudenberger 170e80d4af0SHarald Freudenberger return 0; 171e80d4af0SHarald Freudenberger } 172e80d4af0SHarald Freudenberger 173e80d4af0SHarald Freudenberger /* 174e80d4af0SHarald Freudenberger * Free the cprb memory allocated with the function above. 175e80d4af0SHarald Freudenberger * If the scrub value is not zero, the memory is filled 176e80d4af0SHarald Freudenberger * with zeros before freeing (useful if there was some 177e80d4af0SHarald Freudenberger * clear key material in there). 178e80d4af0SHarald Freudenberger */ 179e80d4af0SHarald Freudenberger static void free_cprbmem(void *mem, size_t paramblen, int scrub) 180e80d4af0SHarald Freudenberger { 181e80d4af0SHarald Freudenberger if (scrub) 182e80d4af0SHarald Freudenberger memzero_explicit(mem, 2 * (sizeof(struct CPRBX) + paramblen)); 183e80d4af0SHarald Freudenberger kfree(mem); 184e80d4af0SHarald Freudenberger } 185e80d4af0SHarald Freudenberger 186e80d4af0SHarald Freudenberger /* 187e80d4af0SHarald Freudenberger * Helper function to prepare the xcrb struct 188e80d4af0SHarald Freudenberger */ 189e80d4af0SHarald Freudenberger static inline void prep_xcrb(struct ica_xcRB *pxcrb, 190e80d4af0SHarald Freudenberger u16 cardnr, 191e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, 192e80d4af0SHarald Freudenberger struct CPRBX *prepcblk) 193e80d4af0SHarald Freudenberger { 194e80d4af0SHarald Freudenberger memset(pxcrb, 0, sizeof(*pxcrb)); 195e80d4af0SHarald Freudenberger pxcrb->agent_ID = 0x4341; /* 'CA' */ 196e80d4af0SHarald Freudenberger pxcrb->user_defined = (cardnr == 0xFFFF ? AUTOSELECT : cardnr); 197e80d4af0SHarald Freudenberger pxcrb->request_control_blk_length = 198e80d4af0SHarald Freudenberger preqcblk->cprb_len + preqcblk->req_parml; 1997a003637SHeiko Carstens pxcrb->request_control_blk_addr = (void __user *) preqcblk; 200e80d4af0SHarald Freudenberger pxcrb->reply_control_blk_length = preqcblk->rpl_msgbl; 2017a003637SHeiko Carstens pxcrb->reply_control_blk_addr = (void __user *) prepcblk; 202e80d4af0SHarald Freudenberger } 203e80d4af0SHarald Freudenberger 204e80d4af0SHarald Freudenberger /* 205e80d4af0SHarald Freudenberger * Helper function which calls zcrypt_send_cprb with 206e80d4af0SHarald Freudenberger * memory management segment adjusted to kernel space 207e80d4af0SHarald Freudenberger * so that the copy_from_user called within this 208e80d4af0SHarald Freudenberger * function do in fact copy from kernel space. 209e80d4af0SHarald Freudenberger */ 210e80d4af0SHarald Freudenberger static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb) 211e80d4af0SHarald Freudenberger { 212e80d4af0SHarald Freudenberger int rc; 213e80d4af0SHarald Freudenberger mm_segment_t old_fs = get_fs(); 214e80d4af0SHarald Freudenberger 215e80d4af0SHarald Freudenberger set_fs(KERNEL_DS); 216e80d4af0SHarald Freudenberger rc = zcrypt_send_cprb(xcrb); 217e80d4af0SHarald Freudenberger set_fs(old_fs); 218e80d4af0SHarald Freudenberger 219e80d4af0SHarald Freudenberger return rc; 220e80d4af0SHarald Freudenberger } 221e80d4af0SHarald Freudenberger 222e80d4af0SHarald Freudenberger /* 223e80d4af0SHarald Freudenberger * Generate (random) AES secure key. 224e80d4af0SHarald Freudenberger */ 225e80d4af0SHarald Freudenberger int pkey_genseckey(u16 cardnr, u16 domain, 226e80d4af0SHarald Freudenberger u32 keytype, struct pkey_seckey *seckey) 227e80d4af0SHarald Freudenberger { 228e80d4af0SHarald Freudenberger int i, rc, keysize; 229e80d4af0SHarald Freudenberger int seckeysize; 230e80d4af0SHarald Freudenberger u8 *mem; 231e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 232e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 233e80d4af0SHarald Freudenberger struct kgreqparm { 234e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 235e80d4af0SHarald Freudenberger u16 rule_array_len; 236e80d4af0SHarald Freudenberger struct lv1 { 237e80d4af0SHarald Freudenberger u16 len; 238e80d4af0SHarald Freudenberger char key_form[8]; 239e80d4af0SHarald Freudenberger char key_length[8]; 240e80d4af0SHarald Freudenberger char key_type1[8]; 241e80d4af0SHarald Freudenberger char key_type2[8]; 242e80d4af0SHarald Freudenberger } lv1; 243e80d4af0SHarald Freudenberger struct lv2 { 244e80d4af0SHarald Freudenberger u16 len; 245e80d4af0SHarald Freudenberger struct keyid { 246e80d4af0SHarald Freudenberger u16 len; 247e80d4af0SHarald Freudenberger u16 attr; 248e80d4af0SHarald Freudenberger u8 data[SECKEYBLOBSIZE]; 249e80d4af0SHarald Freudenberger } keyid[6]; 250e80d4af0SHarald Freudenberger } lv2; 251e80d4af0SHarald Freudenberger } *preqparm; 252e80d4af0SHarald Freudenberger struct kgrepparm { 253e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 254e80d4af0SHarald Freudenberger u16 rule_array_len; 255e80d4af0SHarald Freudenberger struct lv3 { 256e80d4af0SHarald Freudenberger u16 len; 257e80d4af0SHarald Freudenberger u16 keyblocklen; 258e80d4af0SHarald Freudenberger struct { 259e80d4af0SHarald Freudenberger u16 toklen; 260e80d4af0SHarald Freudenberger u16 tokattr; 261e80d4af0SHarald Freudenberger u8 tok[0]; 262e80d4af0SHarald Freudenberger /* ... some more data ... */ 263e80d4af0SHarald Freudenberger } keyblock; 264e80d4af0SHarald Freudenberger } lv3; 265e80d4af0SHarald Freudenberger } *prepparm; 266e80d4af0SHarald Freudenberger 267e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 268e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 269e80d4af0SHarald Freudenberger if (rc) 270e80d4af0SHarald Freudenberger return rc; 271e80d4af0SHarald Freudenberger 272e80d4af0SHarald Freudenberger /* fill request cprb struct */ 273e80d4af0SHarald Freudenberger preqcblk->domain = domain; 274e80d4af0SHarald Freudenberger 275e80d4af0SHarald Freudenberger /* fill request cprb param block with KG request */ 276e80d4af0SHarald Freudenberger preqparm = (struct kgreqparm *) preqcblk->req_parmb; 277e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "KG", 2); 278e80d4af0SHarald Freudenberger preqparm->rule_array_len = sizeof(preqparm->rule_array_len); 279e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1); 280e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_form, "OP ", 8); 281e80d4af0SHarald Freudenberger switch (keytype) { 282e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 283e80d4af0SHarald Freudenberger keysize = 16; 284e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN16 ", 8); 285e80d4af0SHarald Freudenberger break; 286e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 287e80d4af0SHarald Freudenberger keysize = 24; 288e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN24 ", 8); 289e80d4af0SHarald Freudenberger break; 290e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 291e80d4af0SHarald Freudenberger keysize = 32; 292e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN32 ", 8); 293e80d4af0SHarald Freudenberger break; 294e80d4af0SHarald Freudenberger default: 295e80d4af0SHarald Freudenberger DEBUG_ERR( 296ac2b96f3SHarald Freudenberger "%s unknown/unsupported keytype %d\n", 297ac2b96f3SHarald Freudenberger __func__, keytype); 298e80d4af0SHarald Freudenberger rc = -EINVAL; 299e80d4af0SHarald Freudenberger goto out; 300e80d4af0SHarald Freudenberger } 301e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_type1, "AESDATA ", 8); 302e80d4af0SHarald Freudenberger preqparm->lv2.len = sizeof(struct lv2); 303e80d4af0SHarald Freudenberger for (i = 0; i < 6; i++) { 304e80d4af0SHarald Freudenberger preqparm->lv2.keyid[i].len = sizeof(struct keyid); 305e80d4af0SHarald Freudenberger preqparm->lv2.keyid[i].attr = (i == 2 ? 0x30 : 0x10); 306e80d4af0SHarald Freudenberger } 307e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct kgreqparm); 308e80d4af0SHarald Freudenberger 309e80d4af0SHarald Freudenberger /* fill xcrb struct */ 310e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 311e80d4af0SHarald Freudenberger 312e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 313e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 314e80d4af0SHarald Freudenberger if (rc) { 315e80d4af0SHarald Freudenberger DEBUG_ERR( 316ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 317ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 318e80d4af0SHarald Freudenberger goto out; 319e80d4af0SHarald Freudenberger } 320e80d4af0SHarald Freudenberger 321e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 322e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 323e80d4af0SHarald Freudenberger DEBUG_ERR( 324ac2b96f3SHarald Freudenberger "%s secure key generate failure, card response %d/%d\n", 325ac2b96f3SHarald Freudenberger __func__, 326e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 327e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 328e80d4af0SHarald Freudenberger rc = -EIO; 329e80d4af0SHarald Freudenberger goto out; 330e80d4af0SHarald Freudenberger } 331e80d4af0SHarald Freudenberger 332e80d4af0SHarald Freudenberger /* process response cprb param block */ 333e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 334e80d4af0SHarald Freudenberger prepparm = (struct kgrepparm *) prepcblk->rpl_parmb; 335e80d4af0SHarald Freudenberger 336e80d4af0SHarald Freudenberger /* check length of the returned secure key token */ 337e80d4af0SHarald Freudenberger seckeysize = prepparm->lv3.keyblock.toklen 338e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.toklen) 339e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.tokattr); 340e80d4af0SHarald Freudenberger if (seckeysize != SECKEYBLOBSIZE) { 341e80d4af0SHarald Freudenberger DEBUG_ERR( 342ac2b96f3SHarald Freudenberger "%s secure token size mismatch %d != %d bytes\n", 343ac2b96f3SHarald Freudenberger __func__, seckeysize, SECKEYBLOBSIZE); 344e80d4af0SHarald Freudenberger rc = -EIO; 345e80d4af0SHarald Freudenberger goto out; 346e80d4af0SHarald Freudenberger } 347e80d4af0SHarald Freudenberger 348e80d4af0SHarald Freudenberger /* check secure key token */ 349e80d4af0SHarald Freudenberger rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); 350e80d4af0SHarald Freudenberger if (rc) { 351e80d4af0SHarald Freudenberger rc = -EIO; 352e80d4af0SHarald Freudenberger goto out; 353e80d4af0SHarald Freudenberger } 354e80d4af0SHarald Freudenberger 355e80d4af0SHarald Freudenberger /* copy the generated secure key token */ 356e80d4af0SHarald Freudenberger memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); 357e80d4af0SHarald Freudenberger 358e80d4af0SHarald Freudenberger out: 359e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 0); 360e80d4af0SHarald Freudenberger return rc; 361e80d4af0SHarald Freudenberger } 362e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_genseckey); 363e80d4af0SHarald Freudenberger 364e80d4af0SHarald Freudenberger /* 365e80d4af0SHarald Freudenberger * Generate an AES secure key with given key value. 366e80d4af0SHarald Freudenberger */ 367e80d4af0SHarald Freudenberger int pkey_clr2seckey(u16 cardnr, u16 domain, u32 keytype, 368e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 369e80d4af0SHarald Freudenberger struct pkey_seckey *seckey) 370e80d4af0SHarald Freudenberger { 371e80d4af0SHarald Freudenberger int rc, keysize, seckeysize; 372e80d4af0SHarald Freudenberger u8 *mem; 373e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 374e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 375e80d4af0SHarald Freudenberger struct cmreqparm { 376e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 377e80d4af0SHarald Freudenberger u16 rule_array_len; 378e80d4af0SHarald Freudenberger char rule_array[8]; 379e80d4af0SHarald Freudenberger struct lv1 { 380e80d4af0SHarald Freudenberger u16 len; 381e80d4af0SHarald Freudenberger u8 clrkey[0]; 382e80d4af0SHarald Freudenberger } lv1; 383e80d4af0SHarald Freudenberger struct lv2 { 384e80d4af0SHarald Freudenberger u16 len; 385e80d4af0SHarald Freudenberger struct keyid { 386e80d4af0SHarald Freudenberger u16 len; 387e80d4af0SHarald Freudenberger u16 attr; 388e80d4af0SHarald Freudenberger u8 data[SECKEYBLOBSIZE]; 389e80d4af0SHarald Freudenberger } keyid; 390e80d4af0SHarald Freudenberger } lv2; 391e80d4af0SHarald Freudenberger } *preqparm; 392e80d4af0SHarald Freudenberger struct lv2 *plv2; 393e80d4af0SHarald Freudenberger struct cmrepparm { 394e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 395e80d4af0SHarald Freudenberger u16 rule_array_len; 396e80d4af0SHarald Freudenberger struct lv3 { 397e80d4af0SHarald Freudenberger u16 len; 398e80d4af0SHarald Freudenberger u16 keyblocklen; 399e80d4af0SHarald Freudenberger struct { 400e80d4af0SHarald Freudenberger u16 toklen; 401e80d4af0SHarald Freudenberger u16 tokattr; 402e80d4af0SHarald Freudenberger u8 tok[0]; 403e80d4af0SHarald Freudenberger /* ... some more data ... */ 404e80d4af0SHarald Freudenberger } keyblock; 405e80d4af0SHarald Freudenberger } lv3; 406e80d4af0SHarald Freudenberger } *prepparm; 407e80d4af0SHarald Freudenberger 408e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 409e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 410e80d4af0SHarald Freudenberger if (rc) 411e80d4af0SHarald Freudenberger return rc; 412e80d4af0SHarald Freudenberger 413e80d4af0SHarald Freudenberger /* fill request cprb struct */ 414e80d4af0SHarald Freudenberger preqcblk->domain = domain; 415e80d4af0SHarald Freudenberger 416e80d4af0SHarald Freudenberger /* fill request cprb param block with CM request */ 417e80d4af0SHarald Freudenberger preqparm = (struct cmreqparm *) preqcblk->req_parmb; 418e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "CM", 2); 419e80d4af0SHarald Freudenberger memcpy(preqparm->rule_array, "AES ", 8); 420e80d4af0SHarald Freudenberger preqparm->rule_array_len = 421e80d4af0SHarald Freudenberger sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); 422e80d4af0SHarald Freudenberger switch (keytype) { 423e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 424e80d4af0SHarald Freudenberger keysize = 16; 425e80d4af0SHarald Freudenberger break; 426e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 427e80d4af0SHarald Freudenberger keysize = 24; 428e80d4af0SHarald Freudenberger break; 429e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 430e80d4af0SHarald Freudenberger keysize = 32; 431e80d4af0SHarald Freudenberger break; 432e80d4af0SHarald Freudenberger default: 433e80d4af0SHarald Freudenberger DEBUG_ERR( 434ac2b96f3SHarald Freudenberger "%s unknown/unsupported keytype %d\n", 435ac2b96f3SHarald Freudenberger __func__, keytype); 436e80d4af0SHarald Freudenberger rc = -EINVAL; 437e80d4af0SHarald Freudenberger goto out; 438e80d4af0SHarald Freudenberger } 439e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1) + keysize; 440e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.clrkey, clrkey->clrkey, keysize); 441e80d4af0SHarald Freudenberger plv2 = (struct lv2 *) (((u8 *) &preqparm->lv2) + keysize); 442e80d4af0SHarald Freudenberger plv2->len = sizeof(struct lv2); 443e80d4af0SHarald Freudenberger plv2->keyid.len = sizeof(struct keyid); 444e80d4af0SHarald Freudenberger plv2->keyid.attr = 0x30; 445e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct cmreqparm) + keysize; 446e80d4af0SHarald Freudenberger 447e80d4af0SHarald Freudenberger /* fill xcrb struct */ 448e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 449e80d4af0SHarald Freudenberger 450e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 451e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 452e80d4af0SHarald Freudenberger if (rc) { 453e80d4af0SHarald Freudenberger DEBUG_ERR( 454ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 455ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 456e80d4af0SHarald Freudenberger goto out; 457e80d4af0SHarald Freudenberger } 458e80d4af0SHarald Freudenberger 459e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 460e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 461e80d4af0SHarald Freudenberger DEBUG_ERR( 462ac2b96f3SHarald Freudenberger "%s clear key import failure, card response %d/%d\n", 463ac2b96f3SHarald Freudenberger __func__, 464e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 465e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 466e80d4af0SHarald Freudenberger rc = -EIO; 467e80d4af0SHarald Freudenberger goto out; 468e80d4af0SHarald Freudenberger } 469e80d4af0SHarald Freudenberger 470e80d4af0SHarald Freudenberger /* process response cprb param block */ 471e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 472e80d4af0SHarald Freudenberger prepparm = (struct cmrepparm *) prepcblk->rpl_parmb; 473e80d4af0SHarald Freudenberger 474e80d4af0SHarald Freudenberger /* check length of the returned secure key token */ 475e80d4af0SHarald Freudenberger seckeysize = prepparm->lv3.keyblock.toklen 476e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.toklen) 477e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.tokattr); 478e80d4af0SHarald Freudenberger if (seckeysize != SECKEYBLOBSIZE) { 479e80d4af0SHarald Freudenberger DEBUG_ERR( 480ac2b96f3SHarald Freudenberger "%s secure token size mismatch %d != %d bytes\n", 481ac2b96f3SHarald Freudenberger __func__, seckeysize, SECKEYBLOBSIZE); 482e80d4af0SHarald Freudenberger rc = -EIO; 483e80d4af0SHarald Freudenberger goto out; 484e80d4af0SHarald Freudenberger } 485e80d4af0SHarald Freudenberger 486e80d4af0SHarald Freudenberger /* check secure key token */ 487e80d4af0SHarald Freudenberger rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); 488e80d4af0SHarald Freudenberger if (rc) { 489e80d4af0SHarald Freudenberger rc = -EIO; 490e80d4af0SHarald Freudenberger goto out; 491e80d4af0SHarald Freudenberger } 492e80d4af0SHarald Freudenberger 493e80d4af0SHarald Freudenberger /* copy the generated secure key token */ 494e80d4af0SHarald Freudenberger memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); 495e80d4af0SHarald Freudenberger 496e80d4af0SHarald Freudenberger out: 497e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 1); 498e80d4af0SHarald Freudenberger return rc; 499e80d4af0SHarald Freudenberger } 500e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_clr2seckey); 501e80d4af0SHarald Freudenberger 502e80d4af0SHarald Freudenberger /* 503e80d4af0SHarald Freudenberger * Derive a proteced key from the secure key blob. 504e80d4af0SHarald Freudenberger */ 505e80d4af0SHarald Freudenberger int pkey_sec2protkey(u16 cardnr, u16 domain, 506e80d4af0SHarald Freudenberger const struct pkey_seckey *seckey, 507e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 508e80d4af0SHarald Freudenberger { 509e80d4af0SHarald Freudenberger int rc; 510e80d4af0SHarald Freudenberger u8 *mem; 511e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 512e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 513e80d4af0SHarald Freudenberger struct uskreqparm { 514e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 515e80d4af0SHarald Freudenberger u16 rule_array_len; 516e80d4af0SHarald Freudenberger struct lv1 { 517e80d4af0SHarald Freudenberger u16 len; 518e80d4af0SHarald Freudenberger u16 attr_len; 519e80d4af0SHarald Freudenberger u16 attr_flags; 520e80d4af0SHarald Freudenberger } lv1; 521e80d4af0SHarald Freudenberger struct lv2 { 522e80d4af0SHarald Freudenberger u16 len; 523e80d4af0SHarald Freudenberger u16 attr_len; 524e80d4af0SHarald Freudenberger u16 attr_flags; 525e80d4af0SHarald Freudenberger u8 token[0]; /* cca secure key token */ 526e80d4af0SHarald Freudenberger } lv2 __packed; 527e80d4af0SHarald Freudenberger } *preqparm; 528e80d4af0SHarald Freudenberger struct uskrepparm { 529e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 530e80d4af0SHarald Freudenberger u16 rule_array_len; 531e80d4af0SHarald Freudenberger struct lv3 { 532e80d4af0SHarald Freudenberger u16 len; 533e80d4af0SHarald Freudenberger u16 attr_len; 534e80d4af0SHarald Freudenberger u16 attr_flags; 535e80d4af0SHarald Freudenberger struct cpacfkeyblock { 536e80d4af0SHarald Freudenberger u8 version; /* version of this struct */ 537e80d4af0SHarald Freudenberger u8 flags[2]; 538e80d4af0SHarald Freudenberger u8 algo; 539e80d4af0SHarald Freudenberger u8 form; 540e80d4af0SHarald Freudenberger u8 pad1[3]; 541e80d4af0SHarald Freudenberger u16 keylen; 542e80d4af0SHarald Freudenberger u8 key[64]; /* the key (keylen bytes) */ 543e80d4af0SHarald Freudenberger u16 keyattrlen; 544e80d4af0SHarald Freudenberger u8 keyattr[32]; 545e80d4af0SHarald Freudenberger u8 pad2[1]; 546e80d4af0SHarald Freudenberger u8 vptype; 547e80d4af0SHarald Freudenberger u8 vp[32]; /* verification pattern */ 548e80d4af0SHarald Freudenberger } keyblock; 549e80d4af0SHarald Freudenberger } lv3 __packed; 550e80d4af0SHarald Freudenberger } *prepparm; 551e80d4af0SHarald Freudenberger 552e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 553e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 554e80d4af0SHarald Freudenberger if (rc) 555e80d4af0SHarald Freudenberger return rc; 556e80d4af0SHarald Freudenberger 557e80d4af0SHarald Freudenberger /* fill request cprb struct */ 558e80d4af0SHarald Freudenberger preqcblk->domain = domain; 559e80d4af0SHarald Freudenberger 560e80d4af0SHarald Freudenberger /* fill request cprb param block with USK request */ 561e80d4af0SHarald Freudenberger preqparm = (struct uskreqparm *) preqcblk->req_parmb; 562e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "US", 2); 563e80d4af0SHarald Freudenberger preqparm->rule_array_len = sizeof(preqparm->rule_array_len); 564e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1); 565e80d4af0SHarald Freudenberger preqparm->lv1.attr_len = sizeof(struct lv1) - sizeof(preqparm->lv1.len); 566e80d4af0SHarald Freudenberger preqparm->lv1.attr_flags = 0x0001; 567e80d4af0SHarald Freudenberger preqparm->lv2.len = sizeof(struct lv2) + SECKEYBLOBSIZE; 568e80d4af0SHarald Freudenberger preqparm->lv2.attr_len = sizeof(struct lv2) 569e80d4af0SHarald Freudenberger - sizeof(preqparm->lv2.len) + SECKEYBLOBSIZE; 570e80d4af0SHarald Freudenberger preqparm->lv2.attr_flags = 0x0000; 571e80d4af0SHarald Freudenberger memcpy(preqparm->lv2.token, seckey->seckey, SECKEYBLOBSIZE); 572e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct uskreqparm) + SECKEYBLOBSIZE; 573e80d4af0SHarald Freudenberger 574e80d4af0SHarald Freudenberger /* fill xcrb struct */ 575e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 576e80d4af0SHarald Freudenberger 577e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 578e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 579e80d4af0SHarald Freudenberger if (rc) { 580e80d4af0SHarald Freudenberger DEBUG_ERR( 581ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 582ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 583e80d4af0SHarald Freudenberger goto out; 584e80d4af0SHarald Freudenberger } 585e80d4af0SHarald Freudenberger 586e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 587e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 588e80d4af0SHarald Freudenberger DEBUG_ERR( 589ac2b96f3SHarald Freudenberger "%s unwrap secure key failure, card response %d/%d\n", 590ac2b96f3SHarald Freudenberger __func__, 591e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 592e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 593e80d4af0SHarald Freudenberger rc = -EIO; 594e80d4af0SHarald Freudenberger goto out; 595e80d4af0SHarald Freudenberger } 596ca681ec8SHarald Freudenberger if (prepcblk->ccp_rscode != 0) { 597ca681ec8SHarald Freudenberger DEBUG_WARN( 598ac2b96f3SHarald Freudenberger "%s unwrap secure key warning, card response %d/%d\n", 599ac2b96f3SHarald Freudenberger __func__, 600ca681ec8SHarald Freudenberger (int) prepcblk->ccp_rtcode, 601ca681ec8SHarald Freudenberger (int) prepcblk->ccp_rscode); 602ca681ec8SHarald Freudenberger } 603e80d4af0SHarald Freudenberger 604e80d4af0SHarald Freudenberger /* process response cprb param block */ 605e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 606e80d4af0SHarald Freudenberger prepparm = (struct uskrepparm *) prepcblk->rpl_parmb; 607e80d4af0SHarald Freudenberger 608e80d4af0SHarald Freudenberger /* check the returned keyblock */ 609e80d4af0SHarald Freudenberger if (prepparm->lv3.keyblock.version != 0x01) { 610e80d4af0SHarald Freudenberger DEBUG_ERR( 611ac2b96f3SHarald Freudenberger "%s reply param keyblock version mismatch 0x%02x != 0x01\n", 612ac2b96f3SHarald Freudenberger __func__, (int) prepparm->lv3.keyblock.version); 613e80d4af0SHarald Freudenberger rc = -EIO; 614e80d4af0SHarald Freudenberger goto out; 615e80d4af0SHarald Freudenberger } 616e80d4af0SHarald Freudenberger 617e80d4af0SHarald Freudenberger /* copy the tanslated protected key */ 618e80d4af0SHarald Freudenberger switch (prepparm->lv3.keyblock.keylen) { 619e80d4af0SHarald Freudenberger case 16+32: 620e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_128; 621e80d4af0SHarald Freudenberger break; 622e80d4af0SHarald Freudenberger case 24+32: 623e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_192; 624e80d4af0SHarald Freudenberger break; 625e80d4af0SHarald Freudenberger case 32+32: 626e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_256; 627e80d4af0SHarald Freudenberger break; 628e80d4af0SHarald Freudenberger default: 629ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 630ac2b96f3SHarald Freudenberger __func__, prepparm->lv3.keyblock.keylen); 631e80d4af0SHarald Freudenberger rc = -EIO; 632e80d4af0SHarald Freudenberger goto out; 633e80d4af0SHarald Freudenberger } 634e80d4af0SHarald Freudenberger protkey->len = prepparm->lv3.keyblock.keylen; 635e80d4af0SHarald Freudenberger memcpy(protkey->protkey, prepparm->lv3.keyblock.key, protkey->len); 636e80d4af0SHarald Freudenberger 637e80d4af0SHarald Freudenberger out: 638e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 0); 639e80d4af0SHarald Freudenberger return rc; 640e80d4af0SHarald Freudenberger } 641e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_sec2protkey); 642e80d4af0SHarald Freudenberger 643e80d4af0SHarald Freudenberger /* 644e80d4af0SHarald Freudenberger * Create a protected key from a clear key value. 645e80d4af0SHarald Freudenberger */ 646e80d4af0SHarald Freudenberger int pkey_clr2protkey(u32 keytype, 647e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 648e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 649e80d4af0SHarald Freudenberger { 650e80d4af0SHarald Freudenberger long fc; 651e80d4af0SHarald Freudenberger int keysize; 652e80d4af0SHarald Freudenberger u8 paramblock[64]; 653e80d4af0SHarald Freudenberger 654e80d4af0SHarald Freudenberger switch (keytype) { 655e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 656e80d4af0SHarald Freudenberger keysize = 16; 657e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 658e80d4af0SHarald Freudenberger break; 659e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 660e80d4af0SHarald Freudenberger keysize = 24; 661e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 662e80d4af0SHarald Freudenberger break; 663e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 664e80d4af0SHarald Freudenberger keysize = 32; 665e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 666e80d4af0SHarald Freudenberger break; 667e80d4af0SHarald Freudenberger default: 668ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 669ac2b96f3SHarald Freudenberger __func__, keytype); 670e80d4af0SHarald Freudenberger return -EINVAL; 671e80d4af0SHarald Freudenberger } 672e80d4af0SHarald Freudenberger 673e80d4af0SHarald Freudenberger /* prepare param block */ 674e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 675e80d4af0SHarald Freudenberger memcpy(paramblock, clrkey->clrkey, keysize); 676e80d4af0SHarald Freudenberger 677e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 678e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 679e80d4af0SHarald Freudenberger 680e80d4af0SHarald Freudenberger /* copy created protected key */ 681e80d4af0SHarald Freudenberger protkey->type = keytype; 682e80d4af0SHarald Freudenberger protkey->len = keysize + 32; 683e80d4af0SHarald Freudenberger memcpy(protkey->protkey, paramblock, keysize + 32); 684e80d4af0SHarald Freudenberger 685e80d4af0SHarald Freudenberger return 0; 686e80d4af0SHarald Freudenberger } 687e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_clr2protkey); 688e80d4af0SHarald Freudenberger 689e80d4af0SHarald Freudenberger /* 690e80d4af0SHarald Freudenberger * query cryptographic facility from adapter 691e80d4af0SHarald Freudenberger */ 692e80d4af0SHarald Freudenberger static int query_crypto_facility(u16 cardnr, u16 domain, 693e80d4af0SHarald Freudenberger const char *keyword, 694e80d4af0SHarald Freudenberger u8 *rarray, size_t *rarraylen, 695e80d4af0SHarald Freudenberger u8 *varray, size_t *varraylen) 696e80d4af0SHarald Freudenberger { 697e80d4af0SHarald Freudenberger int rc; 698e80d4af0SHarald Freudenberger u16 len; 699e80d4af0SHarald Freudenberger u8 *mem, *ptr; 700e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 701e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 702e80d4af0SHarald Freudenberger struct fqreqparm { 703e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 704e80d4af0SHarald Freudenberger u16 rule_array_len; 705e80d4af0SHarald Freudenberger char rule_array[8]; 706e80d4af0SHarald Freudenberger struct lv1 { 707e80d4af0SHarald Freudenberger u16 len; 708e80d4af0SHarald Freudenberger u8 data[VARDATASIZE]; 709e80d4af0SHarald Freudenberger } lv1; 710e80d4af0SHarald Freudenberger u16 dummylen; 711e80d4af0SHarald Freudenberger } *preqparm; 712e80d4af0SHarald Freudenberger size_t parmbsize = sizeof(struct fqreqparm); 713e80d4af0SHarald Freudenberger struct fqrepparm { 714e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 715e80d4af0SHarald Freudenberger u8 lvdata[0]; 716e80d4af0SHarald Freudenberger } *prepparm; 717e80d4af0SHarald Freudenberger 718e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 719e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(parmbsize, &mem, &preqcblk, &prepcblk); 720e80d4af0SHarald Freudenberger if (rc) 721e80d4af0SHarald Freudenberger return rc; 722e80d4af0SHarald Freudenberger 723e80d4af0SHarald Freudenberger /* fill request cprb struct */ 724e80d4af0SHarald Freudenberger preqcblk->domain = domain; 725e80d4af0SHarald Freudenberger 726e80d4af0SHarald Freudenberger /* fill request cprb param block with FQ request */ 727e80d4af0SHarald Freudenberger preqparm = (struct fqreqparm *) preqcblk->req_parmb; 728e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "FQ", 2); 729a09baa95SVasily Gorbik memcpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); 730e80d4af0SHarald Freudenberger preqparm->rule_array_len = 731e80d4af0SHarald Freudenberger sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); 732e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(preqparm->lv1); 733e80d4af0SHarald Freudenberger preqparm->dummylen = sizeof(preqparm->dummylen); 734e80d4af0SHarald Freudenberger preqcblk->req_parml = parmbsize; 735e80d4af0SHarald Freudenberger 736e80d4af0SHarald Freudenberger /* fill xcrb struct */ 737e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 738e80d4af0SHarald Freudenberger 739e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 740e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 741e80d4af0SHarald Freudenberger if (rc) { 742e80d4af0SHarald Freudenberger DEBUG_ERR( 743ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 744ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 745e80d4af0SHarald Freudenberger goto out; 746e80d4af0SHarald Freudenberger } 747e80d4af0SHarald Freudenberger 748e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 749e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 750e80d4af0SHarald Freudenberger DEBUG_ERR( 751ac2b96f3SHarald Freudenberger "%s unwrap secure key failure, card response %d/%d\n", 752ac2b96f3SHarald Freudenberger __func__, 753e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 754e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 755e80d4af0SHarald Freudenberger rc = -EIO; 756e80d4af0SHarald Freudenberger goto out; 757e80d4af0SHarald Freudenberger } 758e80d4af0SHarald Freudenberger 759e80d4af0SHarald Freudenberger /* process response cprb param block */ 760e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 761e80d4af0SHarald Freudenberger prepparm = (struct fqrepparm *) prepcblk->rpl_parmb; 762e80d4af0SHarald Freudenberger ptr = prepparm->lvdata; 763e80d4af0SHarald Freudenberger 764e80d4af0SHarald Freudenberger /* check and possibly copy reply rule array */ 765e80d4af0SHarald Freudenberger len = *((u16 *) ptr); 766e80d4af0SHarald Freudenberger if (len > sizeof(u16)) { 767e80d4af0SHarald Freudenberger ptr += sizeof(u16); 768e80d4af0SHarald Freudenberger len -= sizeof(u16); 769e80d4af0SHarald Freudenberger if (rarray && rarraylen && *rarraylen > 0) { 770e80d4af0SHarald Freudenberger *rarraylen = (len > *rarraylen ? *rarraylen : len); 771e80d4af0SHarald Freudenberger memcpy(rarray, ptr, *rarraylen); 772e80d4af0SHarald Freudenberger } 773e80d4af0SHarald Freudenberger ptr += len; 774e80d4af0SHarald Freudenberger } 775e80d4af0SHarald Freudenberger /* check and possible copy reply var array */ 776e80d4af0SHarald Freudenberger len = *((u16 *) ptr); 777e80d4af0SHarald Freudenberger if (len > sizeof(u16)) { 778e80d4af0SHarald Freudenberger ptr += sizeof(u16); 779e80d4af0SHarald Freudenberger len -= sizeof(u16); 780e80d4af0SHarald Freudenberger if (varray && varraylen && *varraylen > 0) { 781e80d4af0SHarald Freudenberger *varraylen = (len > *varraylen ? *varraylen : len); 782e80d4af0SHarald Freudenberger memcpy(varray, ptr, *varraylen); 783e80d4af0SHarald Freudenberger } 784e80d4af0SHarald Freudenberger ptr += len; 785e80d4af0SHarald Freudenberger } 786e80d4af0SHarald Freudenberger 787e80d4af0SHarald Freudenberger out: 788e80d4af0SHarald Freudenberger free_cprbmem(mem, parmbsize, 0); 789e80d4af0SHarald Freudenberger return rc; 790e80d4af0SHarald Freudenberger } 791e80d4af0SHarald Freudenberger 792e80d4af0SHarald Freudenberger /* 793ca681ec8SHarald Freudenberger * Fetch the current and old mkvp values via 794ca681ec8SHarald Freudenberger * query_crypto_facility from adapter. 795e80d4af0SHarald Freudenberger */ 796ca681ec8SHarald Freudenberger static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) 797e80d4af0SHarald Freudenberger { 798e80d4af0SHarald Freudenberger int rc, found = 0; 799e80d4af0SHarald Freudenberger size_t rlen, vlen; 800e80d4af0SHarald Freudenberger u8 *rarray, *varray, *pg; 801e80d4af0SHarald Freudenberger 802e80d4af0SHarald Freudenberger pg = (u8 *) __get_free_page(GFP_KERNEL); 803e80d4af0SHarald Freudenberger if (!pg) 804e80d4af0SHarald Freudenberger return -ENOMEM; 805e80d4af0SHarald Freudenberger rarray = pg; 806e80d4af0SHarald Freudenberger varray = pg + PAGE_SIZE/2; 807e80d4af0SHarald Freudenberger rlen = vlen = PAGE_SIZE/2; 808e80d4af0SHarald Freudenberger 809e80d4af0SHarald Freudenberger rc = query_crypto_facility(cardnr, domain, "STATICSA", 810e80d4af0SHarald Freudenberger rarray, &rlen, varray, &vlen); 811e80d4af0SHarald Freudenberger if (rc == 0 && rlen > 8*8 && vlen > 184+8) { 812ca681ec8SHarald Freudenberger if (rarray[8*8] == '2') { 813e80d4af0SHarald Freudenberger /* current master key state is valid */ 814ca681ec8SHarald Freudenberger mkvp[0] = *((u64 *)(varray + 184)); 815ca681ec8SHarald Freudenberger mkvp[1] = *((u64 *)(varray + 172)); 816e80d4af0SHarald Freudenberger found = 1; 817e80d4af0SHarald Freudenberger } 818e80d4af0SHarald Freudenberger } 819e80d4af0SHarald Freudenberger 820e80d4af0SHarald Freudenberger free_page((unsigned long) pg); 821e80d4af0SHarald Freudenberger 822e80d4af0SHarald Freudenberger return found ? 0 : -ENOENT; 823e80d4af0SHarald Freudenberger } 824e80d4af0SHarald Freudenberger 825e80d4af0SHarald Freudenberger /* struct to hold cached mkvp info for each card/domain */ 826e80d4af0SHarald Freudenberger struct mkvp_info { 827e80d4af0SHarald Freudenberger struct list_head list; 828e80d4af0SHarald Freudenberger u16 cardnr; 829e80d4af0SHarald Freudenberger u16 domain; 830ca681ec8SHarald Freudenberger u64 mkvp[2]; 831e80d4af0SHarald Freudenberger }; 832e80d4af0SHarald Freudenberger 833e80d4af0SHarald Freudenberger /* a list with mkvp_info entries */ 834e80d4af0SHarald Freudenberger static LIST_HEAD(mkvp_list); 835e80d4af0SHarald Freudenberger static DEFINE_SPINLOCK(mkvp_list_lock); 836e80d4af0SHarald Freudenberger 837ca681ec8SHarald Freudenberger static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2]) 838e80d4af0SHarald Freudenberger { 839e80d4af0SHarald Freudenberger int rc = -ENOENT; 840e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 841e80d4af0SHarald Freudenberger 842e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 843e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 844e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 845e80d4af0SHarald Freudenberger ptr->domain == domain) { 846ca681ec8SHarald Freudenberger memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64)); 847e80d4af0SHarald Freudenberger rc = 0; 848e80d4af0SHarald Freudenberger break; 849e80d4af0SHarald Freudenberger } 850e80d4af0SHarald Freudenberger } 851e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 852e80d4af0SHarald Freudenberger 853e80d4af0SHarald Freudenberger return rc; 854e80d4af0SHarald Freudenberger } 855e80d4af0SHarald Freudenberger 856ca681ec8SHarald Freudenberger static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) 857e80d4af0SHarald Freudenberger { 858e80d4af0SHarald Freudenberger int found = 0; 859e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 860e80d4af0SHarald Freudenberger 861e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 862e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 863e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 864e80d4af0SHarald Freudenberger ptr->domain == domain) { 865ca681ec8SHarald Freudenberger memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); 866e80d4af0SHarald Freudenberger found = 1; 867e80d4af0SHarald Freudenberger break; 868e80d4af0SHarald Freudenberger } 869e80d4af0SHarald Freudenberger } 870e80d4af0SHarald Freudenberger if (!found) { 871e80d4af0SHarald Freudenberger ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); 872e80d4af0SHarald Freudenberger if (!ptr) { 873e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 874e80d4af0SHarald Freudenberger return; 875e80d4af0SHarald Freudenberger } 876e80d4af0SHarald Freudenberger ptr->cardnr = cardnr; 877e80d4af0SHarald Freudenberger ptr->domain = domain; 878ca681ec8SHarald Freudenberger memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); 879e80d4af0SHarald Freudenberger list_add(&ptr->list, &mkvp_list); 880e80d4af0SHarald Freudenberger } 881e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 882e80d4af0SHarald Freudenberger } 883e80d4af0SHarald Freudenberger 884e80d4af0SHarald Freudenberger static void mkvp_cache_scrub(u16 cardnr, u16 domain) 885e80d4af0SHarald Freudenberger { 886e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 887e80d4af0SHarald Freudenberger 888e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 889e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 890e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 891e80d4af0SHarald Freudenberger ptr->domain == domain) { 892e80d4af0SHarald Freudenberger list_del(&ptr->list); 893e80d4af0SHarald Freudenberger kfree(ptr); 894e80d4af0SHarald Freudenberger break; 895e80d4af0SHarald Freudenberger } 896e80d4af0SHarald Freudenberger } 897e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 898e80d4af0SHarald Freudenberger } 899e80d4af0SHarald Freudenberger 900e80d4af0SHarald Freudenberger static void __exit mkvp_cache_free(void) 901e80d4af0SHarald Freudenberger { 902e80d4af0SHarald Freudenberger struct mkvp_info *ptr, *pnext; 903e80d4af0SHarald Freudenberger 904e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 905e80d4af0SHarald Freudenberger list_for_each_entry_safe(ptr, pnext, &mkvp_list, list) { 906e80d4af0SHarald Freudenberger list_del(&ptr->list); 907e80d4af0SHarald Freudenberger kfree(ptr); 908e80d4af0SHarald Freudenberger } 909e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 910e80d4af0SHarald Freudenberger } 911e80d4af0SHarald Freudenberger 912e80d4af0SHarald Freudenberger /* 913e80d4af0SHarald Freudenberger * Search for a matching crypto card based on the Master Key 914e80d4af0SHarald Freudenberger * Verification Pattern provided inside a secure key. 915e80d4af0SHarald Freudenberger */ 916e80d4af0SHarald Freudenberger int pkey_findcard(const struct pkey_seckey *seckey, 917e80d4af0SHarald Freudenberger u16 *pcardnr, u16 *pdomain, int verify) 918e80d4af0SHarald Freudenberger { 919e80d4af0SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 920af4a7227SHarald Freudenberger struct zcrypt_device_status_ext *device_status; 921e80d4af0SHarald Freudenberger u16 card, dom; 922ca681ec8SHarald Freudenberger u64 mkvp[2]; 923ca681ec8SHarald Freudenberger int i, rc, oi = -1; 924e80d4af0SHarald Freudenberger 925e80d4af0SHarald Freudenberger /* mkvp must not be zero */ 926e80d4af0SHarald Freudenberger if (t->mkvp == 0) 927e80d4af0SHarald Freudenberger return -EINVAL; 928e80d4af0SHarald Freudenberger 929e80d4af0SHarald Freudenberger /* fetch status of all crypto cards */ 9306da2ec56SKees Cook device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT, 9316da2ec56SKees Cook sizeof(struct zcrypt_device_status_ext), 932e80d4af0SHarald Freudenberger GFP_KERNEL); 933af4a7227SHarald Freudenberger if (!device_status) 934e80d4af0SHarald Freudenberger return -ENOMEM; 935af4a7227SHarald Freudenberger zcrypt_device_status_mask_ext(device_status); 936e80d4af0SHarald Freudenberger 937e80d4af0SHarald Freudenberger /* walk through all crypto cards */ 938af4a7227SHarald Freudenberger for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { 939af4a7227SHarald Freudenberger card = AP_QID_CARD(device_status[i].qid); 940af4a7227SHarald Freudenberger dom = AP_QID_QUEUE(device_status[i].qid); 941af4a7227SHarald Freudenberger if (device_status[i].online && 942af4a7227SHarald Freudenberger device_status[i].functions & 0x04) { 943e80d4af0SHarald Freudenberger /* an enabled CCA Coprocessor card */ 944e80d4af0SHarald Freudenberger /* try cached mkvp */ 945ca681ec8SHarald Freudenberger if (mkvp_cache_fetch(card, dom, mkvp) == 0 && 946ca681ec8SHarald Freudenberger t->mkvp == mkvp[0]) { 947e80d4af0SHarald Freudenberger if (!verify) 948e80d4af0SHarald Freudenberger break; 949e80d4af0SHarald Freudenberger /* verify: fetch mkvp from adapter */ 950ca681ec8SHarald Freudenberger if (fetch_mkvp(card, dom, mkvp) == 0) { 951e80d4af0SHarald Freudenberger mkvp_cache_update(card, dom, mkvp); 952ca681ec8SHarald Freudenberger if (t->mkvp == mkvp[0]) 953e80d4af0SHarald Freudenberger break; 954e80d4af0SHarald Freudenberger } 955e80d4af0SHarald Freudenberger } 956e80d4af0SHarald Freudenberger } else { 957e80d4af0SHarald Freudenberger /* Card is offline and/or not a CCA card. */ 958e80d4af0SHarald Freudenberger /* del mkvp entry from cache if it exists */ 959e80d4af0SHarald Freudenberger mkvp_cache_scrub(card, dom); 960e80d4af0SHarald Freudenberger } 961e80d4af0SHarald Freudenberger } 962af4a7227SHarald Freudenberger if (i >= MAX_ZDEV_ENTRIES_EXT) { 963e80d4af0SHarald Freudenberger /* nothing found, so this time without cache */ 964af4a7227SHarald Freudenberger for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { 965af4a7227SHarald Freudenberger if (!(device_status[i].online && 966af4a7227SHarald Freudenberger device_status[i].functions & 0x04)) 967e80d4af0SHarald Freudenberger continue; 968af4a7227SHarald Freudenberger card = AP_QID_CARD(device_status[i].qid); 969af4a7227SHarald Freudenberger dom = AP_QID_QUEUE(device_status[i].qid); 970e80d4af0SHarald Freudenberger /* fresh fetch mkvp from adapter */ 971ca681ec8SHarald Freudenberger if (fetch_mkvp(card, dom, mkvp) == 0) { 972e80d4af0SHarald Freudenberger mkvp_cache_update(card, dom, mkvp); 973ca681ec8SHarald Freudenberger if (t->mkvp == mkvp[0]) 974e80d4af0SHarald Freudenberger break; 975ca681ec8SHarald Freudenberger if (t->mkvp == mkvp[1] && oi < 0) 976ca681ec8SHarald Freudenberger oi = i; 977e80d4af0SHarald Freudenberger } 978e80d4af0SHarald Freudenberger } 979af4a7227SHarald Freudenberger if (i >= MAX_ZDEV_ENTRIES_EXT && oi >= 0) { 980ca681ec8SHarald Freudenberger /* old mkvp matched, use this card then */ 981af4a7227SHarald Freudenberger card = AP_QID_CARD(device_status[oi].qid); 982af4a7227SHarald Freudenberger dom = AP_QID_QUEUE(device_status[oi].qid); 983e80d4af0SHarald Freudenberger } 984ca681ec8SHarald Freudenberger } 985af4a7227SHarald Freudenberger if (i < MAX_ZDEV_ENTRIES_EXT || oi >= 0) { 986e80d4af0SHarald Freudenberger if (pcardnr) 987e80d4af0SHarald Freudenberger *pcardnr = card; 988e80d4af0SHarald Freudenberger if (pdomain) 989e80d4af0SHarald Freudenberger *pdomain = dom; 990e80d4af0SHarald Freudenberger rc = 0; 991e80d4af0SHarald Freudenberger } else 992e80d4af0SHarald Freudenberger rc = -ENODEV; 993e80d4af0SHarald Freudenberger 994af4a7227SHarald Freudenberger kfree(device_status); 995e80d4af0SHarald Freudenberger return rc; 996e80d4af0SHarald Freudenberger } 997e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_findcard); 998e80d4af0SHarald Freudenberger 999e80d4af0SHarald Freudenberger /* 1000e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 1001e80d4af0SHarald Freudenberger */ 1002e80d4af0SHarald Freudenberger int pkey_skey2pkey(const struct pkey_seckey *seckey, 1003e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 1004e80d4af0SHarald Freudenberger { 1005e80d4af0SHarald Freudenberger u16 cardnr, domain; 1006e80d4af0SHarald Freudenberger int rc, verify; 1007e80d4af0SHarald Freudenberger 1008e80d4af0SHarald Freudenberger /* 1009e80d4af0SHarald Freudenberger * The pkey_sec2protkey call may fail when a card has been 1010e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 1011e80d4af0SHarald Freudenberger * of the mkvp into the cache. So first try without verify then 1012e80d4af0SHarald Freudenberger * with verify enabled (thus refreshing the mkvp for each card). 1013e80d4af0SHarald Freudenberger */ 1014e80d4af0SHarald Freudenberger for (verify = 0; verify < 2; verify++) { 1015e80d4af0SHarald Freudenberger rc = pkey_findcard(seckey, &cardnr, &domain, verify); 1016e80d4af0SHarald Freudenberger if (rc) 1017e80d4af0SHarald Freudenberger continue; 1018e80d4af0SHarald Freudenberger rc = pkey_sec2protkey(cardnr, domain, seckey, protkey); 1019e80d4af0SHarald Freudenberger if (rc == 0) 1020e80d4af0SHarald Freudenberger break; 1021e80d4af0SHarald Freudenberger } 1022e80d4af0SHarald Freudenberger 1023e80d4af0SHarald Freudenberger if (rc) 1024ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 1025e80d4af0SHarald Freudenberger 1026e80d4af0SHarald Freudenberger return rc; 1027e80d4af0SHarald Freudenberger } 1028e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_skey2pkey); 1029e80d4af0SHarald Freudenberger 1030e80d4af0SHarald Freudenberger /* 1031e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 1032e61a6134SHarald Freudenberger */ 1033e61a6134SHarald Freudenberger int pkey_verifykey(const struct pkey_seckey *seckey, 1034e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 1035e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 1036e61a6134SHarald Freudenberger { 1037e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 1038e61a6134SHarald Freudenberger u16 cardnr, domain; 1039e61a6134SHarald Freudenberger u64 mkvp[2]; 1040e61a6134SHarald Freudenberger int rc; 1041e61a6134SHarald Freudenberger 1042e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 1043e61a6134SHarald Freudenberger rc = check_secaeskeytoken((u8 *) seckey, 0); 1044e61a6134SHarald Freudenberger if (rc) 1045e61a6134SHarald Freudenberger goto out; 1046e61a6134SHarald Freudenberger if (pattributes) 1047e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 1048e61a6134SHarald Freudenberger if (pkeysize) 1049e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 1050e61a6134SHarald Freudenberger 1051e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 1052e61a6134SHarald Freudenberger rc = pkey_findcard(seckey, &cardnr, &domain, 1); 1053e61a6134SHarald Freudenberger if (rc) 1054e61a6134SHarald Freudenberger goto out; 1055e61a6134SHarald Freudenberger 1056e61a6134SHarald Freudenberger /* check mkvp for old mkvp match */ 1057e61a6134SHarald Freudenberger rc = mkvp_cache_fetch(cardnr, domain, mkvp); 1058e61a6134SHarald Freudenberger if (rc) 1059e61a6134SHarald Freudenberger goto out; 1060e61a6134SHarald Freudenberger if (t->mkvp == mkvp[1]) { 1061ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 1062e61a6134SHarald Freudenberger if (pattributes) 1063e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 1064e61a6134SHarald Freudenberger } 1065e61a6134SHarald Freudenberger 1066e61a6134SHarald Freudenberger if (pcardnr) 1067e61a6134SHarald Freudenberger *pcardnr = cardnr; 1068e61a6134SHarald Freudenberger if (pdomain) 1069e61a6134SHarald Freudenberger *pdomain = domain; 1070e61a6134SHarald Freudenberger 1071e61a6134SHarald Freudenberger out: 1072ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 1073e61a6134SHarald Freudenberger return rc; 1074e61a6134SHarald Freudenberger } 1075e61a6134SHarald Freudenberger EXPORT_SYMBOL(pkey_verifykey); 1076e61a6134SHarald Freudenberger 1077e61a6134SHarald Freudenberger /* 1078a45a5c7dSIngo Franzki * Generate a random protected key 1079a45a5c7dSIngo Franzki */ 1080a45a5c7dSIngo Franzki int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey) 1081a45a5c7dSIngo Franzki { 1082a45a5c7dSIngo Franzki struct pkey_clrkey clrkey; 1083a45a5c7dSIngo Franzki int keysize; 1084a45a5c7dSIngo Franzki int rc; 1085a45a5c7dSIngo Franzki 1086a45a5c7dSIngo Franzki switch (keytype) { 1087a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_128: 1088a45a5c7dSIngo Franzki keysize = 16; 1089a45a5c7dSIngo Franzki break; 1090a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_192: 1091a45a5c7dSIngo Franzki keysize = 24; 1092a45a5c7dSIngo Franzki break; 1093a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_256: 1094a45a5c7dSIngo Franzki keysize = 32; 1095a45a5c7dSIngo Franzki break; 1096a45a5c7dSIngo Franzki default: 1097a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 1098a45a5c7dSIngo Franzki keytype); 1099a45a5c7dSIngo Franzki return -EINVAL; 1100a45a5c7dSIngo Franzki } 1101a45a5c7dSIngo Franzki 1102a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 1103a45a5c7dSIngo Franzki get_random_bytes(clrkey.clrkey, keysize); 1104a45a5c7dSIngo Franzki 1105a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 1106a45a5c7dSIngo Franzki rc = pkey_clr2protkey(keytype, &clrkey, protkey); 1107a45a5c7dSIngo Franzki if (rc) 1108a45a5c7dSIngo Franzki return rc; 1109a45a5c7dSIngo Franzki 1110a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 1111a45a5c7dSIngo Franzki get_random_bytes(protkey->protkey, keysize); 1112a45a5c7dSIngo Franzki 1113a45a5c7dSIngo Franzki return 0; 1114a45a5c7dSIngo Franzki } 1115a45a5c7dSIngo Franzki EXPORT_SYMBOL(pkey_genprotkey); 1116a45a5c7dSIngo Franzki 1117a45a5c7dSIngo Franzki /* 1118*cb26b9ffSIngo Franzki * Verify if a protected key is still valid 1119*cb26b9ffSIngo Franzki */ 1120*cb26b9ffSIngo Franzki int pkey_verifyprotkey(const struct pkey_protkey *protkey) 1121*cb26b9ffSIngo Franzki { 1122*cb26b9ffSIngo Franzki unsigned long fc; 1123*cb26b9ffSIngo Franzki struct { 1124*cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 1125*cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 1126*cb26b9ffSIngo Franzki } param; 1127*cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 1128*cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 1129*cb26b9ffSIngo Franzki unsigned int k; 1130*cb26b9ffSIngo Franzki 1131*cb26b9ffSIngo Franzki switch (protkey->type) { 1132*cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 1133*cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 1134*cb26b9ffSIngo Franzki break; 1135*cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 1136*cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 1137*cb26b9ffSIngo Franzki break; 1138*cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 1139*cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 1140*cb26b9ffSIngo Franzki break; 1141*cb26b9ffSIngo Franzki default: 1142*cb26b9ffSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 1143*cb26b9ffSIngo Franzki protkey->type); 1144*cb26b9ffSIngo Franzki return -EINVAL; 1145*cb26b9ffSIngo Franzki } 1146*cb26b9ffSIngo Franzki 1147*cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 1148*cb26b9ffSIngo Franzki 1149*cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 1150*cb26b9ffSIngo Franzki memcpy(param.key, protkey->protkey, sizeof(param.key)); 1151*cb26b9ffSIngo Franzki 1152*cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 1153*cb26b9ffSIngo Franzki sizeof(null_msg)); 1154*cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 1155*cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 1156*cb26b9ffSIngo Franzki return -EKEYREJECTED; 1157*cb26b9ffSIngo Franzki } 1158*cb26b9ffSIngo Franzki 1159*cb26b9ffSIngo Franzki return 0; 1160*cb26b9ffSIngo Franzki } 1161*cb26b9ffSIngo Franzki EXPORT_SYMBOL(pkey_verifyprotkey); 1162*cb26b9ffSIngo Franzki 1163*cb26b9ffSIngo Franzki /* 1164e80d4af0SHarald Freudenberger * File io functions 1165e80d4af0SHarald Freudenberger */ 1166e80d4af0SHarald Freudenberger 1167e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 1168e80d4af0SHarald Freudenberger unsigned long arg) 1169e80d4af0SHarald Freudenberger { 1170e80d4af0SHarald Freudenberger int rc; 1171e80d4af0SHarald Freudenberger 1172e80d4af0SHarald Freudenberger switch (cmd) { 1173e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1174e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *) arg; 1175e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1176e80d4af0SHarald Freudenberger 1177e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1178e80d4af0SHarald Freudenberger return -EFAULT; 1179e80d4af0SHarald Freudenberger rc = pkey_genseckey(kgs.cardnr, kgs.domain, 1180e80d4af0SHarald Freudenberger kgs.keytype, &kgs.seckey); 1181ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_genseckey()=%d\n", __func__, rc); 1182e80d4af0SHarald Freudenberger if (rc) 1183e80d4af0SHarald Freudenberger break; 1184e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1185e80d4af0SHarald Freudenberger return -EFAULT; 1186e80d4af0SHarald Freudenberger break; 1187e80d4af0SHarald Freudenberger } 1188e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1189e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *) arg; 1190e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1191e80d4af0SHarald Freudenberger 1192e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1193e80d4af0SHarald Freudenberger return -EFAULT; 1194e80d4af0SHarald Freudenberger rc = pkey_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1195e80d4af0SHarald Freudenberger &kcs.clrkey, &kcs.seckey); 1196ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey()=%d\n", __func__, rc); 1197e80d4af0SHarald Freudenberger if (rc) 1198e80d4af0SHarald Freudenberger break; 1199e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1200e80d4af0SHarald Freudenberger return -EFAULT; 1201e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1202e80d4af0SHarald Freudenberger break; 1203e80d4af0SHarald Freudenberger } 1204e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1205e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *) arg; 1206e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1207e80d4af0SHarald Freudenberger 1208e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1209e80d4af0SHarald Freudenberger return -EFAULT; 1210e80d4af0SHarald Freudenberger rc = pkey_sec2protkey(ksp.cardnr, ksp.domain, 1211e80d4af0SHarald Freudenberger &ksp.seckey, &ksp.protkey); 1212ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_sec2protkey()=%d\n", __func__, rc); 1213e80d4af0SHarald Freudenberger if (rc) 1214e80d4af0SHarald Freudenberger break; 1215e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1216e80d4af0SHarald Freudenberger return -EFAULT; 1217e80d4af0SHarald Freudenberger break; 1218e80d4af0SHarald Freudenberger } 1219e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1220e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *) arg; 1221e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1222e80d4af0SHarald Freudenberger 1223e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1224e80d4af0SHarald Freudenberger return -EFAULT; 1225e80d4af0SHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, 1226e80d4af0SHarald Freudenberger &kcp.clrkey, &kcp.protkey); 1227ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1228e80d4af0SHarald Freudenberger if (rc) 1229e80d4af0SHarald Freudenberger break; 1230e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1231e80d4af0SHarald Freudenberger return -EFAULT; 1232e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1233e80d4af0SHarald Freudenberger break; 1234e80d4af0SHarald Freudenberger } 1235e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1236e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *) arg; 1237e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1238e80d4af0SHarald Freudenberger 1239e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1240e80d4af0SHarald Freudenberger return -EFAULT; 1241e80d4af0SHarald Freudenberger rc = pkey_findcard(&kfc.seckey, 1242e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1243ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_findcard()=%d\n", __func__, rc); 1244e80d4af0SHarald Freudenberger if (rc) 1245e80d4af0SHarald Freudenberger break; 1246e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1247e80d4af0SHarald Freudenberger return -EFAULT; 1248e80d4af0SHarald Freudenberger break; 1249e80d4af0SHarald Freudenberger } 1250e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1251e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *) arg; 1252e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1253e80d4af0SHarald Freudenberger 1254e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1255e80d4af0SHarald Freudenberger return -EFAULT; 1256e80d4af0SHarald Freudenberger rc = pkey_skey2pkey(&ksp.seckey, &ksp.protkey); 1257ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1258e80d4af0SHarald Freudenberger if (rc) 1259e80d4af0SHarald Freudenberger break; 1260e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1261e80d4af0SHarald Freudenberger return -EFAULT; 1262e80d4af0SHarald Freudenberger break; 1263e80d4af0SHarald Freudenberger } 1264e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1265e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *) arg; 1266e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1267e61a6134SHarald Freudenberger 1268e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1269e61a6134SHarald Freudenberger return -EFAULT; 1270e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1271e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1272ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1273e61a6134SHarald Freudenberger if (rc) 1274e61a6134SHarald Freudenberger break; 1275e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1276e61a6134SHarald Freudenberger return -EFAULT; 1277e61a6134SHarald Freudenberger break; 1278e61a6134SHarald Freudenberger } 1279a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1280a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *) arg; 1281a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1282a45a5c7dSIngo Franzki 1283a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1284a45a5c7dSIngo Franzki return -EFAULT; 1285a45a5c7dSIngo Franzki rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); 1286a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1287a45a5c7dSIngo Franzki if (rc) 1288a45a5c7dSIngo Franzki break; 1289a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1290a45a5c7dSIngo Franzki return -EFAULT; 1291a45a5c7dSIngo Franzki break; 1292a45a5c7dSIngo Franzki } 1293*cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 1294*cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *) arg; 1295*cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 1296*cb26b9ffSIngo Franzki 1297*cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 1298*cb26b9ffSIngo Franzki return -EFAULT; 1299*cb26b9ffSIngo Franzki rc = pkey_verifyprotkey(&kvp.protkey); 1300*cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 1301*cb26b9ffSIngo Franzki break; 1302*cb26b9ffSIngo Franzki } 1303e80d4af0SHarald Freudenberger default: 1304e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1305e80d4af0SHarald Freudenberger return -ENOTTY; 1306e80d4af0SHarald Freudenberger } 1307e80d4af0SHarald Freudenberger 1308e80d4af0SHarald Freudenberger return rc; 1309e80d4af0SHarald Freudenberger } 1310e80d4af0SHarald Freudenberger 1311e80d4af0SHarald Freudenberger /* 1312e80d4af0SHarald Freudenberger * Sysfs and file io operations 1313e80d4af0SHarald Freudenberger */ 1314d632c047SIngo Franzki 1315d632c047SIngo Franzki /* 1316d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1317d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1318d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1319d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1320d632c047SIngo Franzki */ 1321d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1322d632c047SIngo Franzki loff_t off, size_t count) 1323d632c047SIngo Franzki { 1324d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1325d632c047SIngo Franzki struct pkey_protkey protkey; 1326d632c047SIngo Franzki int rc; 1327d632c047SIngo Franzki 1328d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1329d632c047SIngo Franzki return -EINVAL; 1330d632c047SIngo Franzki if (is_xts) 1331d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1332d632c047SIngo Franzki return -EINVAL; 1333d632c047SIngo Franzki 1334d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1335d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1336d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1337d632c047SIngo Franzki protkeytoken.keytype = keytype; 1338d632c047SIngo Franzki 1339d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1340d632c047SIngo Franzki if (rc) 1341d632c047SIngo Franzki return rc; 1342d632c047SIngo Franzki 1343d632c047SIngo Franzki protkeytoken.len = protkey.len; 1344d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1345d632c047SIngo Franzki 1346d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1347d632c047SIngo Franzki 1348d632c047SIngo Franzki if (is_xts) { 1349d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1350d632c047SIngo Franzki if (rc) 1351d632c047SIngo Franzki return rc; 1352d632c047SIngo Franzki 1353d632c047SIngo Franzki protkeytoken.len = protkey.len; 1354d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1355d632c047SIngo Franzki 1356d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1357d632c047SIngo Franzki sizeof(protkeytoken)); 1358d632c047SIngo Franzki 1359d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1360d632c047SIngo Franzki } 1361d632c047SIngo Franzki 1362d632c047SIngo Franzki return sizeof(protkeytoken); 1363d632c047SIngo Franzki } 1364d632c047SIngo Franzki 1365d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1366d632c047SIngo Franzki struct kobject *kobj, 1367d632c047SIngo Franzki struct bin_attribute *attr, 1368d632c047SIngo Franzki char *buf, loff_t off, 1369d632c047SIngo Franzki size_t count) 1370d632c047SIngo Franzki { 1371d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1372d632c047SIngo Franzki off, count); 1373d632c047SIngo Franzki } 1374d632c047SIngo Franzki 1375d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1376d632c047SIngo Franzki struct kobject *kobj, 1377d632c047SIngo Franzki struct bin_attribute *attr, 1378d632c047SIngo Franzki char *buf, loff_t off, 1379d632c047SIngo Franzki size_t count) 1380d632c047SIngo Franzki { 1381d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1382d632c047SIngo Franzki off, count); 1383d632c047SIngo Franzki } 1384d632c047SIngo Franzki 1385d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1386d632c047SIngo Franzki struct kobject *kobj, 1387d632c047SIngo Franzki struct bin_attribute *attr, 1388d632c047SIngo Franzki char *buf, loff_t off, 1389d632c047SIngo Franzki size_t count) 1390d632c047SIngo Franzki { 1391d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1392d632c047SIngo Franzki off, count); 1393d632c047SIngo Franzki } 1394d632c047SIngo Franzki 1395d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1396d632c047SIngo Franzki struct kobject *kobj, 1397d632c047SIngo Franzki struct bin_attribute *attr, 1398d632c047SIngo Franzki char *buf, loff_t off, 1399d632c047SIngo Franzki size_t count) 1400d632c047SIngo Franzki { 1401d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1402d632c047SIngo Franzki off, count); 1403d632c047SIngo Franzki } 1404d632c047SIngo Franzki 1405d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1406d632c047SIngo Franzki struct kobject *kobj, 1407d632c047SIngo Franzki struct bin_attribute *attr, 1408d632c047SIngo Franzki char *buf, loff_t off, 1409d632c047SIngo Franzki size_t count) 1410d632c047SIngo Franzki { 1411d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1412d632c047SIngo Franzki off, count); 1413d632c047SIngo Franzki } 1414d632c047SIngo Franzki 1415d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1416d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1417d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1418d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1419d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1420d632c047SIngo Franzki 1421d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1422d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1423d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1424d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1425d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1426d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1427d632c047SIngo Franzki NULL 1428d632c047SIngo Franzki }; 1429d632c047SIngo Franzki 1430d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1431d632c047SIngo Franzki .name = "protkey", 1432d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1433d632c047SIngo Franzki }; 1434d632c047SIngo Franzki 1435af504452SIngo Franzki /* 1436af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1437af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1438af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1439af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1440af504452SIngo Franzki */ 1441af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1442af504452SIngo Franzki loff_t off, size_t count) 1443af504452SIngo Franzki { 1444af504452SIngo Franzki int rc; 1445af504452SIngo Franzki 1446af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1447af504452SIngo Franzki return -EINVAL; 1448af504452SIngo Franzki if (is_xts) 1449af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1450af504452SIngo Franzki return -EINVAL; 1451af504452SIngo Franzki 1452af504452SIngo Franzki rc = pkey_genseckey(-1, -1, keytype, (struct pkey_seckey *)buf); 1453af504452SIngo Franzki if (rc) 1454af504452SIngo Franzki return rc; 1455af504452SIngo Franzki 1456af504452SIngo Franzki if (is_xts) { 1457af504452SIngo Franzki buf += sizeof(struct pkey_seckey); 1458af504452SIngo Franzki rc = pkey_genseckey(-1, -1, keytype, (struct pkey_seckey *)buf); 1459af504452SIngo Franzki if (rc) 1460af504452SIngo Franzki return rc; 1461af504452SIngo Franzki 1462af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1463af504452SIngo Franzki } 1464af504452SIngo Franzki 1465af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1466af504452SIngo Franzki } 1467af504452SIngo Franzki 1468af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1469af504452SIngo Franzki struct kobject *kobj, 1470af504452SIngo Franzki struct bin_attribute *attr, 1471af504452SIngo Franzki char *buf, loff_t off, 1472af504452SIngo Franzki size_t count) 1473af504452SIngo Franzki { 1474af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1475af504452SIngo Franzki off, count); 1476af504452SIngo Franzki } 1477af504452SIngo Franzki 1478af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1479af504452SIngo Franzki struct kobject *kobj, 1480af504452SIngo Franzki struct bin_attribute *attr, 1481af504452SIngo Franzki char *buf, loff_t off, 1482af504452SIngo Franzki size_t count) 1483af504452SIngo Franzki { 1484af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1485af504452SIngo Franzki off, count); 1486af504452SIngo Franzki } 1487af504452SIngo Franzki 1488af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1489af504452SIngo Franzki struct kobject *kobj, 1490af504452SIngo Franzki struct bin_attribute *attr, 1491af504452SIngo Franzki char *buf, loff_t off, 1492af504452SIngo Franzki size_t count) 1493af504452SIngo Franzki { 1494af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1495af504452SIngo Franzki off, count); 1496af504452SIngo Franzki } 1497af504452SIngo Franzki 1498af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1499af504452SIngo Franzki struct kobject *kobj, 1500af504452SIngo Franzki struct bin_attribute *attr, 1501af504452SIngo Franzki char *buf, loff_t off, 1502af504452SIngo Franzki size_t count) 1503af504452SIngo Franzki { 1504af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1505af504452SIngo Franzki off, count); 1506af504452SIngo Franzki } 1507af504452SIngo Franzki 1508af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1509af504452SIngo Franzki struct kobject *kobj, 1510af504452SIngo Franzki struct bin_attribute *attr, 1511af504452SIngo Franzki char *buf, loff_t off, 1512af504452SIngo Franzki size_t count) 1513af504452SIngo Franzki { 1514af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1515af504452SIngo Franzki off, count); 1516af504452SIngo Franzki } 1517af504452SIngo Franzki 1518af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1519af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1520af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1521af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1522af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1523af504452SIngo Franzki 1524af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1525af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1526af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1527af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1528af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1529af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1530af504452SIngo Franzki NULL 1531af504452SIngo Franzki }; 1532af504452SIngo Franzki 1533af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1534af504452SIngo Franzki .name = "ccadata", 1535af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1536af504452SIngo Franzki }; 1537af504452SIngo Franzki 1538d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 1539d632c047SIngo Franzki &protkey_attr_group, 1540af504452SIngo Franzki &ccadata_attr_group, 1541d632c047SIngo Franzki NULL, 1542d632c047SIngo Franzki }; 1543d632c047SIngo Franzki 1544e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 1545e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 1546e80d4af0SHarald Freudenberger .open = nonseekable_open, 1547e80d4af0SHarald Freudenberger .llseek = no_llseek, 1548e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 1549e80d4af0SHarald Freudenberger }; 1550e80d4af0SHarald Freudenberger 1551e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 1552e80d4af0SHarald Freudenberger .name = "pkey", 1553e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 1554e80d4af0SHarald Freudenberger .mode = 0666, 1555e80d4af0SHarald Freudenberger .fops = &pkey_fops, 1556d632c047SIngo Franzki .groups = pkey_attr_groups, 1557e80d4af0SHarald Freudenberger }; 1558e80d4af0SHarald Freudenberger 1559e80d4af0SHarald Freudenberger /* 1560e80d4af0SHarald Freudenberger * Module init 1561e80d4af0SHarald Freudenberger */ 1562cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 1563e80d4af0SHarald Freudenberger { 1564*cb26b9ffSIngo Franzki cpacf_mask_t pckmo_functions, kmc_functions; 1565e80d4af0SHarald Freudenberger 1566e80d4af0SHarald Freudenberger /* check for pckmo instructions available */ 1567e80d4af0SHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 1568e80d4af0SHarald Freudenberger return -EOPNOTSUPP; 1569e80d4af0SHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_128_KEY) || 1570e80d4af0SHarald Freudenberger !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_192_KEY) || 1571e80d4af0SHarald Freudenberger !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_256_KEY)) 1572e80d4af0SHarald Freudenberger return -EOPNOTSUPP; 1573e80d4af0SHarald Freudenberger 1574*cb26b9ffSIngo Franzki /* check for kmc instructions available */ 1575*cb26b9ffSIngo Franzki if (!cpacf_query(CPACF_KMC, &kmc_functions)) 1576*cb26b9ffSIngo Franzki return -EOPNOTSUPP; 1577*cb26b9ffSIngo Franzki if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) || 1578*cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) || 1579*cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) 1580*cb26b9ffSIngo Franzki return -EOPNOTSUPP; 1581*cb26b9ffSIngo Franzki 1582e80d4af0SHarald Freudenberger pkey_debug_init(); 1583e80d4af0SHarald Freudenberger 1584e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 1585e80d4af0SHarald Freudenberger } 1586e80d4af0SHarald Freudenberger 1587e80d4af0SHarald Freudenberger /* 1588e80d4af0SHarald Freudenberger * Module exit 1589e80d4af0SHarald Freudenberger */ 1590e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 1591e80d4af0SHarald Freudenberger { 1592e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 1593e80d4af0SHarald Freudenberger mkvp_cache_free(); 1594e80d4af0SHarald Freudenberger pkey_debug_exit(); 1595e80d4af0SHarald Freudenberger } 1596e80d4af0SHarald Freudenberger 1597e80d4af0SHarald Freudenberger module_init(pkey_init); 1598e80d4af0SHarald Freudenberger module_exit(pkey_exit); 1599