int ep11_kblob2protkey()

in crypto/zcrypt_ep11misc.c [1266:1384]


int ep11_kblob2protkey(u16 card, u16 dom, const u8 *keyblob, size_t keybloblen,
		       u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
	int rc = -EIO;
	u8 *wkbuf = NULL;
	size_t wkbuflen, keylen;
	struct wk_info {
		u16 version;
		u8  res1[16];
		u32 pkeytype;
		u32 pkeybitsize;
		u64 pkeysize;
		u8  res2[8];
		u8  pkey[0];
	} __packed * wki;
	const u8 *key;
	struct ep11kblob_header *hdr;

	/* key with or without header ? */
	hdr = (struct ep11kblob_header *) keyblob;
	if (hdr->type == TOKTYPE_NON_CCA
	    && (hdr->version == TOKVER_EP11_AES_WITH_HEADER
		|| hdr->version == TOKVER_EP11_ECC_WITH_HEADER)
	    && is_ep11_keyblob(keyblob + sizeof(struct ep11kblob_header))) {
		/* EP11 AES or ECC key with header */
		key = keyblob + sizeof(struct ep11kblob_header);
		keylen = hdr->len - sizeof(struct ep11kblob_header);
	} else if (hdr->type == TOKTYPE_NON_CCA
		   && hdr->version == TOKVER_EP11_AES
		   && is_ep11_keyblob(keyblob)) {
		/* EP11 AES key (old style) */
		key = keyblob;
		keylen = hdr->len;
	} else if (is_ep11_keyblob(keyblob)) {
		/* raw EP11 key blob */
		key = keyblob;
		keylen = keybloblen;
	} else
		return -EINVAL;

	/* alloc temp working buffer */
	wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1));
	wkbuf = kmalloc(wkbuflen, GFP_ATOMIC);
	if (!wkbuf)
		return -ENOMEM;

	/* ep11 secure key -> protected key + info */
	rc = ep11_wrapkey(card, dom, key, keylen,
			  0, def_iv, wkbuf, &wkbuflen);
	if (rc) {
		DEBUG_ERR(
			"%s rewrapping ep11 key to pkey failed, rc=%d\n",
			__func__, rc);
		goto out;
	}
	wki = (struct wk_info *) wkbuf;

	/* check struct version and pkey type */
	if (wki->version != 1 || wki->pkeytype < 1 || wki->pkeytype > 5) {
		DEBUG_ERR("%s wk info version %d or pkeytype %d mismatch.\n",
			  __func__, (int) wki->version, (int) wki->pkeytype);
		rc = -EIO;
		goto out;
	}

	/* check protected key type field */
	switch (wki->pkeytype) {
	case 1: /* AES */
		switch (wki->pkeysize) {
		case 16+32:
			/* AES 128 protected key */
			if (protkeytype)
				*protkeytype = PKEY_KEYTYPE_AES_128;
			break;
		case 24+32:
			/* AES 192 protected key */
			if (protkeytype)
				*protkeytype = PKEY_KEYTYPE_AES_192;
			break;
		case 32+32:
			/* AES 256 protected key */
			if (protkeytype)
				*protkeytype = PKEY_KEYTYPE_AES_256;
			break;
		default:
			DEBUG_ERR("%s unknown/unsupported AES pkeysize %d\n",
				  __func__, (int) wki->pkeysize);
			rc = -EIO;
			goto out;
		}
		break;
	case 3: /* EC-P */
	case 4: /* EC-ED */
	case 5: /* EC-BP */
		if (protkeytype)
			*protkeytype = PKEY_KEYTYPE_ECC;
		break;
	case 2: /* TDES */
	default:
		DEBUG_ERR("%s unknown/unsupported key type %d\n",
			  __func__, (int) wki->pkeytype);
		rc = -EIO;
		goto out;
	}

	/* copy the tanslated protected key */
	if (wki->pkeysize > *protkeylen) {
		DEBUG_ERR("%s wk info pkeysize %llu > protkeysize %u\n",
			  __func__, wki->pkeysize, *protkeylen);
		rc = -EINVAL;
		goto out;
	}
	memcpy(protkey, wki->pkey, wki->pkeysize);
	*protkeylen = wki->pkeysize;

out:
	kfree(wkbuf);
	return rc;
}