int ep11_genaeskey()

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;
}