int cca_gencipherkey()

in crypto/zcrypt_ccamisc.c [744:936]


int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
		     u8 *keybuf, size_t *keybufsize)
{
	int rc;
	u8 *mem, *ptr;
	struct CPRBX *preqcblk, *prepcblk;
	struct ica_xcRB xcrb;
	struct gkreqparm {
		u8  subfunc_code[2];
		u16 rule_array_len;
		char rule_array[2*8];
		struct {
			u16 len;
			u8  key_type_1[8];
			u8  key_type_2[8];
			u16 clear_key_bit_len;
			u16 key_name_1_len;
			u16 key_name_2_len;
			u16 user_data_1_len;
			u16 user_data_2_len;
			u8  key_name_1[0];
			u8  key_name_2[0];
			u8  user_data_1[0];
			u8  user_data_2[0];
		} vud;
		struct {
			u16 len;
			struct {
				u16 len;
				u16 flag;
				u8  kek_id_1[0];
			} tlv1;
			struct {
				u16 len;
				u16 flag;
				u8  kek_id_2[0];
			} tlv2;
			struct {
				u16 len;
				u16 flag;
				u8  gen_key_id_1[SIZEOF_SKELETON];
			} tlv3;
			struct {
				u16 len;
				u16 flag;
				u8  gen_key_id_1_label[0];
			} tlv4;
			struct {
				u16 len;
				u16 flag;
				u8  gen_key_id_2[0];
			} tlv5;
			struct {
				u16 len;
				u16 flag;
				u8  gen_key_id_2_label[0];
			} tlv6;
		} kb;
	} __packed * preqparm;
	struct gkrepparm {
		u8  subfunc_code[2];
		u16 rule_array_len;
		struct {
			u16 len;
		} vud;
		struct {
			u16 len;
			struct {
				u16 len;
				u16 flag;
				u8  gen_key[0]; /* 120-136 bytes */
			} tlv1;
		} kb;
	} __packed * prepparm;
	struct cipherkeytoken *t;

	/* get already prepared memory for 2 cprbs with param block each */
	rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
	if (rc)
		return rc;

	/* fill request cprb struct */
	preqcblk->domain = domain;
	preqcblk->req_parml = sizeof(struct gkreqparm);

	/* prepare request param block with GK request */
	preqparm = (struct gkreqparm __force *) preqcblk->req_parmb;
	memcpy(preqparm->subfunc_code, "GK", 2);
	preqparm->rule_array_len =  sizeof(uint16_t) + 2 * 8;
	memcpy(preqparm->rule_array, "AES     OP      ", 2*8);

	/* prepare vud block */
	preqparm->vud.len = sizeof(preqparm->vud);
	switch (keybitsize) {
	case 128:
	case 192:
	case 256:
		break;
	default:
		DEBUG_ERR(
			"%s unknown/unsupported keybitsize %d\n",
			__func__, keybitsize);
		rc = -EINVAL;
		goto out;
	}
	preqparm->vud.clear_key_bit_len = keybitsize;
	memcpy(preqparm->vud.key_type_1, "TOKEN   ", 8);
	memset(preqparm->vud.key_type_2, ' ', sizeof(preqparm->vud.key_type_2));

	/* prepare kb block */
	preqparm->kb.len = sizeof(preqparm->kb);
	preqparm->kb.tlv1.len = sizeof(preqparm->kb.tlv1);
	preqparm->kb.tlv1.flag = 0x0030;
	preqparm->kb.tlv2.len = sizeof(preqparm->kb.tlv2);
	preqparm->kb.tlv2.flag = 0x0030;
	preqparm->kb.tlv3.len = sizeof(preqparm->kb.tlv3);
	preqparm->kb.tlv3.flag = 0x0030;
	memcpy(preqparm->kb.tlv3.gen_key_id_1,
	       aes_cipher_key_skeleton, SIZEOF_SKELETON);
	preqparm->kb.tlv4.len = sizeof(preqparm->kb.tlv4);
	preqparm->kb.tlv4.flag = 0x0030;
	preqparm->kb.tlv5.len = sizeof(preqparm->kb.tlv5);
	preqparm->kb.tlv5.flag = 0x0030;
	preqparm->kb.tlv6.len = sizeof(preqparm->kb.tlv6);
	preqparm->kb.tlv6.flag = 0x0030;

	/* patch the skeleton key token export flags inside the kb block */
	if (keygenflags) {
		t = (struct cipherkeytoken *) preqparm->kb.tlv3.gen_key_id_1;
		t->kmf1 |= (u16) (keygenflags & 0x0000FF00);
		t->kmf1 &= (u16) ~(keygenflags & 0x000000FF);
	}

	/* prepare xcrb struct */
	prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);

	/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
	rc = zcrypt_send_cprb(&xcrb);
	if (rc) {
		DEBUG_ERR(
			"%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
			__func__, (int) cardnr, (int) domain, rc);
		goto out;
	}

	/* check response returncode and reasoncode */
	if (prepcblk->ccp_rtcode != 0) {
		DEBUG_ERR(
			"%s cipher key generate failure, card response %d/%d\n",
			__func__,
			(int) prepcblk->ccp_rtcode,
			(int) prepcblk->ccp_rscode);
		rc = -EIO;
		goto out;
	}

	/* process response cprb param block */
	ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX);
	prepcblk->rpl_parmb = (u8 __user *) ptr;
	prepparm = (struct gkrepparm *) ptr;

	/* do some plausibility checks on the key block */
	if (prepparm->kb.len < 120 + 5 * sizeof(uint16_t) ||
	    prepparm->kb.len > 136 + 5 * sizeof(uint16_t)) {
		DEBUG_ERR("%s reply with invalid or unknown key block\n",
			  __func__);
		rc = -EIO;
		goto out;
	}

	/* and some checks on the generated key */
	rc = cca_check_secaescipherkey(zcrypt_dbf_info, DBF_ERR,
				       prepparm->kb.tlv1.gen_key,
				       keybitsize, 1);
	if (rc) {
		rc = -EIO;
		goto out;
	}

	/* copy the generated vlsc key token */
	t = (struct cipherkeytoken *) prepparm->kb.tlv1.gen_key;
	if (keybuf) {
		if (*keybufsize >= t->len)
			memcpy(keybuf, t, t->len);
		else
			rc = -EINVAL;
	}
	*keybufsize = t->len;

out:
	free_cprbmem(mem, PARMBSIZE, 0);
	return rc;
}