1*e80d4af0SHarald Freudenberger /* 2*e80d4af0SHarald Freudenberger * pkey device driver 3*e80d4af0SHarald Freudenberger * 4*e80d4af0SHarald Freudenberger * Copyright IBM Corp. 2017 5*e80d4af0SHarald Freudenberger * Author(s): Harald Freudenberger 6*e80d4af0SHarald Freudenberger * 7*e80d4af0SHarald Freudenberger * This program is free software; you can redistribute it and/or modify 8*e80d4af0SHarald Freudenberger * it under the terms of the GNU General Public License (version 2 only) 9*e80d4af0SHarald Freudenberger * as published by the Free Software Foundation. 10*e80d4af0SHarald Freudenberger * 11*e80d4af0SHarald Freudenberger */ 12*e80d4af0SHarald Freudenberger 13*e80d4af0SHarald Freudenberger #define KMSG_COMPONENT "pkey" 14*e80d4af0SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 15*e80d4af0SHarald Freudenberger 16*e80d4af0SHarald Freudenberger #include <linux/fs.h> 17*e80d4af0SHarald Freudenberger #include <linux/init.h> 18*e80d4af0SHarald Freudenberger #include <linux/miscdevice.h> 19*e80d4af0SHarald Freudenberger #include <linux/module.h> 20*e80d4af0SHarald Freudenberger #include <linux/slab.h> 21*e80d4af0SHarald Freudenberger #include <linux/kallsyms.h> 22*e80d4af0SHarald Freudenberger #include <linux/debugfs.h> 23*e80d4af0SHarald Freudenberger #include <asm/zcrypt.h> 24*e80d4af0SHarald Freudenberger #include <asm/cpacf.h> 25*e80d4af0SHarald Freudenberger #include <asm/pkey.h> 26*e80d4af0SHarald Freudenberger 27*e80d4af0SHarald Freudenberger #include "zcrypt_api.h" 28*e80d4af0SHarald Freudenberger 29*e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL"); 30*e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 31*e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface"); 32*e80d4af0SHarald Freudenberger 33*e80d4af0SHarald Freudenberger /* Size of parameter block used for all cca requests/replies */ 34*e80d4af0SHarald Freudenberger #define PARMBSIZE 512 35*e80d4af0SHarald Freudenberger 36*e80d4af0SHarald Freudenberger /* Size of vardata block used for some of the cca requests/replies */ 37*e80d4af0SHarald Freudenberger #define VARDATASIZE 4096 38*e80d4af0SHarald Freudenberger 39*e80d4af0SHarald Freudenberger /* 40*e80d4af0SHarald Freudenberger * debug feature data and functions 41*e80d4af0SHarald Freudenberger */ 42*e80d4af0SHarald Freudenberger 43*e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 44*e80d4af0SHarald Freudenberger 45*e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 46*e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 47*e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 48*e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 49*e80d4af0SHarald Freudenberger 50*e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 51*e80d4af0SHarald Freudenberger { 52*e80d4af0SHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 4 * sizeof(long)); 53*e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 54*e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 55*e80d4af0SHarald Freudenberger } 56*e80d4af0SHarald Freudenberger 57*e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 58*e80d4af0SHarald Freudenberger { 59*e80d4af0SHarald Freudenberger debug_unregister(debug_info); 60*e80d4af0SHarald Freudenberger } 61*e80d4af0SHarald Freudenberger 62*e80d4af0SHarald Freudenberger /* inside view of a secure key token (only type 0x01 version 0x04) */ 63*e80d4af0SHarald Freudenberger struct secaeskeytoken { 64*e80d4af0SHarald Freudenberger u8 type; /* 0x01 for internal key token */ 65*e80d4af0SHarald Freudenberger u8 res0[3]; 66*e80d4af0SHarald Freudenberger u8 version; /* should be 0x04 */ 67*e80d4af0SHarald Freudenberger u8 res1[1]; 68*e80d4af0SHarald Freudenberger u8 flag; /* key flags */ 69*e80d4af0SHarald Freudenberger u8 res2[1]; 70*e80d4af0SHarald Freudenberger u64 mkvp; /* master key verification pattern */ 71*e80d4af0SHarald Freudenberger u8 key[32]; /* key value (encrypted) */ 72*e80d4af0SHarald Freudenberger u8 cv[8]; /* control vector */ 73*e80d4af0SHarald Freudenberger u16 bitsize; /* key bit size */ 74*e80d4af0SHarald Freudenberger u16 keysize; /* key byte size */ 75*e80d4af0SHarald Freudenberger u8 tvv[4]; /* token validation value */ 76*e80d4af0SHarald Freudenberger } __packed; 77*e80d4af0SHarald Freudenberger 78*e80d4af0SHarald Freudenberger /* 79*e80d4af0SHarald Freudenberger * Simple check if the token is a valid CCA secure AES key 80*e80d4af0SHarald Freudenberger * token. If keybitsize is given, the bitsize of the key is 81*e80d4af0SHarald Freudenberger * also checked. Returns 0 on success or errno value on failure. 82*e80d4af0SHarald Freudenberger */ 83*e80d4af0SHarald Freudenberger static int check_secaeskeytoken(u8 *token, int keybitsize) 84*e80d4af0SHarald Freudenberger { 85*e80d4af0SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) token; 86*e80d4af0SHarald Freudenberger 87*e80d4af0SHarald Freudenberger if (t->type != 0x01) { 88*e80d4af0SHarald Freudenberger DEBUG_ERR( 89*e80d4af0SHarald Freudenberger "check_secaeskeytoken secure token check failed, type mismatch 0x%02x != 0x01\n", 90*e80d4af0SHarald Freudenberger (int) t->type); 91*e80d4af0SHarald Freudenberger return -EINVAL; 92*e80d4af0SHarald Freudenberger } 93*e80d4af0SHarald Freudenberger if (t->version != 0x04) { 94*e80d4af0SHarald Freudenberger DEBUG_ERR( 95*e80d4af0SHarald Freudenberger "check_secaeskeytoken secure token check failed, version mismatch 0x%02x != 0x04\n", 96*e80d4af0SHarald Freudenberger (int) t->version); 97*e80d4af0SHarald Freudenberger return -EINVAL; 98*e80d4af0SHarald Freudenberger } 99*e80d4af0SHarald Freudenberger if (keybitsize > 0 && t->bitsize != keybitsize) { 100*e80d4af0SHarald Freudenberger DEBUG_ERR( 101*e80d4af0SHarald Freudenberger "check_secaeskeytoken secure token check failed, bitsize mismatch %d != %d\n", 102*e80d4af0SHarald Freudenberger (int) t->bitsize, keybitsize); 103*e80d4af0SHarald Freudenberger return -EINVAL; 104*e80d4af0SHarald Freudenberger } 105*e80d4af0SHarald Freudenberger 106*e80d4af0SHarald Freudenberger return 0; 107*e80d4af0SHarald Freudenberger } 108*e80d4af0SHarald Freudenberger 109*e80d4af0SHarald Freudenberger /* 110*e80d4af0SHarald Freudenberger * Allocate consecutive memory for request CPRB, request param 111*e80d4af0SHarald Freudenberger * block, reply CPRB and reply param block and fill in values 112*e80d4af0SHarald Freudenberger * for the common fields. Returns 0 on success or errno value 113*e80d4af0SHarald Freudenberger * on failure. 114*e80d4af0SHarald Freudenberger */ 115*e80d4af0SHarald Freudenberger static int alloc_and_prep_cprbmem(size_t paramblen, 116*e80d4af0SHarald Freudenberger u8 **pcprbmem, 117*e80d4af0SHarald Freudenberger struct CPRBX **preqCPRB, 118*e80d4af0SHarald Freudenberger struct CPRBX **prepCPRB) 119*e80d4af0SHarald Freudenberger { 120*e80d4af0SHarald Freudenberger u8 *cprbmem; 121*e80d4af0SHarald Freudenberger size_t cprbplusparamblen = sizeof(struct CPRBX) + paramblen; 122*e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 123*e80d4af0SHarald Freudenberger 124*e80d4af0SHarald Freudenberger /* 125*e80d4af0SHarald Freudenberger * allocate consecutive memory for request CPRB, request param 126*e80d4af0SHarald Freudenberger * block, reply CPRB and reply param block 127*e80d4af0SHarald Freudenberger */ 128*e80d4af0SHarald Freudenberger cprbmem = kmalloc(2 * cprbplusparamblen, GFP_KERNEL); 129*e80d4af0SHarald Freudenberger if (!cprbmem) 130*e80d4af0SHarald Freudenberger return -ENOMEM; 131*e80d4af0SHarald Freudenberger memset(cprbmem, 0, 2 * cprbplusparamblen); 132*e80d4af0SHarald Freudenberger 133*e80d4af0SHarald Freudenberger preqcblk = (struct CPRBX *) cprbmem; 134*e80d4af0SHarald Freudenberger prepcblk = (struct CPRBX *) (cprbmem + cprbplusparamblen); 135*e80d4af0SHarald Freudenberger 136*e80d4af0SHarald Freudenberger /* fill request cprb struct */ 137*e80d4af0SHarald Freudenberger preqcblk->cprb_len = sizeof(struct CPRBX); 138*e80d4af0SHarald Freudenberger preqcblk->cprb_ver_id = 0x02; 139*e80d4af0SHarald Freudenberger memcpy(preqcblk->func_id, "T2", 2); 140*e80d4af0SHarald Freudenberger preqcblk->rpl_msgbl = cprbplusparamblen; 141*e80d4af0SHarald Freudenberger if (paramblen) { 142*e80d4af0SHarald Freudenberger preqcblk->req_parmb = 143*e80d4af0SHarald Freudenberger ((u8 *) preqcblk) + sizeof(struct CPRBX); 144*e80d4af0SHarald Freudenberger preqcblk->rpl_parmb = 145*e80d4af0SHarald Freudenberger ((u8 *) prepcblk) + sizeof(struct CPRBX); 146*e80d4af0SHarald Freudenberger } 147*e80d4af0SHarald Freudenberger 148*e80d4af0SHarald Freudenberger *pcprbmem = cprbmem; 149*e80d4af0SHarald Freudenberger *preqCPRB = preqcblk; 150*e80d4af0SHarald Freudenberger *prepCPRB = prepcblk; 151*e80d4af0SHarald Freudenberger 152*e80d4af0SHarald Freudenberger return 0; 153*e80d4af0SHarald Freudenberger } 154*e80d4af0SHarald Freudenberger 155*e80d4af0SHarald Freudenberger /* 156*e80d4af0SHarald Freudenberger * Free the cprb memory allocated with the function above. 157*e80d4af0SHarald Freudenberger * If the scrub value is not zero, the memory is filled 158*e80d4af0SHarald Freudenberger * with zeros before freeing (useful if there was some 159*e80d4af0SHarald Freudenberger * clear key material in there). 160*e80d4af0SHarald Freudenberger */ 161*e80d4af0SHarald Freudenberger static void free_cprbmem(void *mem, size_t paramblen, int scrub) 162*e80d4af0SHarald Freudenberger { 163*e80d4af0SHarald Freudenberger if (scrub) 164*e80d4af0SHarald Freudenberger memzero_explicit(mem, 2 * (sizeof(struct CPRBX) + paramblen)); 165*e80d4af0SHarald Freudenberger kfree(mem); 166*e80d4af0SHarald Freudenberger } 167*e80d4af0SHarald Freudenberger 168*e80d4af0SHarald Freudenberger /* 169*e80d4af0SHarald Freudenberger * Helper function to prepare the xcrb struct 170*e80d4af0SHarald Freudenberger */ 171*e80d4af0SHarald Freudenberger static inline void prep_xcrb(struct ica_xcRB *pxcrb, 172*e80d4af0SHarald Freudenberger u16 cardnr, 173*e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, 174*e80d4af0SHarald Freudenberger struct CPRBX *prepcblk) 175*e80d4af0SHarald Freudenberger { 176*e80d4af0SHarald Freudenberger memset(pxcrb, 0, sizeof(*pxcrb)); 177*e80d4af0SHarald Freudenberger pxcrb->agent_ID = 0x4341; /* 'CA' */ 178*e80d4af0SHarald Freudenberger pxcrb->user_defined = (cardnr == 0xFFFF ? AUTOSELECT : cardnr); 179*e80d4af0SHarald Freudenberger pxcrb->request_control_blk_length = 180*e80d4af0SHarald Freudenberger preqcblk->cprb_len + preqcblk->req_parml; 181*e80d4af0SHarald Freudenberger pxcrb->request_control_blk_addr = (void *) preqcblk; 182*e80d4af0SHarald Freudenberger pxcrb->reply_control_blk_length = preqcblk->rpl_msgbl; 183*e80d4af0SHarald Freudenberger pxcrb->reply_control_blk_addr = (void *) prepcblk; 184*e80d4af0SHarald Freudenberger } 185*e80d4af0SHarald Freudenberger 186*e80d4af0SHarald Freudenberger /* 187*e80d4af0SHarald Freudenberger * Helper function which calls zcrypt_send_cprb with 188*e80d4af0SHarald Freudenberger * memory management segment adjusted to kernel space 189*e80d4af0SHarald Freudenberger * so that the copy_from_user called within this 190*e80d4af0SHarald Freudenberger * function do in fact copy from kernel space. 191*e80d4af0SHarald Freudenberger */ 192*e80d4af0SHarald Freudenberger static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb) 193*e80d4af0SHarald Freudenberger { 194*e80d4af0SHarald Freudenberger int rc; 195*e80d4af0SHarald Freudenberger mm_segment_t old_fs = get_fs(); 196*e80d4af0SHarald Freudenberger 197*e80d4af0SHarald Freudenberger set_fs(KERNEL_DS); 198*e80d4af0SHarald Freudenberger rc = zcrypt_send_cprb(xcrb); 199*e80d4af0SHarald Freudenberger set_fs(old_fs); 200*e80d4af0SHarald Freudenberger 201*e80d4af0SHarald Freudenberger return rc; 202*e80d4af0SHarald Freudenberger } 203*e80d4af0SHarald Freudenberger 204*e80d4af0SHarald Freudenberger /* 205*e80d4af0SHarald Freudenberger * Generate (random) AES secure key. 206*e80d4af0SHarald Freudenberger */ 207*e80d4af0SHarald Freudenberger int pkey_genseckey(u16 cardnr, u16 domain, 208*e80d4af0SHarald Freudenberger u32 keytype, struct pkey_seckey *seckey) 209*e80d4af0SHarald Freudenberger { 210*e80d4af0SHarald Freudenberger int i, rc, keysize; 211*e80d4af0SHarald Freudenberger int seckeysize; 212*e80d4af0SHarald Freudenberger u8 *mem; 213*e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 214*e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 215*e80d4af0SHarald Freudenberger struct kgreqparm { 216*e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 217*e80d4af0SHarald Freudenberger u16 rule_array_len; 218*e80d4af0SHarald Freudenberger struct lv1 { 219*e80d4af0SHarald Freudenberger u16 len; 220*e80d4af0SHarald Freudenberger char key_form[8]; 221*e80d4af0SHarald Freudenberger char key_length[8]; 222*e80d4af0SHarald Freudenberger char key_type1[8]; 223*e80d4af0SHarald Freudenberger char key_type2[8]; 224*e80d4af0SHarald Freudenberger } lv1; 225*e80d4af0SHarald Freudenberger struct lv2 { 226*e80d4af0SHarald Freudenberger u16 len; 227*e80d4af0SHarald Freudenberger struct keyid { 228*e80d4af0SHarald Freudenberger u16 len; 229*e80d4af0SHarald Freudenberger u16 attr; 230*e80d4af0SHarald Freudenberger u8 data[SECKEYBLOBSIZE]; 231*e80d4af0SHarald Freudenberger } keyid[6]; 232*e80d4af0SHarald Freudenberger } lv2; 233*e80d4af0SHarald Freudenberger } *preqparm; 234*e80d4af0SHarald Freudenberger struct kgrepparm { 235*e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 236*e80d4af0SHarald Freudenberger u16 rule_array_len; 237*e80d4af0SHarald Freudenberger struct lv3 { 238*e80d4af0SHarald Freudenberger u16 len; 239*e80d4af0SHarald Freudenberger u16 keyblocklen; 240*e80d4af0SHarald Freudenberger struct { 241*e80d4af0SHarald Freudenberger u16 toklen; 242*e80d4af0SHarald Freudenberger u16 tokattr; 243*e80d4af0SHarald Freudenberger u8 tok[0]; 244*e80d4af0SHarald Freudenberger /* ... some more data ... */ 245*e80d4af0SHarald Freudenberger } keyblock; 246*e80d4af0SHarald Freudenberger } lv3; 247*e80d4af0SHarald Freudenberger } *prepparm; 248*e80d4af0SHarald Freudenberger 249*e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 250*e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 251*e80d4af0SHarald Freudenberger if (rc) 252*e80d4af0SHarald Freudenberger return rc; 253*e80d4af0SHarald Freudenberger 254*e80d4af0SHarald Freudenberger /* fill request cprb struct */ 255*e80d4af0SHarald Freudenberger preqcblk->domain = domain; 256*e80d4af0SHarald Freudenberger 257*e80d4af0SHarald Freudenberger /* fill request cprb param block with KG request */ 258*e80d4af0SHarald Freudenberger preqparm = (struct kgreqparm *) preqcblk->req_parmb; 259*e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "KG", 2); 260*e80d4af0SHarald Freudenberger preqparm->rule_array_len = sizeof(preqparm->rule_array_len); 261*e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1); 262*e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_form, "OP ", 8); 263*e80d4af0SHarald Freudenberger switch (keytype) { 264*e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 265*e80d4af0SHarald Freudenberger keysize = 16; 266*e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN16 ", 8); 267*e80d4af0SHarald Freudenberger break; 268*e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 269*e80d4af0SHarald Freudenberger keysize = 24; 270*e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN24 ", 8); 271*e80d4af0SHarald Freudenberger break; 272*e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 273*e80d4af0SHarald Freudenberger keysize = 32; 274*e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN32 ", 8); 275*e80d4af0SHarald Freudenberger break; 276*e80d4af0SHarald Freudenberger default: 277*e80d4af0SHarald Freudenberger DEBUG_ERR( 278*e80d4af0SHarald Freudenberger "pkey_genseckey unknown/unsupported keytype %d\n", 279*e80d4af0SHarald Freudenberger keytype); 280*e80d4af0SHarald Freudenberger rc = -EINVAL; 281*e80d4af0SHarald Freudenberger goto out; 282*e80d4af0SHarald Freudenberger } 283*e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_type1, "AESDATA ", 8); 284*e80d4af0SHarald Freudenberger preqparm->lv2.len = sizeof(struct lv2); 285*e80d4af0SHarald Freudenberger for (i = 0; i < 6; i++) { 286*e80d4af0SHarald Freudenberger preqparm->lv2.keyid[i].len = sizeof(struct keyid); 287*e80d4af0SHarald Freudenberger preqparm->lv2.keyid[i].attr = (i == 2 ? 0x30 : 0x10); 288*e80d4af0SHarald Freudenberger } 289*e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct kgreqparm); 290*e80d4af0SHarald Freudenberger 291*e80d4af0SHarald Freudenberger /* fill xcrb struct */ 292*e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 293*e80d4af0SHarald Freudenberger 294*e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 295*e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 296*e80d4af0SHarald Freudenberger if (rc) { 297*e80d4af0SHarald Freudenberger DEBUG_ERR( 298*e80d4af0SHarald Freudenberger "pkey_genseckey zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 299*e80d4af0SHarald Freudenberger (int) cardnr, (int) domain, rc); 300*e80d4af0SHarald Freudenberger goto out; 301*e80d4af0SHarald Freudenberger } 302*e80d4af0SHarald Freudenberger 303*e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 304*e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 305*e80d4af0SHarald Freudenberger DEBUG_ERR( 306*e80d4af0SHarald Freudenberger "pkey_genseckey secure key generate failure, card response %d/%d\n", 307*e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 308*e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 309*e80d4af0SHarald Freudenberger rc = -EIO; 310*e80d4af0SHarald Freudenberger goto out; 311*e80d4af0SHarald Freudenberger } 312*e80d4af0SHarald Freudenberger 313*e80d4af0SHarald Freudenberger /* process response cprb param block */ 314*e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 315*e80d4af0SHarald Freudenberger prepparm = (struct kgrepparm *) prepcblk->rpl_parmb; 316*e80d4af0SHarald Freudenberger 317*e80d4af0SHarald Freudenberger /* check length of the returned secure key token */ 318*e80d4af0SHarald Freudenberger seckeysize = prepparm->lv3.keyblock.toklen 319*e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.toklen) 320*e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.tokattr); 321*e80d4af0SHarald Freudenberger if (seckeysize != SECKEYBLOBSIZE) { 322*e80d4af0SHarald Freudenberger DEBUG_ERR( 323*e80d4af0SHarald Freudenberger "pkey_genseckey secure token size mismatch %d != %d bytes\n", 324*e80d4af0SHarald Freudenberger seckeysize, SECKEYBLOBSIZE); 325*e80d4af0SHarald Freudenberger rc = -EIO; 326*e80d4af0SHarald Freudenberger goto out; 327*e80d4af0SHarald Freudenberger } 328*e80d4af0SHarald Freudenberger 329*e80d4af0SHarald Freudenberger /* check secure key token */ 330*e80d4af0SHarald Freudenberger rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); 331*e80d4af0SHarald Freudenberger if (rc) { 332*e80d4af0SHarald Freudenberger rc = -EIO; 333*e80d4af0SHarald Freudenberger goto out; 334*e80d4af0SHarald Freudenberger } 335*e80d4af0SHarald Freudenberger 336*e80d4af0SHarald Freudenberger /* copy the generated secure key token */ 337*e80d4af0SHarald Freudenberger memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); 338*e80d4af0SHarald Freudenberger 339*e80d4af0SHarald Freudenberger out: 340*e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 0); 341*e80d4af0SHarald Freudenberger return rc; 342*e80d4af0SHarald Freudenberger } 343*e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_genseckey); 344*e80d4af0SHarald Freudenberger 345*e80d4af0SHarald Freudenberger /* 346*e80d4af0SHarald Freudenberger * Generate an AES secure key with given key value. 347*e80d4af0SHarald Freudenberger */ 348*e80d4af0SHarald Freudenberger int pkey_clr2seckey(u16 cardnr, u16 domain, u32 keytype, 349*e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 350*e80d4af0SHarald Freudenberger struct pkey_seckey *seckey) 351*e80d4af0SHarald Freudenberger { 352*e80d4af0SHarald Freudenberger int rc, keysize, seckeysize; 353*e80d4af0SHarald Freudenberger u8 *mem; 354*e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 355*e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 356*e80d4af0SHarald Freudenberger struct cmreqparm { 357*e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 358*e80d4af0SHarald Freudenberger u16 rule_array_len; 359*e80d4af0SHarald Freudenberger char rule_array[8]; 360*e80d4af0SHarald Freudenberger struct lv1 { 361*e80d4af0SHarald Freudenberger u16 len; 362*e80d4af0SHarald Freudenberger u8 clrkey[0]; 363*e80d4af0SHarald Freudenberger } lv1; 364*e80d4af0SHarald Freudenberger struct lv2 { 365*e80d4af0SHarald Freudenberger u16 len; 366*e80d4af0SHarald Freudenberger struct keyid { 367*e80d4af0SHarald Freudenberger u16 len; 368*e80d4af0SHarald Freudenberger u16 attr; 369*e80d4af0SHarald Freudenberger u8 data[SECKEYBLOBSIZE]; 370*e80d4af0SHarald Freudenberger } keyid; 371*e80d4af0SHarald Freudenberger } lv2; 372*e80d4af0SHarald Freudenberger } *preqparm; 373*e80d4af0SHarald Freudenberger struct lv2 *plv2; 374*e80d4af0SHarald Freudenberger struct cmrepparm { 375*e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 376*e80d4af0SHarald Freudenberger u16 rule_array_len; 377*e80d4af0SHarald Freudenberger struct lv3 { 378*e80d4af0SHarald Freudenberger u16 len; 379*e80d4af0SHarald Freudenberger u16 keyblocklen; 380*e80d4af0SHarald Freudenberger struct { 381*e80d4af0SHarald Freudenberger u16 toklen; 382*e80d4af0SHarald Freudenberger u16 tokattr; 383*e80d4af0SHarald Freudenberger u8 tok[0]; 384*e80d4af0SHarald Freudenberger /* ... some more data ... */ 385*e80d4af0SHarald Freudenberger } keyblock; 386*e80d4af0SHarald Freudenberger } lv3; 387*e80d4af0SHarald Freudenberger } *prepparm; 388*e80d4af0SHarald Freudenberger 389*e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 390*e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 391*e80d4af0SHarald Freudenberger if (rc) 392*e80d4af0SHarald Freudenberger return rc; 393*e80d4af0SHarald Freudenberger 394*e80d4af0SHarald Freudenberger /* fill request cprb struct */ 395*e80d4af0SHarald Freudenberger preqcblk->domain = domain; 396*e80d4af0SHarald Freudenberger 397*e80d4af0SHarald Freudenberger /* fill request cprb param block with CM request */ 398*e80d4af0SHarald Freudenberger preqparm = (struct cmreqparm *) preqcblk->req_parmb; 399*e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "CM", 2); 400*e80d4af0SHarald Freudenberger memcpy(preqparm->rule_array, "AES ", 8); 401*e80d4af0SHarald Freudenberger preqparm->rule_array_len = 402*e80d4af0SHarald Freudenberger sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); 403*e80d4af0SHarald Freudenberger switch (keytype) { 404*e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 405*e80d4af0SHarald Freudenberger keysize = 16; 406*e80d4af0SHarald Freudenberger break; 407*e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 408*e80d4af0SHarald Freudenberger keysize = 24; 409*e80d4af0SHarald Freudenberger break; 410*e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 411*e80d4af0SHarald Freudenberger keysize = 32; 412*e80d4af0SHarald Freudenberger break; 413*e80d4af0SHarald Freudenberger default: 414*e80d4af0SHarald Freudenberger DEBUG_ERR( 415*e80d4af0SHarald Freudenberger "pkey_clr2seckey unknown/unsupported keytype %d\n", 416*e80d4af0SHarald Freudenberger keytype); 417*e80d4af0SHarald Freudenberger rc = -EINVAL; 418*e80d4af0SHarald Freudenberger goto out; 419*e80d4af0SHarald Freudenberger } 420*e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1) + keysize; 421*e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.clrkey, clrkey->clrkey, keysize); 422*e80d4af0SHarald Freudenberger plv2 = (struct lv2 *) (((u8 *) &preqparm->lv2) + keysize); 423*e80d4af0SHarald Freudenberger plv2->len = sizeof(struct lv2); 424*e80d4af0SHarald Freudenberger plv2->keyid.len = sizeof(struct keyid); 425*e80d4af0SHarald Freudenberger plv2->keyid.attr = 0x30; 426*e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct cmreqparm) + keysize; 427*e80d4af0SHarald Freudenberger 428*e80d4af0SHarald Freudenberger /* fill xcrb struct */ 429*e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 430*e80d4af0SHarald Freudenberger 431*e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 432*e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 433*e80d4af0SHarald Freudenberger if (rc) { 434*e80d4af0SHarald Freudenberger DEBUG_ERR( 435*e80d4af0SHarald Freudenberger "pkey_clr2seckey zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 436*e80d4af0SHarald Freudenberger (int) cardnr, (int) domain, rc); 437*e80d4af0SHarald Freudenberger goto out; 438*e80d4af0SHarald Freudenberger } 439*e80d4af0SHarald Freudenberger 440*e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 441*e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 442*e80d4af0SHarald Freudenberger DEBUG_ERR( 443*e80d4af0SHarald Freudenberger "pkey_clr2seckey clear key import failure, card response %d/%d\n", 444*e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 445*e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 446*e80d4af0SHarald Freudenberger rc = -EIO; 447*e80d4af0SHarald Freudenberger goto out; 448*e80d4af0SHarald Freudenberger } 449*e80d4af0SHarald Freudenberger 450*e80d4af0SHarald Freudenberger /* process response cprb param block */ 451*e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 452*e80d4af0SHarald Freudenberger prepparm = (struct cmrepparm *) prepcblk->rpl_parmb; 453*e80d4af0SHarald Freudenberger 454*e80d4af0SHarald Freudenberger /* check length of the returned secure key token */ 455*e80d4af0SHarald Freudenberger seckeysize = prepparm->lv3.keyblock.toklen 456*e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.toklen) 457*e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.tokattr); 458*e80d4af0SHarald Freudenberger if (seckeysize != SECKEYBLOBSIZE) { 459*e80d4af0SHarald Freudenberger DEBUG_ERR( 460*e80d4af0SHarald Freudenberger "pkey_clr2seckey secure token size mismatch %d != %d bytes\n", 461*e80d4af0SHarald Freudenberger seckeysize, SECKEYBLOBSIZE); 462*e80d4af0SHarald Freudenberger rc = -EIO; 463*e80d4af0SHarald Freudenberger goto out; 464*e80d4af0SHarald Freudenberger } 465*e80d4af0SHarald Freudenberger 466*e80d4af0SHarald Freudenberger /* check secure key token */ 467*e80d4af0SHarald Freudenberger rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); 468*e80d4af0SHarald Freudenberger if (rc) { 469*e80d4af0SHarald Freudenberger rc = -EIO; 470*e80d4af0SHarald Freudenberger goto out; 471*e80d4af0SHarald Freudenberger } 472*e80d4af0SHarald Freudenberger 473*e80d4af0SHarald Freudenberger /* copy the generated secure key token */ 474*e80d4af0SHarald Freudenberger memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); 475*e80d4af0SHarald Freudenberger 476*e80d4af0SHarald Freudenberger out: 477*e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 1); 478*e80d4af0SHarald Freudenberger return rc; 479*e80d4af0SHarald Freudenberger } 480*e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_clr2seckey); 481*e80d4af0SHarald Freudenberger 482*e80d4af0SHarald Freudenberger /* 483*e80d4af0SHarald Freudenberger * Derive a proteced key from the secure key blob. 484*e80d4af0SHarald Freudenberger */ 485*e80d4af0SHarald Freudenberger int pkey_sec2protkey(u16 cardnr, u16 domain, 486*e80d4af0SHarald Freudenberger const struct pkey_seckey *seckey, 487*e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 488*e80d4af0SHarald Freudenberger { 489*e80d4af0SHarald Freudenberger int rc; 490*e80d4af0SHarald Freudenberger u8 *mem; 491*e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 492*e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 493*e80d4af0SHarald Freudenberger struct uskreqparm { 494*e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 495*e80d4af0SHarald Freudenberger u16 rule_array_len; 496*e80d4af0SHarald Freudenberger struct lv1 { 497*e80d4af0SHarald Freudenberger u16 len; 498*e80d4af0SHarald Freudenberger u16 attr_len; 499*e80d4af0SHarald Freudenberger u16 attr_flags; 500*e80d4af0SHarald Freudenberger } lv1; 501*e80d4af0SHarald Freudenberger struct lv2 { 502*e80d4af0SHarald Freudenberger u16 len; 503*e80d4af0SHarald Freudenberger u16 attr_len; 504*e80d4af0SHarald Freudenberger u16 attr_flags; 505*e80d4af0SHarald Freudenberger u8 token[0]; /* cca secure key token */ 506*e80d4af0SHarald Freudenberger } lv2 __packed; 507*e80d4af0SHarald Freudenberger } *preqparm; 508*e80d4af0SHarald Freudenberger struct uskrepparm { 509*e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 510*e80d4af0SHarald Freudenberger u16 rule_array_len; 511*e80d4af0SHarald Freudenberger struct lv3 { 512*e80d4af0SHarald Freudenberger u16 len; 513*e80d4af0SHarald Freudenberger u16 attr_len; 514*e80d4af0SHarald Freudenberger u16 attr_flags; 515*e80d4af0SHarald Freudenberger struct cpacfkeyblock { 516*e80d4af0SHarald Freudenberger u8 version; /* version of this struct */ 517*e80d4af0SHarald Freudenberger u8 flags[2]; 518*e80d4af0SHarald Freudenberger u8 algo; 519*e80d4af0SHarald Freudenberger u8 form; 520*e80d4af0SHarald Freudenberger u8 pad1[3]; 521*e80d4af0SHarald Freudenberger u16 keylen; 522*e80d4af0SHarald Freudenberger u8 key[64]; /* the key (keylen bytes) */ 523*e80d4af0SHarald Freudenberger u16 keyattrlen; 524*e80d4af0SHarald Freudenberger u8 keyattr[32]; 525*e80d4af0SHarald Freudenberger u8 pad2[1]; 526*e80d4af0SHarald Freudenberger u8 vptype; 527*e80d4af0SHarald Freudenberger u8 vp[32]; /* verification pattern */ 528*e80d4af0SHarald Freudenberger } keyblock; 529*e80d4af0SHarald Freudenberger } lv3 __packed; 530*e80d4af0SHarald Freudenberger } *prepparm; 531*e80d4af0SHarald Freudenberger 532*e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 533*e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 534*e80d4af0SHarald Freudenberger if (rc) 535*e80d4af0SHarald Freudenberger return rc; 536*e80d4af0SHarald Freudenberger 537*e80d4af0SHarald Freudenberger /* fill request cprb struct */ 538*e80d4af0SHarald Freudenberger preqcblk->domain = domain; 539*e80d4af0SHarald Freudenberger 540*e80d4af0SHarald Freudenberger /* fill request cprb param block with USK request */ 541*e80d4af0SHarald Freudenberger preqparm = (struct uskreqparm *) preqcblk->req_parmb; 542*e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "US", 2); 543*e80d4af0SHarald Freudenberger preqparm->rule_array_len = sizeof(preqparm->rule_array_len); 544*e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1); 545*e80d4af0SHarald Freudenberger preqparm->lv1.attr_len = sizeof(struct lv1) - sizeof(preqparm->lv1.len); 546*e80d4af0SHarald Freudenberger preqparm->lv1.attr_flags = 0x0001; 547*e80d4af0SHarald Freudenberger preqparm->lv2.len = sizeof(struct lv2) + SECKEYBLOBSIZE; 548*e80d4af0SHarald Freudenberger preqparm->lv2.attr_len = sizeof(struct lv2) 549*e80d4af0SHarald Freudenberger - sizeof(preqparm->lv2.len) + SECKEYBLOBSIZE; 550*e80d4af0SHarald Freudenberger preqparm->lv2.attr_flags = 0x0000; 551*e80d4af0SHarald Freudenberger memcpy(preqparm->lv2.token, seckey->seckey, SECKEYBLOBSIZE); 552*e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct uskreqparm) + SECKEYBLOBSIZE; 553*e80d4af0SHarald Freudenberger 554*e80d4af0SHarald Freudenberger /* fill xcrb struct */ 555*e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 556*e80d4af0SHarald Freudenberger 557*e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 558*e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 559*e80d4af0SHarald Freudenberger if (rc) { 560*e80d4af0SHarald Freudenberger DEBUG_ERR( 561*e80d4af0SHarald Freudenberger "pkey_sec2protkey zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 562*e80d4af0SHarald Freudenberger (int) cardnr, (int) domain, rc); 563*e80d4af0SHarald Freudenberger goto out; 564*e80d4af0SHarald Freudenberger } 565*e80d4af0SHarald Freudenberger 566*e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 567*e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 568*e80d4af0SHarald Freudenberger DEBUG_ERR( 569*e80d4af0SHarald Freudenberger "pkey_sec2protkey unwrap secure key failure, card response %d/%d\n", 570*e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 571*e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 572*e80d4af0SHarald Freudenberger rc = -EIO; 573*e80d4af0SHarald Freudenberger goto out; 574*e80d4af0SHarald Freudenberger } 575*e80d4af0SHarald Freudenberger 576*e80d4af0SHarald Freudenberger /* process response cprb param block */ 577*e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 578*e80d4af0SHarald Freudenberger prepparm = (struct uskrepparm *) prepcblk->rpl_parmb; 579*e80d4af0SHarald Freudenberger 580*e80d4af0SHarald Freudenberger /* check the returned keyblock */ 581*e80d4af0SHarald Freudenberger if (prepparm->lv3.keyblock.version != 0x01) { 582*e80d4af0SHarald Freudenberger DEBUG_ERR( 583*e80d4af0SHarald Freudenberger "pkey_sec2protkey reply param keyblock version mismatch 0x%02x != 0x01\n", 584*e80d4af0SHarald Freudenberger (int) prepparm->lv3.keyblock.version); 585*e80d4af0SHarald Freudenberger rc = -EIO; 586*e80d4af0SHarald Freudenberger goto out; 587*e80d4af0SHarald Freudenberger } 588*e80d4af0SHarald Freudenberger 589*e80d4af0SHarald Freudenberger /* copy the tanslated protected key */ 590*e80d4af0SHarald Freudenberger switch (prepparm->lv3.keyblock.keylen) { 591*e80d4af0SHarald Freudenberger case 16+32: 592*e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_128; 593*e80d4af0SHarald Freudenberger break; 594*e80d4af0SHarald Freudenberger case 24+32: 595*e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_192; 596*e80d4af0SHarald Freudenberger break; 597*e80d4af0SHarald Freudenberger case 32+32: 598*e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_256; 599*e80d4af0SHarald Freudenberger break; 600*e80d4af0SHarald Freudenberger default: 601*e80d4af0SHarald Freudenberger DEBUG_ERR("pkey_sec2protkey unknown/unsupported keytype %d\n", 602*e80d4af0SHarald Freudenberger prepparm->lv3.keyblock.keylen); 603*e80d4af0SHarald Freudenberger rc = -EIO; 604*e80d4af0SHarald Freudenberger goto out; 605*e80d4af0SHarald Freudenberger } 606*e80d4af0SHarald Freudenberger protkey->len = prepparm->lv3.keyblock.keylen; 607*e80d4af0SHarald Freudenberger memcpy(protkey->protkey, prepparm->lv3.keyblock.key, protkey->len); 608*e80d4af0SHarald Freudenberger 609*e80d4af0SHarald Freudenberger out: 610*e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 0); 611*e80d4af0SHarald Freudenberger return rc; 612*e80d4af0SHarald Freudenberger } 613*e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_sec2protkey); 614*e80d4af0SHarald Freudenberger 615*e80d4af0SHarald Freudenberger /* 616*e80d4af0SHarald Freudenberger * Create a protected key from a clear key value. 617*e80d4af0SHarald Freudenberger */ 618*e80d4af0SHarald Freudenberger int pkey_clr2protkey(u32 keytype, 619*e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 620*e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 621*e80d4af0SHarald Freudenberger { 622*e80d4af0SHarald Freudenberger long fc; 623*e80d4af0SHarald Freudenberger int keysize; 624*e80d4af0SHarald Freudenberger u8 paramblock[64]; 625*e80d4af0SHarald Freudenberger 626*e80d4af0SHarald Freudenberger switch (keytype) { 627*e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 628*e80d4af0SHarald Freudenberger keysize = 16; 629*e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 630*e80d4af0SHarald Freudenberger break; 631*e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 632*e80d4af0SHarald Freudenberger keysize = 24; 633*e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 634*e80d4af0SHarald Freudenberger break; 635*e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 636*e80d4af0SHarald Freudenberger keysize = 32; 637*e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 638*e80d4af0SHarald Freudenberger break; 639*e80d4af0SHarald Freudenberger default: 640*e80d4af0SHarald Freudenberger DEBUG_ERR("pkey_clr2protkey unknown/unsupported keytype %d\n", 641*e80d4af0SHarald Freudenberger keytype); 642*e80d4af0SHarald Freudenberger return -EINVAL; 643*e80d4af0SHarald Freudenberger } 644*e80d4af0SHarald Freudenberger 645*e80d4af0SHarald Freudenberger /* prepare param block */ 646*e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 647*e80d4af0SHarald Freudenberger memcpy(paramblock, clrkey->clrkey, keysize); 648*e80d4af0SHarald Freudenberger 649*e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 650*e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 651*e80d4af0SHarald Freudenberger 652*e80d4af0SHarald Freudenberger /* copy created protected key */ 653*e80d4af0SHarald Freudenberger protkey->type = keytype; 654*e80d4af0SHarald Freudenberger protkey->len = keysize + 32; 655*e80d4af0SHarald Freudenberger memcpy(protkey->protkey, paramblock, keysize + 32); 656*e80d4af0SHarald Freudenberger 657*e80d4af0SHarald Freudenberger return 0; 658*e80d4af0SHarald Freudenberger } 659*e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_clr2protkey); 660*e80d4af0SHarald Freudenberger 661*e80d4af0SHarald Freudenberger /* 662*e80d4af0SHarald Freudenberger * query cryptographic facility from adapter 663*e80d4af0SHarald Freudenberger */ 664*e80d4af0SHarald Freudenberger static int query_crypto_facility(u16 cardnr, u16 domain, 665*e80d4af0SHarald Freudenberger const char *keyword, 666*e80d4af0SHarald Freudenberger u8 *rarray, size_t *rarraylen, 667*e80d4af0SHarald Freudenberger u8 *varray, size_t *varraylen) 668*e80d4af0SHarald Freudenberger { 669*e80d4af0SHarald Freudenberger int rc; 670*e80d4af0SHarald Freudenberger u16 len; 671*e80d4af0SHarald Freudenberger u8 *mem, *ptr; 672*e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 673*e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 674*e80d4af0SHarald Freudenberger struct fqreqparm { 675*e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 676*e80d4af0SHarald Freudenberger u16 rule_array_len; 677*e80d4af0SHarald Freudenberger char rule_array[8]; 678*e80d4af0SHarald Freudenberger struct lv1 { 679*e80d4af0SHarald Freudenberger u16 len; 680*e80d4af0SHarald Freudenberger u8 data[VARDATASIZE]; 681*e80d4af0SHarald Freudenberger } lv1; 682*e80d4af0SHarald Freudenberger u16 dummylen; 683*e80d4af0SHarald Freudenberger } *preqparm; 684*e80d4af0SHarald Freudenberger size_t parmbsize = sizeof(struct fqreqparm); 685*e80d4af0SHarald Freudenberger struct fqrepparm { 686*e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 687*e80d4af0SHarald Freudenberger u8 lvdata[0]; 688*e80d4af0SHarald Freudenberger } *prepparm; 689*e80d4af0SHarald Freudenberger 690*e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 691*e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(parmbsize, &mem, &preqcblk, &prepcblk); 692*e80d4af0SHarald Freudenberger if (rc) 693*e80d4af0SHarald Freudenberger return rc; 694*e80d4af0SHarald Freudenberger 695*e80d4af0SHarald Freudenberger /* fill request cprb struct */ 696*e80d4af0SHarald Freudenberger preqcblk->domain = domain; 697*e80d4af0SHarald Freudenberger 698*e80d4af0SHarald Freudenberger /* fill request cprb param block with FQ request */ 699*e80d4af0SHarald Freudenberger preqparm = (struct fqreqparm *) preqcblk->req_parmb; 700*e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "FQ", 2); 701*e80d4af0SHarald Freudenberger strncpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); 702*e80d4af0SHarald Freudenberger preqparm->rule_array_len = 703*e80d4af0SHarald Freudenberger sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); 704*e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(preqparm->lv1); 705*e80d4af0SHarald Freudenberger preqparm->dummylen = sizeof(preqparm->dummylen); 706*e80d4af0SHarald Freudenberger preqcblk->req_parml = parmbsize; 707*e80d4af0SHarald Freudenberger 708*e80d4af0SHarald Freudenberger /* fill xcrb struct */ 709*e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 710*e80d4af0SHarald Freudenberger 711*e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 712*e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 713*e80d4af0SHarald Freudenberger if (rc) { 714*e80d4af0SHarald Freudenberger DEBUG_ERR( 715*e80d4af0SHarald Freudenberger "query_crypto_facility zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 716*e80d4af0SHarald Freudenberger (int) cardnr, (int) domain, rc); 717*e80d4af0SHarald Freudenberger goto out; 718*e80d4af0SHarald Freudenberger } 719*e80d4af0SHarald Freudenberger 720*e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 721*e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 722*e80d4af0SHarald Freudenberger DEBUG_ERR( 723*e80d4af0SHarald Freudenberger "query_crypto_facility unwrap secure key failure, card response %d/%d\n", 724*e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 725*e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 726*e80d4af0SHarald Freudenberger rc = -EIO; 727*e80d4af0SHarald Freudenberger goto out; 728*e80d4af0SHarald Freudenberger } 729*e80d4af0SHarald Freudenberger 730*e80d4af0SHarald Freudenberger /* process response cprb param block */ 731*e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 732*e80d4af0SHarald Freudenberger prepparm = (struct fqrepparm *) prepcblk->rpl_parmb; 733*e80d4af0SHarald Freudenberger ptr = prepparm->lvdata; 734*e80d4af0SHarald Freudenberger 735*e80d4af0SHarald Freudenberger /* check and possibly copy reply rule array */ 736*e80d4af0SHarald Freudenberger len = *((u16 *) ptr); 737*e80d4af0SHarald Freudenberger if (len > sizeof(u16)) { 738*e80d4af0SHarald Freudenberger ptr += sizeof(u16); 739*e80d4af0SHarald Freudenberger len -= sizeof(u16); 740*e80d4af0SHarald Freudenberger if (rarray && rarraylen && *rarraylen > 0) { 741*e80d4af0SHarald Freudenberger *rarraylen = (len > *rarraylen ? *rarraylen : len); 742*e80d4af0SHarald Freudenberger memcpy(rarray, ptr, *rarraylen); 743*e80d4af0SHarald Freudenberger } 744*e80d4af0SHarald Freudenberger ptr += len; 745*e80d4af0SHarald Freudenberger } 746*e80d4af0SHarald Freudenberger /* check and possible copy reply var array */ 747*e80d4af0SHarald Freudenberger len = *((u16 *) ptr); 748*e80d4af0SHarald Freudenberger if (len > sizeof(u16)) { 749*e80d4af0SHarald Freudenberger ptr += sizeof(u16); 750*e80d4af0SHarald Freudenberger len -= sizeof(u16); 751*e80d4af0SHarald Freudenberger if (varray && varraylen && *varraylen > 0) { 752*e80d4af0SHarald Freudenberger *varraylen = (len > *varraylen ? *varraylen : len); 753*e80d4af0SHarald Freudenberger memcpy(varray, ptr, *varraylen); 754*e80d4af0SHarald Freudenberger } 755*e80d4af0SHarald Freudenberger ptr += len; 756*e80d4af0SHarald Freudenberger } 757*e80d4af0SHarald Freudenberger 758*e80d4af0SHarald Freudenberger out: 759*e80d4af0SHarald Freudenberger free_cprbmem(mem, parmbsize, 0); 760*e80d4af0SHarald Freudenberger return rc; 761*e80d4af0SHarald Freudenberger } 762*e80d4af0SHarald Freudenberger 763*e80d4af0SHarald Freudenberger /* 764*e80d4af0SHarald Freudenberger * Fetch just the mkvp value via query_crypto_facility from adapter. 765*e80d4af0SHarald Freudenberger */ 766*e80d4af0SHarald Freudenberger static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp) 767*e80d4af0SHarald Freudenberger { 768*e80d4af0SHarald Freudenberger int rc, found = 0; 769*e80d4af0SHarald Freudenberger size_t rlen, vlen; 770*e80d4af0SHarald Freudenberger u8 *rarray, *varray, *pg; 771*e80d4af0SHarald Freudenberger 772*e80d4af0SHarald Freudenberger pg = (u8 *) __get_free_page(GFP_KERNEL); 773*e80d4af0SHarald Freudenberger if (!pg) 774*e80d4af0SHarald Freudenberger return -ENOMEM; 775*e80d4af0SHarald Freudenberger rarray = pg; 776*e80d4af0SHarald Freudenberger varray = pg + PAGE_SIZE/2; 777*e80d4af0SHarald Freudenberger rlen = vlen = PAGE_SIZE/2; 778*e80d4af0SHarald Freudenberger 779*e80d4af0SHarald Freudenberger rc = query_crypto_facility(cardnr, domain, "STATICSA", 780*e80d4af0SHarald Freudenberger rarray, &rlen, varray, &vlen); 781*e80d4af0SHarald Freudenberger if (rc == 0 && rlen > 8*8 && vlen > 184+8) { 782*e80d4af0SHarald Freudenberger if (rarray[64] == '2') { 783*e80d4af0SHarald Freudenberger /* current master key state is valid */ 784*e80d4af0SHarald Freudenberger *mkvp = *((u64 *)(varray + 184)); 785*e80d4af0SHarald Freudenberger found = 1; 786*e80d4af0SHarald Freudenberger } 787*e80d4af0SHarald Freudenberger } 788*e80d4af0SHarald Freudenberger 789*e80d4af0SHarald Freudenberger free_page((unsigned long) pg); 790*e80d4af0SHarald Freudenberger 791*e80d4af0SHarald Freudenberger return found ? 0 : -ENOENT; 792*e80d4af0SHarald Freudenberger } 793*e80d4af0SHarald Freudenberger 794*e80d4af0SHarald Freudenberger /* struct to hold cached mkvp info for each card/domain */ 795*e80d4af0SHarald Freudenberger struct mkvp_info { 796*e80d4af0SHarald Freudenberger struct list_head list; 797*e80d4af0SHarald Freudenberger u16 cardnr; 798*e80d4af0SHarald Freudenberger u16 domain; 799*e80d4af0SHarald Freudenberger u64 mkvp; 800*e80d4af0SHarald Freudenberger }; 801*e80d4af0SHarald Freudenberger 802*e80d4af0SHarald Freudenberger /* a list with mkvp_info entries */ 803*e80d4af0SHarald Freudenberger static LIST_HEAD(mkvp_list); 804*e80d4af0SHarald Freudenberger static DEFINE_SPINLOCK(mkvp_list_lock); 805*e80d4af0SHarald Freudenberger 806*e80d4af0SHarald Freudenberger static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) 807*e80d4af0SHarald Freudenberger { 808*e80d4af0SHarald Freudenberger int rc = -ENOENT; 809*e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 810*e80d4af0SHarald Freudenberger 811*e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 812*e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 813*e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 814*e80d4af0SHarald Freudenberger ptr->domain == domain) { 815*e80d4af0SHarald Freudenberger *mkvp = ptr->mkvp; 816*e80d4af0SHarald Freudenberger rc = 0; 817*e80d4af0SHarald Freudenberger break; 818*e80d4af0SHarald Freudenberger } 819*e80d4af0SHarald Freudenberger } 820*e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 821*e80d4af0SHarald Freudenberger 822*e80d4af0SHarald Freudenberger return rc; 823*e80d4af0SHarald Freudenberger } 824*e80d4af0SHarald Freudenberger 825*e80d4af0SHarald Freudenberger static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) 826*e80d4af0SHarald Freudenberger { 827*e80d4af0SHarald Freudenberger int found = 0; 828*e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 829*e80d4af0SHarald Freudenberger 830*e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 831*e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 832*e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 833*e80d4af0SHarald Freudenberger ptr->domain == domain) { 834*e80d4af0SHarald Freudenberger ptr->mkvp = mkvp; 835*e80d4af0SHarald Freudenberger found = 1; 836*e80d4af0SHarald Freudenberger break; 837*e80d4af0SHarald Freudenberger } 838*e80d4af0SHarald Freudenberger } 839*e80d4af0SHarald Freudenberger if (!found) { 840*e80d4af0SHarald Freudenberger ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); 841*e80d4af0SHarald Freudenberger if (!ptr) { 842*e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 843*e80d4af0SHarald Freudenberger return; 844*e80d4af0SHarald Freudenberger } 845*e80d4af0SHarald Freudenberger ptr->cardnr = cardnr; 846*e80d4af0SHarald Freudenberger ptr->domain = domain; 847*e80d4af0SHarald Freudenberger ptr->mkvp = mkvp; 848*e80d4af0SHarald Freudenberger list_add(&ptr->list, &mkvp_list); 849*e80d4af0SHarald Freudenberger } 850*e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 851*e80d4af0SHarald Freudenberger } 852*e80d4af0SHarald Freudenberger 853*e80d4af0SHarald Freudenberger static void mkvp_cache_scrub(u16 cardnr, u16 domain) 854*e80d4af0SHarald Freudenberger { 855*e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 856*e80d4af0SHarald Freudenberger 857*e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 858*e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 859*e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 860*e80d4af0SHarald Freudenberger ptr->domain == domain) { 861*e80d4af0SHarald Freudenberger list_del(&ptr->list); 862*e80d4af0SHarald Freudenberger kfree(ptr); 863*e80d4af0SHarald Freudenberger break; 864*e80d4af0SHarald Freudenberger } 865*e80d4af0SHarald Freudenberger } 866*e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 867*e80d4af0SHarald Freudenberger } 868*e80d4af0SHarald Freudenberger 869*e80d4af0SHarald Freudenberger static void __exit mkvp_cache_free(void) 870*e80d4af0SHarald Freudenberger { 871*e80d4af0SHarald Freudenberger struct mkvp_info *ptr, *pnext; 872*e80d4af0SHarald Freudenberger 873*e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 874*e80d4af0SHarald Freudenberger list_for_each_entry_safe(ptr, pnext, &mkvp_list, list) { 875*e80d4af0SHarald Freudenberger list_del(&ptr->list); 876*e80d4af0SHarald Freudenberger kfree(ptr); 877*e80d4af0SHarald Freudenberger } 878*e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 879*e80d4af0SHarald Freudenberger } 880*e80d4af0SHarald Freudenberger 881*e80d4af0SHarald Freudenberger /* 882*e80d4af0SHarald Freudenberger * Search for a matching crypto card based on the Master Key 883*e80d4af0SHarald Freudenberger * Verification Pattern provided inside a secure key. 884*e80d4af0SHarald Freudenberger */ 885*e80d4af0SHarald Freudenberger int pkey_findcard(const struct pkey_seckey *seckey, 886*e80d4af0SHarald Freudenberger u16 *pcardnr, u16 *pdomain, int verify) 887*e80d4af0SHarald Freudenberger { 888*e80d4af0SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 889*e80d4af0SHarald Freudenberger struct zcrypt_device_matrix *device_matrix; 890*e80d4af0SHarald Freudenberger u16 card, dom; 891*e80d4af0SHarald Freudenberger u64 mkvp; 892*e80d4af0SHarald Freudenberger int i, rc; 893*e80d4af0SHarald Freudenberger 894*e80d4af0SHarald Freudenberger /* mkvp must not be zero */ 895*e80d4af0SHarald Freudenberger if (t->mkvp == 0) 896*e80d4af0SHarald Freudenberger return -EINVAL; 897*e80d4af0SHarald Freudenberger 898*e80d4af0SHarald Freudenberger /* fetch status of all crypto cards */ 899*e80d4af0SHarald Freudenberger device_matrix = kmalloc(sizeof(struct zcrypt_device_matrix), 900*e80d4af0SHarald Freudenberger GFP_KERNEL); 901*e80d4af0SHarald Freudenberger if (!device_matrix) 902*e80d4af0SHarald Freudenberger return -ENOMEM; 903*e80d4af0SHarald Freudenberger zcrypt_device_status_mask(device_matrix); 904*e80d4af0SHarald Freudenberger 905*e80d4af0SHarald Freudenberger /* walk through all crypto cards */ 906*e80d4af0SHarald Freudenberger for (i = 0; i < MAX_ZDEV_ENTRIES; i++) { 907*e80d4af0SHarald Freudenberger card = AP_QID_CARD(device_matrix->device[i].qid); 908*e80d4af0SHarald Freudenberger dom = AP_QID_QUEUE(device_matrix->device[i].qid); 909*e80d4af0SHarald Freudenberger if (device_matrix->device[i].online && 910*e80d4af0SHarald Freudenberger device_matrix->device[i].functions & 0x04) { 911*e80d4af0SHarald Freudenberger /* an enabled CCA Coprocessor card */ 912*e80d4af0SHarald Freudenberger /* try cached mkvp */ 913*e80d4af0SHarald Freudenberger if (mkvp_cache_fetch(card, dom, &mkvp) == 0 && 914*e80d4af0SHarald Freudenberger t->mkvp == mkvp) { 915*e80d4af0SHarald Freudenberger if (!verify) 916*e80d4af0SHarald Freudenberger break; 917*e80d4af0SHarald Freudenberger /* verify: fetch mkvp from adapter */ 918*e80d4af0SHarald Freudenberger if (fetch_mkvp(card, dom, &mkvp) == 0) { 919*e80d4af0SHarald Freudenberger mkvp_cache_update(card, dom, mkvp); 920*e80d4af0SHarald Freudenberger if (t->mkvp == mkvp) 921*e80d4af0SHarald Freudenberger break; 922*e80d4af0SHarald Freudenberger } 923*e80d4af0SHarald Freudenberger } 924*e80d4af0SHarald Freudenberger } else { 925*e80d4af0SHarald Freudenberger /* Card is offline and/or not a CCA card. */ 926*e80d4af0SHarald Freudenberger /* del mkvp entry from cache if it exists */ 927*e80d4af0SHarald Freudenberger mkvp_cache_scrub(card, dom); 928*e80d4af0SHarald Freudenberger } 929*e80d4af0SHarald Freudenberger } 930*e80d4af0SHarald Freudenberger if (i >= MAX_ZDEV_ENTRIES) { 931*e80d4af0SHarald Freudenberger /* nothing found, so this time without cache */ 932*e80d4af0SHarald Freudenberger for (i = 0; i < MAX_ZDEV_ENTRIES; i++) { 933*e80d4af0SHarald Freudenberger if (!(device_matrix->device[i].online && 934*e80d4af0SHarald Freudenberger device_matrix->device[i].functions & 0x04)) 935*e80d4af0SHarald Freudenberger continue; 936*e80d4af0SHarald Freudenberger card = AP_QID_CARD(device_matrix->device[i].qid); 937*e80d4af0SHarald Freudenberger dom = AP_QID_QUEUE(device_matrix->device[i].qid); 938*e80d4af0SHarald Freudenberger /* fresh fetch mkvp from adapter */ 939*e80d4af0SHarald Freudenberger if (fetch_mkvp(card, dom, &mkvp) == 0) { 940*e80d4af0SHarald Freudenberger mkvp_cache_update(card, dom, mkvp); 941*e80d4af0SHarald Freudenberger if (t->mkvp == mkvp) 942*e80d4af0SHarald Freudenberger break; 943*e80d4af0SHarald Freudenberger } 944*e80d4af0SHarald Freudenberger } 945*e80d4af0SHarald Freudenberger } 946*e80d4af0SHarald Freudenberger if (i < MAX_ZDEV_ENTRIES) { 947*e80d4af0SHarald Freudenberger if (pcardnr) 948*e80d4af0SHarald Freudenberger *pcardnr = card; 949*e80d4af0SHarald Freudenberger if (pdomain) 950*e80d4af0SHarald Freudenberger *pdomain = dom; 951*e80d4af0SHarald Freudenberger rc = 0; 952*e80d4af0SHarald Freudenberger } else 953*e80d4af0SHarald Freudenberger rc = -ENODEV; 954*e80d4af0SHarald Freudenberger 955*e80d4af0SHarald Freudenberger kfree(device_matrix); 956*e80d4af0SHarald Freudenberger return rc; 957*e80d4af0SHarald Freudenberger } 958*e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_findcard); 959*e80d4af0SHarald Freudenberger 960*e80d4af0SHarald Freudenberger /* 961*e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 962*e80d4af0SHarald Freudenberger */ 963*e80d4af0SHarald Freudenberger int pkey_skey2pkey(const struct pkey_seckey *seckey, 964*e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 965*e80d4af0SHarald Freudenberger { 966*e80d4af0SHarald Freudenberger u16 cardnr, domain; 967*e80d4af0SHarald Freudenberger int rc, verify; 968*e80d4af0SHarald Freudenberger 969*e80d4af0SHarald Freudenberger /* 970*e80d4af0SHarald Freudenberger * The pkey_sec2protkey call may fail when a card has been 971*e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 972*e80d4af0SHarald Freudenberger * of the mkvp into the cache. So first try without verify then 973*e80d4af0SHarald Freudenberger * with verify enabled (thus refreshing the mkvp for each card). 974*e80d4af0SHarald Freudenberger */ 975*e80d4af0SHarald Freudenberger for (verify = 0; verify < 2; verify++) { 976*e80d4af0SHarald Freudenberger rc = pkey_findcard(seckey, &cardnr, &domain, verify); 977*e80d4af0SHarald Freudenberger if (rc) 978*e80d4af0SHarald Freudenberger continue; 979*e80d4af0SHarald Freudenberger rc = pkey_sec2protkey(cardnr, domain, seckey, protkey); 980*e80d4af0SHarald Freudenberger if (rc == 0) 981*e80d4af0SHarald Freudenberger break; 982*e80d4af0SHarald Freudenberger } 983*e80d4af0SHarald Freudenberger 984*e80d4af0SHarald Freudenberger if (rc) 985*e80d4af0SHarald Freudenberger DEBUG_DBG("pkey_skey2pkey failed rc=%d\n", rc); 986*e80d4af0SHarald Freudenberger 987*e80d4af0SHarald Freudenberger return rc; 988*e80d4af0SHarald Freudenberger } 989*e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_skey2pkey); 990*e80d4af0SHarald Freudenberger 991*e80d4af0SHarald Freudenberger /* 992*e80d4af0SHarald Freudenberger * File io functions 993*e80d4af0SHarald Freudenberger */ 994*e80d4af0SHarald Freudenberger 995*e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 996*e80d4af0SHarald Freudenberger unsigned long arg) 997*e80d4af0SHarald Freudenberger { 998*e80d4af0SHarald Freudenberger int rc; 999*e80d4af0SHarald Freudenberger 1000*e80d4af0SHarald Freudenberger switch (cmd) { 1001*e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1002*e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *) arg; 1003*e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1004*e80d4af0SHarald Freudenberger 1005*e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1006*e80d4af0SHarald Freudenberger return -EFAULT; 1007*e80d4af0SHarald Freudenberger rc = pkey_genseckey(kgs.cardnr, kgs.domain, 1008*e80d4af0SHarald Freudenberger kgs.keytype, &kgs.seckey); 1009*e80d4af0SHarald Freudenberger DEBUG_DBG("pkey_ioctl pkey_genseckey()=%d\n", rc); 1010*e80d4af0SHarald Freudenberger if (rc) 1011*e80d4af0SHarald Freudenberger break; 1012*e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1013*e80d4af0SHarald Freudenberger return -EFAULT; 1014*e80d4af0SHarald Freudenberger break; 1015*e80d4af0SHarald Freudenberger } 1016*e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1017*e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *) arg; 1018*e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1019*e80d4af0SHarald Freudenberger 1020*e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1021*e80d4af0SHarald Freudenberger return -EFAULT; 1022*e80d4af0SHarald Freudenberger rc = pkey_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1023*e80d4af0SHarald Freudenberger &kcs.clrkey, &kcs.seckey); 1024*e80d4af0SHarald Freudenberger DEBUG_DBG("pkey_ioctl pkey_clr2seckey()=%d\n", rc); 1025*e80d4af0SHarald Freudenberger if (rc) 1026*e80d4af0SHarald Freudenberger break; 1027*e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1028*e80d4af0SHarald Freudenberger return -EFAULT; 1029*e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1030*e80d4af0SHarald Freudenberger break; 1031*e80d4af0SHarald Freudenberger } 1032*e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1033*e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *) arg; 1034*e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1035*e80d4af0SHarald Freudenberger 1036*e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1037*e80d4af0SHarald Freudenberger return -EFAULT; 1038*e80d4af0SHarald Freudenberger rc = pkey_sec2protkey(ksp.cardnr, ksp.domain, 1039*e80d4af0SHarald Freudenberger &ksp.seckey, &ksp.protkey); 1040*e80d4af0SHarald Freudenberger DEBUG_DBG("pkey_ioctl pkey_sec2protkey()=%d\n", rc); 1041*e80d4af0SHarald Freudenberger if (rc) 1042*e80d4af0SHarald Freudenberger break; 1043*e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1044*e80d4af0SHarald Freudenberger return -EFAULT; 1045*e80d4af0SHarald Freudenberger break; 1046*e80d4af0SHarald Freudenberger } 1047*e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1048*e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *) arg; 1049*e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1050*e80d4af0SHarald Freudenberger 1051*e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1052*e80d4af0SHarald Freudenberger return -EFAULT; 1053*e80d4af0SHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, 1054*e80d4af0SHarald Freudenberger &kcp.clrkey, &kcp.protkey); 1055*e80d4af0SHarald Freudenberger DEBUG_DBG("pkey_ioctl pkey_clr2protkey()=%d\n", rc); 1056*e80d4af0SHarald Freudenberger if (rc) 1057*e80d4af0SHarald Freudenberger break; 1058*e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1059*e80d4af0SHarald Freudenberger return -EFAULT; 1060*e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1061*e80d4af0SHarald Freudenberger break; 1062*e80d4af0SHarald Freudenberger } 1063*e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1064*e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *) arg; 1065*e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1066*e80d4af0SHarald Freudenberger 1067*e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1068*e80d4af0SHarald Freudenberger return -EFAULT; 1069*e80d4af0SHarald Freudenberger rc = pkey_findcard(&kfc.seckey, 1070*e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1071*e80d4af0SHarald Freudenberger DEBUG_DBG("pkey_ioctl pkey_findcard()=%d\n", rc); 1072*e80d4af0SHarald Freudenberger if (rc) 1073*e80d4af0SHarald Freudenberger break; 1074*e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1075*e80d4af0SHarald Freudenberger return -EFAULT; 1076*e80d4af0SHarald Freudenberger break; 1077*e80d4af0SHarald Freudenberger } 1078*e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1079*e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *) arg; 1080*e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1081*e80d4af0SHarald Freudenberger 1082*e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1083*e80d4af0SHarald Freudenberger return -EFAULT; 1084*e80d4af0SHarald Freudenberger rc = pkey_skey2pkey(&ksp.seckey, &ksp.protkey); 1085*e80d4af0SHarald Freudenberger DEBUG_DBG("pkey_ioctl pkey_skey2pkey()=%d\n", rc); 1086*e80d4af0SHarald Freudenberger if (rc) 1087*e80d4af0SHarald Freudenberger break; 1088*e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1089*e80d4af0SHarald Freudenberger return -EFAULT; 1090*e80d4af0SHarald Freudenberger break; 1091*e80d4af0SHarald Freudenberger } 1092*e80d4af0SHarald Freudenberger default: 1093*e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1094*e80d4af0SHarald Freudenberger return -ENOTTY; 1095*e80d4af0SHarald Freudenberger } 1096*e80d4af0SHarald Freudenberger 1097*e80d4af0SHarald Freudenberger return rc; 1098*e80d4af0SHarald Freudenberger } 1099*e80d4af0SHarald Freudenberger 1100*e80d4af0SHarald Freudenberger /* 1101*e80d4af0SHarald Freudenberger * Sysfs and file io operations 1102*e80d4af0SHarald Freudenberger */ 1103*e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 1104*e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 1105*e80d4af0SHarald Freudenberger .open = nonseekable_open, 1106*e80d4af0SHarald Freudenberger .llseek = no_llseek, 1107*e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 1108*e80d4af0SHarald Freudenberger }; 1109*e80d4af0SHarald Freudenberger 1110*e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 1111*e80d4af0SHarald Freudenberger .name = "pkey", 1112*e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 1113*e80d4af0SHarald Freudenberger .mode = 0666, 1114*e80d4af0SHarald Freudenberger .fops = &pkey_fops, 1115*e80d4af0SHarald Freudenberger }; 1116*e80d4af0SHarald Freudenberger 1117*e80d4af0SHarald Freudenberger /* 1118*e80d4af0SHarald Freudenberger * Module init 1119*e80d4af0SHarald Freudenberger */ 1120*e80d4af0SHarald Freudenberger int __init pkey_init(void) 1121*e80d4af0SHarald Freudenberger { 1122*e80d4af0SHarald Freudenberger cpacf_mask_t pckmo_functions; 1123*e80d4af0SHarald Freudenberger 1124*e80d4af0SHarald Freudenberger /* check for pckmo instructions available */ 1125*e80d4af0SHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 1126*e80d4af0SHarald Freudenberger return -EOPNOTSUPP; 1127*e80d4af0SHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_128_KEY) || 1128*e80d4af0SHarald Freudenberger !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_192_KEY) || 1129*e80d4af0SHarald Freudenberger !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_256_KEY)) 1130*e80d4af0SHarald Freudenberger return -EOPNOTSUPP; 1131*e80d4af0SHarald Freudenberger 1132*e80d4af0SHarald Freudenberger pkey_debug_init(); 1133*e80d4af0SHarald Freudenberger 1134*e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 1135*e80d4af0SHarald Freudenberger } 1136*e80d4af0SHarald Freudenberger 1137*e80d4af0SHarald Freudenberger /* 1138*e80d4af0SHarald Freudenberger * Module exit 1139*e80d4af0SHarald Freudenberger */ 1140*e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 1141*e80d4af0SHarald Freudenberger { 1142*e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 1143*e80d4af0SHarald Freudenberger mkvp_cache_free(); 1144*e80d4af0SHarald Freudenberger pkey_debug_exit(); 1145*e80d4af0SHarald Freudenberger } 1146*e80d4af0SHarald Freudenberger 1147*e80d4af0SHarald Freudenberger module_init(pkey_init); 1148*e80d4af0SHarald Freudenberger module_exit(pkey_exit); 1149