in crypto/zcrypt_ep11misc.c [668:798]
int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
u8 *keybuf, size_t *keybufsize)
{
struct keygen_req_pl {
struct pl_head head;
u8 var_tag;
u8 var_len;
u32 var;
u8 keybytes_tag;
u8 keybytes_len;
u32 keybytes;
u8 mech_tag;
u8 mech_len;
u32 mech;
u8 attr_tag;
u8 attr_len;
u32 attr_header;
u32 attr_bool_mask;
u32 attr_bool_bits;
u32 attr_val_len_type;
u32 attr_val_len_value;
u8 pin_tag;
u8 pin_len;
} __packed * req_pl;
struct keygen_rep_pl {
struct pl_head head;
u8 rc_tag;
u8 rc_len;
u32 rc;
u8 data_tag;
u8 data_lenfmt;
u16 data_len;
u8 data[512];
} __packed * rep_pl;
struct ep11_cprb *req = NULL, *rep = NULL;
struct ep11_target_dev target;
struct ep11_urb *urb = NULL;
struct ep11keyblob *kb;
int api, rc = -ENOMEM;
switch (keybitsize) {
case 128:
case 192:
case 256:
break;
default:
DEBUG_ERR(
"%s unknown/unsupported keybitsize %d\n",
__func__, keybitsize);
rc = -EINVAL;
goto out;
}
/* request cprb and payload */
req = alloc_cprb(sizeof(struct keygen_req_pl));
if (!req)
goto out;
req_pl = (struct keygen_req_pl *) (((u8 *) req) + sizeof(*req));
api = (!keygenflags || keygenflags & 0x00200000) ? 4 : 1;
prep_head(&req_pl->head, sizeof(*req_pl), api, 21); /* GenerateKey */
req_pl->var_tag = 0x04;
req_pl->var_len = sizeof(u32);
req_pl->keybytes_tag = 0x04;
req_pl->keybytes_len = sizeof(u32);
req_pl->keybytes = keybitsize / 8;
req_pl->mech_tag = 0x04;
req_pl->mech_len = sizeof(u32);
req_pl->mech = 0x00001080; /* CKM_AES_KEY_GEN */
req_pl->attr_tag = 0x04;
req_pl->attr_len = 5 * sizeof(u32);
req_pl->attr_header = 0x10010000;
req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
req_pl->attr_val_len_type = 0x00000161; /* CKA_VALUE_LEN */
req_pl->attr_val_len_value = keybitsize / 8;
req_pl->pin_tag = 0x04;
/* reply cprb and payload */
rep = alloc_cprb(sizeof(struct keygen_rep_pl));
if (!rep)
goto out;
rep_pl = (struct keygen_rep_pl *) (((u8 *) rep) + sizeof(*rep));
/* urb and target */
urb = kmalloc(sizeof(struct ep11_urb), GFP_KERNEL);
if (!urb)
goto out;
target.ap_id = card;
target.dom_id = domain;
prep_urb(urb, &target, 1,
req, sizeof(*req) + sizeof(*req_pl),
rep, sizeof(*rep) + sizeof(*rep_pl));
rc = zcrypt_send_ep11_cprb(urb);
if (rc) {
DEBUG_ERR(
"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
__func__, (int) card, (int) domain, rc);
goto out;
}
rc = check_reply_pl((u8 *)rep_pl, __func__);
if (rc)
goto out;
if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
DEBUG_ERR("%s unknown reply data format\n", __func__);
rc = -EIO;
goto out;
}
if (rep_pl->data_len > *keybufsize) {
DEBUG_ERR("%s mismatch reply data len / key buffer len\n",
__func__);
rc = -ENOSPC;
goto out;
}
/* copy key blob and set header values */
memcpy(keybuf, rep_pl->data, rep_pl->data_len);
*keybufsize = rep_pl->data_len;
kb = (struct ep11keyblob *) keybuf;
kb->head.type = TOKTYPE_NON_CCA;
kb->head.len = rep_pl->data_len;
kb->head.version = TOKVER_EP11_AES;
kb->head.keybitlen = keybitsize;
out:
kfree(req);
kfree(rep);
kfree(urb);
return rc;
}