147f9c279SSumit Garg // SPDX-License-Identifier: GPL-2.0-only
247f9c279SSumit Garg /*
347f9c279SSumit Garg  * Copyright (C) 2010 IBM Corporation
447f9c279SSumit Garg  *
547f9c279SSumit Garg  * Author:
647f9c279SSumit Garg  * David Safford <safford@us.ibm.com>
747f9c279SSumit Garg  *
847f9c279SSumit Garg  * See Documentation/security/keys/trusted-encrypted.rst
947f9c279SSumit Garg  */
1047f9c279SSumit Garg 
1147f9c279SSumit Garg #include <crypto/hash_info.h>
1247f9c279SSumit Garg #include <linux/uaccess.h>
1347f9c279SSumit Garg #include <linux/module.h>
1447f9c279SSumit Garg #include <linux/init.h>
1547f9c279SSumit Garg #include <linux/slab.h>
1647f9c279SSumit Garg #include <linux/parser.h>
1747f9c279SSumit Garg #include <linux/string.h>
1847f9c279SSumit Garg #include <linux/err.h>
1947f9c279SSumit Garg #include <keys/user-type.h>
2047f9c279SSumit Garg #include <keys/trusted-type.h>
2147f9c279SSumit Garg #include <linux/key-type.h>
2247f9c279SSumit Garg #include <linux/rcupdate.h>
2347f9c279SSumit Garg #include <linux/crypto.h>
2447f9c279SSumit Garg #include <crypto/hash.h>
25*a24d22b2SEric Biggers #include <crypto/sha1.h>
2647f9c279SSumit Garg #include <linux/capability.h>
2747f9c279SSumit Garg #include <linux/tpm.h>
2847f9c279SSumit Garg #include <linux/tpm_command.h>
2947f9c279SSumit Garg 
3047f9c279SSumit Garg #include <keys/trusted_tpm.h>
3147f9c279SSumit Garg 
3247f9c279SSumit Garg static const char hmac_alg[] = "hmac(sha1)";
3347f9c279SSumit Garg static const char hash_alg[] = "sha1";
3447f9c279SSumit Garg static struct tpm_chip *chip;
3547f9c279SSumit Garg static struct tpm_digest *digests;
3647f9c279SSumit Garg 
3747f9c279SSumit Garg struct sdesc {
3847f9c279SSumit Garg 	struct shash_desc shash;
3947f9c279SSumit Garg 	char ctx[];
4047f9c279SSumit Garg };
4147f9c279SSumit Garg 
4247f9c279SSumit Garg static struct crypto_shash *hashalg;
4347f9c279SSumit Garg static struct crypto_shash *hmacalg;
4447f9c279SSumit Garg 
4547f9c279SSumit Garg static struct sdesc *init_sdesc(struct crypto_shash *alg)
4647f9c279SSumit Garg {
4747f9c279SSumit Garg 	struct sdesc *sdesc;
4847f9c279SSumit Garg 	int size;
4947f9c279SSumit Garg 
5047f9c279SSumit Garg 	size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
5147f9c279SSumit Garg 	sdesc = kmalloc(size, GFP_KERNEL);
5247f9c279SSumit Garg 	if (!sdesc)
5347f9c279SSumit Garg 		return ERR_PTR(-ENOMEM);
5447f9c279SSumit Garg 	sdesc->shash.tfm = alg;
5547f9c279SSumit Garg 	return sdesc;
5647f9c279SSumit Garg }
5747f9c279SSumit Garg 
5847f9c279SSumit Garg static int TSS_sha1(const unsigned char *data, unsigned int datalen,
5947f9c279SSumit Garg 		    unsigned char *digest)
6047f9c279SSumit Garg {
6147f9c279SSumit Garg 	struct sdesc *sdesc;
6247f9c279SSumit Garg 	int ret;
6347f9c279SSumit Garg 
6447f9c279SSumit Garg 	sdesc = init_sdesc(hashalg);
6547f9c279SSumit Garg 	if (IS_ERR(sdesc)) {
6647f9c279SSumit Garg 		pr_info("trusted_key: can't alloc %s\n", hash_alg);
6747f9c279SSumit Garg 		return PTR_ERR(sdesc);
6847f9c279SSumit Garg 	}
6947f9c279SSumit Garg 
7047f9c279SSumit Garg 	ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
71453431a5SWaiman Long 	kfree_sensitive(sdesc);
7247f9c279SSumit Garg 	return ret;
7347f9c279SSumit Garg }
7447f9c279SSumit Garg 
7547f9c279SSumit Garg static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,
7647f9c279SSumit Garg 		       unsigned int keylen, ...)
7747f9c279SSumit Garg {
7847f9c279SSumit Garg 	struct sdesc *sdesc;
7947f9c279SSumit Garg 	va_list argp;
8047f9c279SSumit Garg 	unsigned int dlen;
8147f9c279SSumit Garg 	unsigned char *data;
8247f9c279SSumit Garg 	int ret;
8347f9c279SSumit Garg 
8447f9c279SSumit Garg 	sdesc = init_sdesc(hmacalg);
8547f9c279SSumit Garg 	if (IS_ERR(sdesc)) {
8647f9c279SSumit Garg 		pr_info("trusted_key: can't alloc %s\n", hmac_alg);
8747f9c279SSumit Garg 		return PTR_ERR(sdesc);
8847f9c279SSumit Garg 	}
8947f9c279SSumit Garg 
9047f9c279SSumit Garg 	ret = crypto_shash_setkey(hmacalg, key, keylen);
9147f9c279SSumit Garg 	if (ret < 0)
9247f9c279SSumit Garg 		goto out;
9347f9c279SSumit Garg 	ret = crypto_shash_init(&sdesc->shash);
9447f9c279SSumit Garg 	if (ret < 0)
9547f9c279SSumit Garg 		goto out;
9647f9c279SSumit Garg 
9747f9c279SSumit Garg 	va_start(argp, keylen);
9847f9c279SSumit Garg 	for (;;) {
9947f9c279SSumit Garg 		dlen = va_arg(argp, unsigned int);
10047f9c279SSumit Garg 		if (dlen == 0)
10147f9c279SSumit Garg 			break;
10247f9c279SSumit Garg 		data = va_arg(argp, unsigned char *);
10347f9c279SSumit Garg 		if (data == NULL) {
10447f9c279SSumit Garg 			ret = -EINVAL;
10547f9c279SSumit Garg 			break;
10647f9c279SSumit Garg 		}
10747f9c279SSumit Garg 		ret = crypto_shash_update(&sdesc->shash, data, dlen);
10847f9c279SSumit Garg 		if (ret < 0)
10947f9c279SSumit Garg 			break;
11047f9c279SSumit Garg 	}
11147f9c279SSumit Garg 	va_end(argp);
11247f9c279SSumit Garg 	if (!ret)
11347f9c279SSumit Garg 		ret = crypto_shash_final(&sdesc->shash, digest);
11447f9c279SSumit Garg out:
115453431a5SWaiman Long 	kfree_sensitive(sdesc);
11647f9c279SSumit Garg 	return ret;
11747f9c279SSumit Garg }
11847f9c279SSumit Garg 
11947f9c279SSumit Garg /*
12047f9c279SSumit Garg  * calculate authorization info fields to send to TPM
12147f9c279SSumit Garg  */
12247f9c279SSumit Garg int TSS_authhmac(unsigned char *digest, const unsigned char *key,
12347f9c279SSumit Garg 			unsigned int keylen, unsigned char *h1,
12447f9c279SSumit Garg 			unsigned char *h2, unsigned int h3, ...)
12547f9c279SSumit Garg {
12647f9c279SSumit Garg 	unsigned char paramdigest[SHA1_DIGEST_SIZE];
12747f9c279SSumit Garg 	struct sdesc *sdesc;
12847f9c279SSumit Garg 	unsigned int dlen;
12947f9c279SSumit Garg 	unsigned char *data;
13047f9c279SSumit Garg 	unsigned char c;
13147f9c279SSumit Garg 	int ret;
13247f9c279SSumit Garg 	va_list argp;
13347f9c279SSumit Garg 
13447f9c279SSumit Garg 	if (!chip)
13547f9c279SSumit Garg 		return -ENODEV;
13647f9c279SSumit Garg 
13747f9c279SSumit Garg 	sdesc = init_sdesc(hashalg);
13847f9c279SSumit Garg 	if (IS_ERR(sdesc)) {
13947f9c279SSumit Garg 		pr_info("trusted_key: can't alloc %s\n", hash_alg);
14047f9c279SSumit Garg 		return PTR_ERR(sdesc);
14147f9c279SSumit Garg 	}
14247f9c279SSumit Garg 
14347f9c279SSumit Garg 	c = !!h3;
14447f9c279SSumit Garg 	ret = crypto_shash_init(&sdesc->shash);
14547f9c279SSumit Garg 	if (ret < 0)
14647f9c279SSumit Garg 		goto out;
14747f9c279SSumit Garg 	va_start(argp, h3);
14847f9c279SSumit Garg 	for (;;) {
14947f9c279SSumit Garg 		dlen = va_arg(argp, unsigned int);
15047f9c279SSumit Garg 		if (dlen == 0)
15147f9c279SSumit Garg 			break;
15247f9c279SSumit Garg 		data = va_arg(argp, unsigned char *);
15347f9c279SSumit Garg 		if (!data) {
15447f9c279SSumit Garg 			ret = -EINVAL;
15547f9c279SSumit Garg 			break;
15647f9c279SSumit Garg 		}
15747f9c279SSumit Garg 		ret = crypto_shash_update(&sdesc->shash, data, dlen);
15847f9c279SSumit Garg 		if (ret < 0)
15947f9c279SSumit Garg 			break;
16047f9c279SSumit Garg 	}
16147f9c279SSumit Garg 	va_end(argp);
16247f9c279SSumit Garg 	if (!ret)
16347f9c279SSumit Garg 		ret = crypto_shash_final(&sdesc->shash, paramdigest);
16447f9c279SSumit Garg 	if (!ret)
16547f9c279SSumit Garg 		ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE,
16647f9c279SSumit Garg 				  paramdigest, TPM_NONCE_SIZE, h1,
16747f9c279SSumit Garg 				  TPM_NONCE_SIZE, h2, 1, &c, 0, 0);
16847f9c279SSumit Garg out:
169453431a5SWaiman Long 	kfree_sensitive(sdesc);
17047f9c279SSumit Garg 	return ret;
17147f9c279SSumit Garg }
17247f9c279SSumit Garg EXPORT_SYMBOL_GPL(TSS_authhmac);
17347f9c279SSumit Garg 
17447f9c279SSumit Garg /*
17547f9c279SSumit Garg  * verify the AUTH1_COMMAND (Seal) result from TPM
17647f9c279SSumit Garg  */
17747f9c279SSumit Garg int TSS_checkhmac1(unsigned char *buffer,
17847f9c279SSumit Garg 			  const uint32_t command,
17947f9c279SSumit Garg 			  const unsigned char *ononce,
18047f9c279SSumit Garg 			  const unsigned char *key,
18147f9c279SSumit Garg 			  unsigned int keylen, ...)
18247f9c279SSumit Garg {
18347f9c279SSumit Garg 	uint32_t bufsize;
18447f9c279SSumit Garg 	uint16_t tag;
18547f9c279SSumit Garg 	uint32_t ordinal;
18647f9c279SSumit Garg 	uint32_t result;
18747f9c279SSumit Garg 	unsigned char *enonce;
18847f9c279SSumit Garg 	unsigned char *continueflag;
18947f9c279SSumit Garg 	unsigned char *authdata;
19047f9c279SSumit Garg 	unsigned char testhmac[SHA1_DIGEST_SIZE];
19147f9c279SSumit Garg 	unsigned char paramdigest[SHA1_DIGEST_SIZE];
19247f9c279SSumit Garg 	struct sdesc *sdesc;
19347f9c279SSumit Garg 	unsigned int dlen;
19447f9c279SSumit Garg 	unsigned int dpos;
19547f9c279SSumit Garg 	va_list argp;
19647f9c279SSumit Garg 	int ret;
19747f9c279SSumit Garg 
19847f9c279SSumit Garg 	if (!chip)
19947f9c279SSumit Garg 		return -ENODEV;
20047f9c279SSumit Garg 
20147f9c279SSumit Garg 	bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
20247f9c279SSumit Garg 	tag = LOAD16(buffer, 0);
20347f9c279SSumit Garg 	ordinal = command;
20447f9c279SSumit Garg 	result = LOAD32N(buffer, TPM_RETURN_OFFSET);
20547f9c279SSumit Garg 	if (tag == TPM_TAG_RSP_COMMAND)
20647f9c279SSumit Garg 		return 0;
20747f9c279SSumit Garg 	if (tag != TPM_TAG_RSP_AUTH1_COMMAND)
20847f9c279SSumit Garg 		return -EINVAL;
20947f9c279SSumit Garg 	authdata = buffer + bufsize - SHA1_DIGEST_SIZE;
21047f9c279SSumit Garg 	continueflag = authdata - 1;
21147f9c279SSumit Garg 	enonce = continueflag - TPM_NONCE_SIZE;
21247f9c279SSumit Garg 
21347f9c279SSumit Garg 	sdesc = init_sdesc(hashalg);
21447f9c279SSumit Garg 	if (IS_ERR(sdesc)) {
21547f9c279SSumit Garg 		pr_info("trusted_key: can't alloc %s\n", hash_alg);
21647f9c279SSumit Garg 		return PTR_ERR(sdesc);
21747f9c279SSumit Garg 	}
21847f9c279SSumit Garg 	ret = crypto_shash_init(&sdesc->shash);
21947f9c279SSumit Garg 	if (ret < 0)
22047f9c279SSumit Garg 		goto out;
22147f9c279SSumit Garg 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
22247f9c279SSumit Garg 				  sizeof result);
22347f9c279SSumit Garg 	if (ret < 0)
22447f9c279SSumit Garg 		goto out;
22547f9c279SSumit Garg 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
22647f9c279SSumit Garg 				  sizeof ordinal);
22747f9c279SSumit Garg 	if (ret < 0)
22847f9c279SSumit Garg 		goto out;
22947f9c279SSumit Garg 	va_start(argp, keylen);
23047f9c279SSumit Garg 	for (;;) {
23147f9c279SSumit Garg 		dlen = va_arg(argp, unsigned int);
23247f9c279SSumit Garg 		if (dlen == 0)
23347f9c279SSumit Garg 			break;
23447f9c279SSumit Garg 		dpos = va_arg(argp, unsigned int);
23547f9c279SSumit Garg 		ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
23647f9c279SSumit Garg 		if (ret < 0)
23747f9c279SSumit Garg 			break;
23847f9c279SSumit Garg 	}
23947f9c279SSumit Garg 	va_end(argp);
24047f9c279SSumit Garg 	if (!ret)
24147f9c279SSumit Garg 		ret = crypto_shash_final(&sdesc->shash, paramdigest);
24247f9c279SSumit Garg 	if (ret < 0)
24347f9c279SSumit Garg 		goto out;
24447f9c279SSumit Garg 
24547f9c279SSumit Garg 	ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest,
24647f9c279SSumit Garg 			  TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce,
24747f9c279SSumit Garg 			  1, continueflag, 0, 0);
24847f9c279SSumit Garg 	if (ret < 0)
24947f9c279SSumit Garg 		goto out;
25047f9c279SSumit Garg 
25147f9c279SSumit Garg 	if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE))
25247f9c279SSumit Garg 		ret = -EINVAL;
25347f9c279SSumit Garg out:
254453431a5SWaiman Long 	kfree_sensitive(sdesc);
25547f9c279SSumit Garg 	return ret;
25647f9c279SSumit Garg }
25747f9c279SSumit Garg EXPORT_SYMBOL_GPL(TSS_checkhmac1);
25847f9c279SSumit Garg 
25947f9c279SSumit Garg /*
26047f9c279SSumit Garg  * verify the AUTH2_COMMAND (unseal) result from TPM
26147f9c279SSumit Garg  */
26247f9c279SSumit Garg static int TSS_checkhmac2(unsigned char *buffer,
26347f9c279SSumit Garg 			  const uint32_t command,
26447f9c279SSumit Garg 			  const unsigned char *ononce,
26547f9c279SSumit Garg 			  const unsigned char *key1,
26647f9c279SSumit Garg 			  unsigned int keylen1,
26747f9c279SSumit Garg 			  const unsigned char *key2,
26847f9c279SSumit Garg 			  unsigned int keylen2, ...)
26947f9c279SSumit Garg {
27047f9c279SSumit Garg 	uint32_t bufsize;
27147f9c279SSumit Garg 	uint16_t tag;
27247f9c279SSumit Garg 	uint32_t ordinal;
27347f9c279SSumit Garg 	uint32_t result;
27447f9c279SSumit Garg 	unsigned char *enonce1;
27547f9c279SSumit Garg 	unsigned char *continueflag1;
27647f9c279SSumit Garg 	unsigned char *authdata1;
27747f9c279SSumit Garg 	unsigned char *enonce2;
27847f9c279SSumit Garg 	unsigned char *continueflag2;
27947f9c279SSumit Garg 	unsigned char *authdata2;
28047f9c279SSumit Garg 	unsigned char testhmac1[SHA1_DIGEST_SIZE];
28147f9c279SSumit Garg 	unsigned char testhmac2[SHA1_DIGEST_SIZE];
28247f9c279SSumit Garg 	unsigned char paramdigest[SHA1_DIGEST_SIZE];
28347f9c279SSumit Garg 	struct sdesc *sdesc;
28447f9c279SSumit Garg 	unsigned int dlen;
28547f9c279SSumit Garg 	unsigned int dpos;
28647f9c279SSumit Garg 	va_list argp;
28747f9c279SSumit Garg 	int ret;
28847f9c279SSumit Garg 
28947f9c279SSumit Garg 	bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
29047f9c279SSumit Garg 	tag = LOAD16(buffer, 0);
29147f9c279SSumit Garg 	ordinal = command;
29247f9c279SSumit Garg 	result = LOAD32N(buffer, TPM_RETURN_OFFSET);
29347f9c279SSumit Garg 
29447f9c279SSumit Garg 	if (tag == TPM_TAG_RSP_COMMAND)
29547f9c279SSumit Garg 		return 0;
29647f9c279SSumit Garg 	if (tag != TPM_TAG_RSP_AUTH2_COMMAND)
29747f9c279SSumit Garg 		return -EINVAL;
29847f9c279SSumit Garg 	authdata1 = buffer + bufsize - (SHA1_DIGEST_SIZE + 1
29947f9c279SSumit Garg 			+ SHA1_DIGEST_SIZE + SHA1_DIGEST_SIZE);
30047f9c279SSumit Garg 	authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE);
30147f9c279SSumit Garg 	continueflag1 = authdata1 - 1;
30247f9c279SSumit Garg 	continueflag2 = authdata2 - 1;
30347f9c279SSumit Garg 	enonce1 = continueflag1 - TPM_NONCE_SIZE;
30447f9c279SSumit Garg 	enonce2 = continueflag2 - TPM_NONCE_SIZE;
30547f9c279SSumit Garg 
30647f9c279SSumit Garg 	sdesc = init_sdesc(hashalg);
30747f9c279SSumit Garg 	if (IS_ERR(sdesc)) {
30847f9c279SSumit Garg 		pr_info("trusted_key: can't alloc %s\n", hash_alg);
30947f9c279SSumit Garg 		return PTR_ERR(sdesc);
31047f9c279SSumit Garg 	}
31147f9c279SSumit Garg 	ret = crypto_shash_init(&sdesc->shash);
31247f9c279SSumit Garg 	if (ret < 0)
31347f9c279SSumit Garg 		goto out;
31447f9c279SSumit Garg 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
31547f9c279SSumit Garg 				  sizeof result);
31647f9c279SSumit Garg 	if (ret < 0)
31747f9c279SSumit Garg 		goto out;
31847f9c279SSumit Garg 	ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
31947f9c279SSumit Garg 				  sizeof ordinal);
32047f9c279SSumit Garg 	if (ret < 0)
32147f9c279SSumit Garg 		goto out;
32247f9c279SSumit Garg 
32347f9c279SSumit Garg 	va_start(argp, keylen2);
32447f9c279SSumit Garg 	for (;;) {
32547f9c279SSumit Garg 		dlen = va_arg(argp, unsigned int);
32647f9c279SSumit Garg 		if (dlen == 0)
32747f9c279SSumit Garg 			break;
32847f9c279SSumit Garg 		dpos = va_arg(argp, unsigned int);
32947f9c279SSumit Garg 		ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
33047f9c279SSumit Garg 		if (ret < 0)
33147f9c279SSumit Garg 			break;
33247f9c279SSumit Garg 	}
33347f9c279SSumit Garg 	va_end(argp);
33447f9c279SSumit Garg 	if (!ret)
33547f9c279SSumit Garg 		ret = crypto_shash_final(&sdesc->shash, paramdigest);
33647f9c279SSumit Garg 	if (ret < 0)
33747f9c279SSumit Garg 		goto out;
33847f9c279SSumit Garg 
33947f9c279SSumit Garg 	ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE,
34047f9c279SSumit Garg 			  paramdigest, TPM_NONCE_SIZE, enonce1,
34147f9c279SSumit Garg 			  TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0);
34247f9c279SSumit Garg 	if (ret < 0)
34347f9c279SSumit Garg 		goto out;
34447f9c279SSumit Garg 	if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) {
34547f9c279SSumit Garg 		ret = -EINVAL;
34647f9c279SSumit Garg 		goto out;
34747f9c279SSumit Garg 	}
34847f9c279SSumit Garg 	ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE,
34947f9c279SSumit Garg 			  paramdigest, TPM_NONCE_SIZE, enonce2,
35047f9c279SSumit Garg 			  TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0);
35147f9c279SSumit Garg 	if (ret < 0)
35247f9c279SSumit Garg 		goto out;
35347f9c279SSumit Garg 	if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE))
35447f9c279SSumit Garg 		ret = -EINVAL;
35547f9c279SSumit Garg out:
356453431a5SWaiman Long 	kfree_sensitive(sdesc);
35747f9c279SSumit Garg 	return ret;
35847f9c279SSumit Garg }
35947f9c279SSumit Garg 
36047f9c279SSumit Garg /*
36147f9c279SSumit Garg  * For key specific tpm requests, we will generate and send our
36247f9c279SSumit Garg  * own TPM command packets using the drivers send function.
36347f9c279SSumit Garg  */
36447f9c279SSumit Garg int trusted_tpm_send(unsigned char *cmd, size_t buflen)
36547f9c279SSumit Garg {
36647f9c279SSumit Garg 	int rc;
36747f9c279SSumit Garg 
36847f9c279SSumit Garg 	if (!chip)
36947f9c279SSumit Garg 		return -ENODEV;
37047f9c279SSumit Garg 
37147f9c279SSumit Garg 	dump_tpm_buf(cmd);
37247f9c279SSumit Garg 	rc = tpm_send(chip, cmd, buflen);
37347f9c279SSumit Garg 	dump_tpm_buf(cmd);
37447f9c279SSumit Garg 	if (rc > 0)
37547f9c279SSumit Garg 		/* Can't return positive return codes values to keyctl */
37647f9c279SSumit Garg 		rc = -EPERM;
37747f9c279SSumit Garg 	return rc;
37847f9c279SSumit Garg }
37947f9c279SSumit Garg EXPORT_SYMBOL_GPL(trusted_tpm_send);
38047f9c279SSumit Garg 
38147f9c279SSumit Garg /*
38247f9c279SSumit Garg  * Lock a trusted key, by extending a selected PCR.
38347f9c279SSumit Garg  *
38447f9c279SSumit Garg  * Prevents a trusted key that is sealed to PCRs from being accessed.
38547f9c279SSumit Garg  * This uses the tpm driver's extend function.
38647f9c279SSumit Garg  */
38747f9c279SSumit Garg static int pcrlock(const int pcrnum)
38847f9c279SSumit Garg {
38947f9c279SSumit Garg 	if (!capable(CAP_SYS_ADMIN))
39047f9c279SSumit Garg 		return -EPERM;
39147f9c279SSumit Garg 
39247f9c279SSumit Garg 	return tpm_pcr_extend(chip, pcrnum, digests) ? -EINVAL : 0;
39347f9c279SSumit Garg }
39447f9c279SSumit Garg 
39547f9c279SSumit Garg /*
39647f9c279SSumit Garg  * Create an object specific authorisation protocol (OSAP) session
39747f9c279SSumit Garg  */
39847f9c279SSumit Garg static int osap(struct tpm_buf *tb, struct osapsess *s,
39947f9c279SSumit Garg 		const unsigned char *key, uint16_t type, uint32_t handle)
40047f9c279SSumit Garg {
40147f9c279SSumit Garg 	unsigned char enonce[TPM_NONCE_SIZE];
40247f9c279SSumit Garg 	unsigned char ononce[TPM_NONCE_SIZE];
40347f9c279SSumit Garg 	int ret;
40447f9c279SSumit Garg 
40547f9c279SSumit Garg 	ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE);
40647f9c279SSumit Garg 	if (ret != TPM_NONCE_SIZE)
40747f9c279SSumit Garg 		return ret;
40847f9c279SSumit Garg 
40947f9c279SSumit Garg 	tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP);
41047f9c279SSumit Garg 	tpm_buf_append_u16(tb, type);
41147f9c279SSumit Garg 	tpm_buf_append_u32(tb, handle);
41247f9c279SSumit Garg 	tpm_buf_append(tb, ononce, TPM_NONCE_SIZE);
41347f9c279SSumit Garg 
41447f9c279SSumit Garg 	ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
41547f9c279SSumit Garg 	if (ret < 0)
41647f9c279SSumit Garg 		return ret;
41747f9c279SSumit Garg 
41847f9c279SSumit Garg 	s->handle = LOAD32(tb->data, TPM_DATA_OFFSET);
41947f9c279SSumit Garg 	memcpy(s->enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]),
42047f9c279SSumit Garg 	       TPM_NONCE_SIZE);
42147f9c279SSumit Garg 	memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +
42247f9c279SSumit Garg 				  TPM_NONCE_SIZE]), TPM_NONCE_SIZE);
42347f9c279SSumit Garg 	return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE,
42447f9c279SSumit Garg 			   enonce, TPM_NONCE_SIZE, ononce, 0, 0);
42547f9c279SSumit Garg }
42647f9c279SSumit Garg 
42747f9c279SSumit Garg /*
42847f9c279SSumit Garg  * Create an object independent authorisation protocol (oiap) session
42947f9c279SSumit Garg  */
43047f9c279SSumit Garg int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
43147f9c279SSumit Garg {
43247f9c279SSumit Garg 	int ret;
43347f9c279SSumit Garg 
43447f9c279SSumit Garg 	if (!chip)
43547f9c279SSumit Garg 		return -ENODEV;
43647f9c279SSumit Garg 
43747f9c279SSumit Garg 	tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP);
43847f9c279SSumit Garg 	ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
43947f9c279SSumit Garg 	if (ret < 0)
44047f9c279SSumit Garg 		return ret;
44147f9c279SSumit Garg 
44247f9c279SSumit Garg 	*handle = LOAD32(tb->data, TPM_DATA_OFFSET);
44347f9c279SSumit Garg 	memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)],
44447f9c279SSumit Garg 	       TPM_NONCE_SIZE);
44547f9c279SSumit Garg 	return 0;
44647f9c279SSumit Garg }
44747f9c279SSumit Garg EXPORT_SYMBOL_GPL(oiap);
44847f9c279SSumit Garg 
44947f9c279SSumit Garg struct tpm_digests {
45047f9c279SSumit Garg 	unsigned char encauth[SHA1_DIGEST_SIZE];
45147f9c279SSumit Garg 	unsigned char pubauth[SHA1_DIGEST_SIZE];
45247f9c279SSumit Garg 	unsigned char xorwork[SHA1_DIGEST_SIZE * 2];
45347f9c279SSumit Garg 	unsigned char xorhash[SHA1_DIGEST_SIZE];
45447f9c279SSumit Garg 	unsigned char nonceodd[TPM_NONCE_SIZE];
45547f9c279SSumit Garg };
45647f9c279SSumit Garg 
45747f9c279SSumit Garg /*
45847f9c279SSumit Garg  * Have the TPM seal(encrypt) the trusted key, possibly based on
45947f9c279SSumit Garg  * Platform Configuration Registers (PCRs). AUTH1 for sealing key.
46047f9c279SSumit Garg  */
46147f9c279SSumit Garg static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
46247f9c279SSumit Garg 		    uint32_t keyhandle, const unsigned char *keyauth,
46347f9c279SSumit Garg 		    const unsigned char *data, uint32_t datalen,
46447f9c279SSumit Garg 		    unsigned char *blob, uint32_t *bloblen,
46547f9c279SSumit Garg 		    const unsigned char *blobauth,
46647f9c279SSumit Garg 		    const unsigned char *pcrinfo, uint32_t pcrinfosize)
46747f9c279SSumit Garg {
46847f9c279SSumit Garg 	struct osapsess sess;
46947f9c279SSumit Garg 	struct tpm_digests *td;
47047f9c279SSumit Garg 	unsigned char cont;
47147f9c279SSumit Garg 	uint32_t ordinal;
47247f9c279SSumit Garg 	uint32_t pcrsize;
47347f9c279SSumit Garg 	uint32_t datsize;
47447f9c279SSumit Garg 	int sealinfosize;
47547f9c279SSumit Garg 	int encdatasize;
47647f9c279SSumit Garg 	int storedsize;
47747f9c279SSumit Garg 	int ret;
47847f9c279SSumit Garg 	int i;
47947f9c279SSumit Garg 
48047f9c279SSumit Garg 	/* alloc some work space for all the hashes */
48147f9c279SSumit Garg 	td = kmalloc(sizeof *td, GFP_KERNEL);
48247f9c279SSumit Garg 	if (!td)
48347f9c279SSumit Garg 		return -ENOMEM;
48447f9c279SSumit Garg 
48547f9c279SSumit Garg 	/* get session for sealing key */
48647f9c279SSumit Garg 	ret = osap(tb, &sess, keyauth, keytype, keyhandle);
48747f9c279SSumit Garg 	if (ret < 0)
48847f9c279SSumit Garg 		goto out;
48947f9c279SSumit Garg 	dump_sess(&sess);
49047f9c279SSumit Garg 
49147f9c279SSumit Garg 	/* calculate encrypted authorization value */
49247f9c279SSumit Garg 	memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE);
49347f9c279SSumit Garg 	memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE);
49447f9c279SSumit Garg 	ret = TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);
49547f9c279SSumit Garg 	if (ret < 0)
49647f9c279SSumit Garg 		goto out;
49747f9c279SSumit Garg 
49847f9c279SSumit Garg 	ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);
49947f9c279SSumit Garg 	if (ret != TPM_NONCE_SIZE)
50047f9c279SSumit Garg 		goto out;
50147f9c279SSumit Garg 	ordinal = htonl(TPM_ORD_SEAL);
50247f9c279SSumit Garg 	datsize = htonl(datalen);
50347f9c279SSumit Garg 	pcrsize = htonl(pcrinfosize);
50447f9c279SSumit Garg 	cont = 0;
50547f9c279SSumit Garg 
50647f9c279SSumit Garg 	/* encrypt data authorization key */
50747f9c279SSumit Garg 	for (i = 0; i < SHA1_DIGEST_SIZE; ++i)
50847f9c279SSumit Garg 		td->encauth[i] = td->xorhash[i] ^ blobauth[i];
50947f9c279SSumit Garg 
51047f9c279SSumit Garg 	/* calculate authorization HMAC value */
51147f9c279SSumit Garg 	if (pcrinfosize == 0) {
51247f9c279SSumit Garg 		/* no pcr info specified */
51347f9c279SSumit Garg 		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
51447f9c279SSumit Garg 				   sess.enonce, td->nonceodd, cont,
51547f9c279SSumit Garg 				   sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,
51647f9c279SSumit Garg 				   td->encauth, sizeof(uint32_t), &pcrsize,
51747f9c279SSumit Garg 				   sizeof(uint32_t), &datsize, datalen, data, 0,
51847f9c279SSumit Garg 				   0);
51947f9c279SSumit Garg 	} else {
52047f9c279SSumit Garg 		/* pcr info specified */
52147f9c279SSumit Garg 		ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,
52247f9c279SSumit Garg 				   sess.enonce, td->nonceodd, cont,
52347f9c279SSumit Garg 				   sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,
52447f9c279SSumit Garg 				   td->encauth, sizeof(uint32_t), &pcrsize,
52547f9c279SSumit Garg 				   pcrinfosize, pcrinfo, sizeof(uint32_t),
52647f9c279SSumit Garg 				   &datsize, datalen, data, 0, 0);
52747f9c279SSumit Garg 	}
52847f9c279SSumit Garg 	if (ret < 0)
52947f9c279SSumit Garg 		goto out;
53047f9c279SSumit Garg 
53147f9c279SSumit Garg 	/* build and send the TPM request packet */
53247f9c279SSumit Garg 	tpm_buf_reset(tb, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_SEAL);
53347f9c279SSumit Garg 	tpm_buf_append_u32(tb, keyhandle);
53447f9c279SSumit Garg 	tpm_buf_append(tb, td->encauth, SHA1_DIGEST_SIZE);
53547f9c279SSumit Garg 	tpm_buf_append_u32(tb, pcrinfosize);
53647f9c279SSumit Garg 	tpm_buf_append(tb, pcrinfo, pcrinfosize);
53747f9c279SSumit Garg 	tpm_buf_append_u32(tb, datalen);
53847f9c279SSumit Garg 	tpm_buf_append(tb, data, datalen);
53947f9c279SSumit Garg 	tpm_buf_append_u32(tb, sess.handle);
54047f9c279SSumit Garg 	tpm_buf_append(tb, td->nonceodd, TPM_NONCE_SIZE);
54147f9c279SSumit Garg 	tpm_buf_append_u8(tb, cont);
54247f9c279SSumit Garg 	tpm_buf_append(tb, td->pubauth, SHA1_DIGEST_SIZE);
54347f9c279SSumit Garg 
54447f9c279SSumit Garg 	ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
54547f9c279SSumit Garg 	if (ret < 0)
54647f9c279SSumit Garg 		goto out;
54747f9c279SSumit Garg 
54847f9c279SSumit Garg 	/* calculate the size of the returned Blob */
54947f9c279SSumit Garg 	sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t));
55047f9c279SSumit Garg 	encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) +
55147f9c279SSumit Garg 			     sizeof(uint32_t) + sealinfosize);
55247f9c279SSumit Garg 	storedsize = sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize +
55347f9c279SSumit Garg 	    sizeof(uint32_t) + encdatasize;
55447f9c279SSumit Garg 
55547f9c279SSumit Garg 	/* check the HMAC in the response */
55647f9c279SSumit Garg 	ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd, sess.secret,
55747f9c279SSumit Garg 			     SHA1_DIGEST_SIZE, storedsize, TPM_DATA_OFFSET, 0,
55847f9c279SSumit Garg 			     0);
55947f9c279SSumit Garg 
56047f9c279SSumit Garg 	/* copy the returned blob to caller */
56147f9c279SSumit Garg 	if (!ret) {
56247f9c279SSumit Garg 		memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize);
56347f9c279SSumit Garg 		*bloblen = storedsize;
56447f9c279SSumit Garg 	}
56547f9c279SSumit Garg out:
566453431a5SWaiman Long 	kfree_sensitive(td);
56747f9c279SSumit Garg 	return ret;
56847f9c279SSumit Garg }
56947f9c279SSumit Garg 
57047f9c279SSumit Garg /*
57147f9c279SSumit Garg  * use the AUTH2_COMMAND form of unseal, to authorize both key and blob
57247f9c279SSumit Garg  */
57347f9c279SSumit Garg static int tpm_unseal(struct tpm_buf *tb,
57447f9c279SSumit Garg 		      uint32_t keyhandle, const unsigned char *keyauth,
57547f9c279SSumit Garg 		      const unsigned char *blob, int bloblen,
57647f9c279SSumit Garg 		      const unsigned char *blobauth,
57747f9c279SSumit Garg 		      unsigned char *data, unsigned int *datalen)
57847f9c279SSumit Garg {
57947f9c279SSumit Garg 	unsigned char nonceodd[TPM_NONCE_SIZE];
58047f9c279SSumit Garg 	unsigned char enonce1[TPM_NONCE_SIZE];
58147f9c279SSumit Garg 	unsigned char enonce2[TPM_NONCE_SIZE];
58247f9c279SSumit Garg 	unsigned char authdata1[SHA1_DIGEST_SIZE];
58347f9c279SSumit Garg 	unsigned char authdata2[SHA1_DIGEST_SIZE];
58447f9c279SSumit Garg 	uint32_t authhandle1 = 0;
58547f9c279SSumit Garg 	uint32_t authhandle2 = 0;
58647f9c279SSumit Garg 	unsigned char cont = 0;
58747f9c279SSumit Garg 	uint32_t ordinal;
58847f9c279SSumit Garg 	int ret;
58947f9c279SSumit Garg 
59047f9c279SSumit Garg 	/* sessions for unsealing key and data */
59147f9c279SSumit Garg 	ret = oiap(tb, &authhandle1, enonce1);
59247f9c279SSumit Garg 	if (ret < 0) {
59347f9c279SSumit Garg 		pr_info("trusted_key: oiap failed (%d)\n", ret);
59447f9c279SSumit Garg 		return ret;
59547f9c279SSumit Garg 	}
59647f9c279SSumit Garg 	ret = oiap(tb, &authhandle2, enonce2);
59747f9c279SSumit Garg 	if (ret < 0) {
59847f9c279SSumit Garg 		pr_info("trusted_key: oiap failed (%d)\n", ret);
59947f9c279SSumit Garg 		return ret;
60047f9c279SSumit Garg 	}
60147f9c279SSumit Garg 
60247f9c279SSumit Garg 	ordinal = htonl(TPM_ORD_UNSEAL);
60347f9c279SSumit Garg 	ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE);
60447f9c279SSumit Garg 	if (ret != TPM_NONCE_SIZE) {
60547f9c279SSumit Garg 		pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
60647f9c279SSumit Garg 		return ret;
60747f9c279SSumit Garg 	}
60847f9c279SSumit Garg 	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
60947f9c279SSumit Garg 			   enonce1, nonceodd, cont, sizeof(uint32_t),
61047f9c279SSumit Garg 			   &ordinal, bloblen, blob, 0, 0);
61147f9c279SSumit Garg 	if (ret < 0)
61247f9c279SSumit Garg 		return ret;
61347f9c279SSumit Garg 	ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE,
61447f9c279SSumit Garg 			   enonce2, nonceodd, cont, sizeof(uint32_t),
61547f9c279SSumit Garg 			   &ordinal, bloblen, blob, 0, 0);
61647f9c279SSumit Garg 	if (ret < 0)
61747f9c279SSumit Garg 		return ret;
61847f9c279SSumit Garg 
61947f9c279SSumit Garg 	/* build and send TPM request packet */
62047f9c279SSumit Garg 	tpm_buf_reset(tb, TPM_TAG_RQU_AUTH2_COMMAND, TPM_ORD_UNSEAL);
62147f9c279SSumit Garg 	tpm_buf_append_u32(tb, keyhandle);
62247f9c279SSumit Garg 	tpm_buf_append(tb, blob, bloblen);
62347f9c279SSumit Garg 	tpm_buf_append_u32(tb, authhandle1);
62447f9c279SSumit Garg 	tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);
62547f9c279SSumit Garg 	tpm_buf_append_u8(tb, cont);
62647f9c279SSumit Garg 	tpm_buf_append(tb, authdata1, SHA1_DIGEST_SIZE);
62747f9c279SSumit Garg 	tpm_buf_append_u32(tb, authhandle2);
62847f9c279SSumit Garg 	tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);
62947f9c279SSumit Garg 	tpm_buf_append_u8(tb, cont);
63047f9c279SSumit Garg 	tpm_buf_append(tb, authdata2, SHA1_DIGEST_SIZE);
63147f9c279SSumit Garg 
63247f9c279SSumit Garg 	ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
63347f9c279SSumit Garg 	if (ret < 0) {
63447f9c279SSumit Garg 		pr_info("trusted_key: authhmac failed (%d)\n", ret);
63547f9c279SSumit Garg 		return ret;
63647f9c279SSumit Garg 	}
63747f9c279SSumit Garg 
63847f9c279SSumit Garg 	*datalen = LOAD32(tb->data, TPM_DATA_OFFSET);
63947f9c279SSumit Garg 	ret = TSS_checkhmac2(tb->data, ordinal, nonceodd,
64047f9c279SSumit Garg 			     keyauth, SHA1_DIGEST_SIZE,
64147f9c279SSumit Garg 			     blobauth, SHA1_DIGEST_SIZE,
64247f9c279SSumit Garg 			     sizeof(uint32_t), TPM_DATA_OFFSET,
64347f9c279SSumit Garg 			     *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0,
64447f9c279SSumit Garg 			     0);
64547f9c279SSumit Garg 	if (ret < 0) {
64647f9c279SSumit Garg 		pr_info("trusted_key: TSS_checkhmac2 failed (%d)\n", ret);
64747f9c279SSumit Garg 		return ret;
64847f9c279SSumit Garg 	}
64947f9c279SSumit Garg 	memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen);
65047f9c279SSumit Garg 	return 0;
65147f9c279SSumit Garg }
65247f9c279SSumit Garg 
65347f9c279SSumit Garg /*
65447f9c279SSumit Garg  * Have the TPM seal(encrypt) the symmetric key
65547f9c279SSumit Garg  */
65647f9c279SSumit Garg static int key_seal(struct trusted_key_payload *p,
65747f9c279SSumit Garg 		    struct trusted_key_options *o)
65847f9c279SSumit Garg {
65947f9c279SSumit Garg 	struct tpm_buf tb;
66047f9c279SSumit Garg 	int ret;
66147f9c279SSumit Garg 
66247f9c279SSumit Garg 	ret = tpm_buf_init(&tb, 0, 0);
66347f9c279SSumit Garg 	if (ret)
66447f9c279SSumit Garg 		return ret;
66547f9c279SSumit Garg 
66647f9c279SSumit Garg 	/* include migratable flag at end of sealed key */
66747f9c279SSumit Garg 	p->key[p->key_len] = p->migratable;
66847f9c279SSumit Garg 
66947f9c279SSumit Garg 	ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth,
67047f9c279SSumit Garg 		       p->key, p->key_len + 1, p->blob, &p->blob_len,
67147f9c279SSumit Garg 		       o->blobauth, o->pcrinfo, o->pcrinfo_len);
67247f9c279SSumit Garg 	if (ret < 0)
67347f9c279SSumit Garg 		pr_info("trusted_key: srkseal failed (%d)\n", ret);
67447f9c279SSumit Garg 
67547f9c279SSumit Garg 	tpm_buf_destroy(&tb);
67647f9c279SSumit Garg 	return ret;
67747f9c279SSumit Garg }
67847f9c279SSumit Garg 
67947f9c279SSumit Garg /*
68047f9c279SSumit Garg  * Have the TPM unseal(decrypt) the symmetric key
68147f9c279SSumit Garg  */
68247f9c279SSumit Garg static int key_unseal(struct trusted_key_payload *p,
68347f9c279SSumit Garg 		      struct trusted_key_options *o)
68447f9c279SSumit Garg {
68547f9c279SSumit Garg 	struct tpm_buf tb;
68647f9c279SSumit Garg 	int ret;
68747f9c279SSumit Garg 
68847f9c279SSumit Garg 	ret = tpm_buf_init(&tb, 0, 0);
68947f9c279SSumit Garg 	if (ret)
69047f9c279SSumit Garg 		return ret;
69147f9c279SSumit Garg 
69247f9c279SSumit Garg 	ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,
69347f9c279SSumit Garg 			 o->blobauth, p->key, &p->key_len);
69447f9c279SSumit Garg 	if (ret < 0)
69547f9c279SSumit Garg 		pr_info("trusted_key: srkunseal failed (%d)\n", ret);
69647f9c279SSumit Garg 	else
69747f9c279SSumit Garg 		/* pull migratable flag out of sealed key */
69847f9c279SSumit Garg 		p->migratable = p->key[--p->key_len];
69947f9c279SSumit Garg 
70047f9c279SSumit Garg 	tpm_buf_destroy(&tb);
70147f9c279SSumit Garg 	return ret;
70247f9c279SSumit Garg }
70347f9c279SSumit Garg 
70447f9c279SSumit Garg enum {
70547f9c279SSumit Garg 	Opt_err,
70647f9c279SSumit Garg 	Opt_new, Opt_load, Opt_update,
70747f9c279SSumit Garg 	Opt_keyhandle, Opt_keyauth, Opt_blobauth,
70847f9c279SSumit Garg 	Opt_pcrinfo, Opt_pcrlock, Opt_migratable,
70947f9c279SSumit Garg 	Opt_hash,
71047f9c279SSumit Garg 	Opt_policydigest,
71147f9c279SSumit Garg 	Opt_policyhandle,
71247f9c279SSumit Garg };
71347f9c279SSumit Garg 
71447f9c279SSumit Garg static const match_table_t key_tokens = {
71547f9c279SSumit Garg 	{Opt_new, "new"},
71647f9c279SSumit Garg 	{Opt_load, "load"},
71747f9c279SSumit Garg 	{Opt_update, "update"},
71847f9c279SSumit Garg 	{Opt_keyhandle, "keyhandle=%s"},
71947f9c279SSumit Garg 	{Opt_keyauth, "keyauth=%s"},
72047f9c279SSumit Garg 	{Opt_blobauth, "blobauth=%s"},
72147f9c279SSumit Garg 	{Opt_pcrinfo, "pcrinfo=%s"},
72247f9c279SSumit Garg 	{Opt_pcrlock, "pcrlock=%s"},
72347f9c279SSumit Garg 	{Opt_migratable, "migratable=%s"},
72447f9c279SSumit Garg 	{Opt_hash, "hash=%s"},
72547f9c279SSumit Garg 	{Opt_policydigest, "policydigest=%s"},
72647f9c279SSumit Garg 	{Opt_policyhandle, "policyhandle=%s"},
72747f9c279SSumit Garg 	{Opt_err, NULL}
72847f9c279SSumit Garg };
72947f9c279SSumit Garg 
73047f9c279SSumit Garg /* can have zero or more token= options */
73147f9c279SSumit Garg static int getoptions(char *c, struct trusted_key_payload *pay,
73247f9c279SSumit Garg 		      struct trusted_key_options *opt)
73347f9c279SSumit Garg {
73447f9c279SSumit Garg 	substring_t args[MAX_OPT_ARGS];
73547f9c279SSumit Garg 	char *p = c;
73647f9c279SSumit Garg 	int token;
73747f9c279SSumit Garg 	int res;
73847f9c279SSumit Garg 	unsigned long handle;
73947f9c279SSumit Garg 	unsigned long lock;
74047f9c279SSumit Garg 	unsigned long token_mask = 0;
74147f9c279SSumit Garg 	unsigned int digest_len;
74247f9c279SSumit Garg 	int i;
74347f9c279SSumit Garg 	int tpm2;
74447f9c279SSumit Garg 
74547f9c279SSumit Garg 	tpm2 = tpm_is_tpm2(chip);
74647f9c279SSumit Garg 	if (tpm2 < 0)
74747f9c279SSumit Garg 		return tpm2;
74847f9c279SSumit Garg 
74947f9c279SSumit Garg 	opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
75047f9c279SSumit Garg 
75147f9c279SSumit Garg 	while ((p = strsep(&c, " \t"))) {
75247f9c279SSumit Garg 		if (*p == '\0' || *p == ' ' || *p == '\t')
75347f9c279SSumit Garg 			continue;
75447f9c279SSumit Garg 		token = match_token(p, key_tokens, args);
75547f9c279SSumit Garg 		if (test_and_set_bit(token, &token_mask))
75647f9c279SSumit Garg 			return -EINVAL;
75747f9c279SSumit Garg 
75847f9c279SSumit Garg 		switch (token) {
75947f9c279SSumit Garg 		case Opt_pcrinfo:
76047f9c279SSumit Garg 			opt->pcrinfo_len = strlen(args[0].from) / 2;
76147f9c279SSumit Garg 			if (opt->pcrinfo_len > MAX_PCRINFO_SIZE)
76247f9c279SSumit Garg 				return -EINVAL;
76347f9c279SSumit Garg 			res = hex2bin(opt->pcrinfo, args[0].from,
76447f9c279SSumit Garg 				      opt->pcrinfo_len);
76547f9c279SSumit Garg 			if (res < 0)
76647f9c279SSumit Garg 				return -EINVAL;
76747f9c279SSumit Garg 			break;
76847f9c279SSumit Garg 		case Opt_keyhandle:
76947f9c279SSumit Garg 			res = kstrtoul(args[0].from, 16, &handle);
77047f9c279SSumit Garg 			if (res < 0)
77147f9c279SSumit Garg 				return -EINVAL;
77247f9c279SSumit Garg 			opt->keytype = SEAL_keytype;
77347f9c279SSumit Garg 			opt->keyhandle = handle;
77447f9c279SSumit Garg 			break;
77547f9c279SSumit Garg 		case Opt_keyauth:
77647f9c279SSumit Garg 			if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE)
77747f9c279SSumit Garg 				return -EINVAL;
77847f9c279SSumit Garg 			res = hex2bin(opt->keyauth, args[0].from,
77947f9c279SSumit Garg 				      SHA1_DIGEST_SIZE);
78047f9c279SSumit Garg 			if (res < 0)
78147f9c279SSumit Garg 				return -EINVAL;
78247f9c279SSumit Garg 			break;
78347f9c279SSumit Garg 		case Opt_blobauth:
78447f9c279SSumit Garg 			if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE)
78547f9c279SSumit Garg 				return -EINVAL;
78647f9c279SSumit Garg 			res = hex2bin(opt->blobauth, args[0].from,
78747f9c279SSumit Garg 				      SHA1_DIGEST_SIZE);
78847f9c279SSumit Garg 			if (res < 0)
78947f9c279SSumit Garg 				return -EINVAL;
79047f9c279SSumit Garg 			break;
79147f9c279SSumit Garg 		case Opt_migratable:
79247f9c279SSumit Garg 			if (*args[0].from == '0')
79347f9c279SSumit Garg 				pay->migratable = 0;
79447f9c279SSumit Garg 			else
79547f9c279SSumit Garg 				return -EINVAL;
79647f9c279SSumit Garg 			break;
79747f9c279SSumit Garg 		case Opt_pcrlock:
79847f9c279SSumit Garg 			res = kstrtoul(args[0].from, 10, &lock);
79947f9c279SSumit Garg 			if (res < 0)
80047f9c279SSumit Garg 				return -EINVAL;
80147f9c279SSumit Garg 			opt->pcrlock = lock;
80247f9c279SSumit Garg 			break;
80347f9c279SSumit Garg 		case Opt_hash:
80447f9c279SSumit Garg 			if (test_bit(Opt_policydigest, &token_mask))
80547f9c279SSumit Garg 				return -EINVAL;
80647f9c279SSumit Garg 			for (i = 0; i < HASH_ALGO__LAST; i++) {
80747f9c279SSumit Garg 				if (!strcmp(args[0].from, hash_algo_name[i])) {
80847f9c279SSumit Garg 					opt->hash = i;
80947f9c279SSumit Garg 					break;
81047f9c279SSumit Garg 				}
81147f9c279SSumit Garg 			}
81247f9c279SSumit Garg 			if (i == HASH_ALGO__LAST)
81347f9c279SSumit Garg 				return -EINVAL;
81447f9c279SSumit Garg 			if  (!tpm2 && i != HASH_ALGO_SHA1) {
81547f9c279SSumit Garg 				pr_info("trusted_key: TPM 1.x only supports SHA-1.\n");
81647f9c279SSumit Garg 				return -EINVAL;
81747f9c279SSumit Garg 			}
81847f9c279SSumit Garg 			break;
81947f9c279SSumit Garg 		case Opt_policydigest:
82047f9c279SSumit Garg 			digest_len = hash_digest_size[opt->hash];
82147f9c279SSumit Garg 			if (!tpm2 || strlen(args[0].from) != (2 * digest_len))
82247f9c279SSumit Garg 				return -EINVAL;
82347f9c279SSumit Garg 			res = hex2bin(opt->policydigest, args[0].from,
82447f9c279SSumit Garg 				      digest_len);
82547f9c279SSumit Garg 			if (res < 0)
82647f9c279SSumit Garg 				return -EINVAL;
82747f9c279SSumit Garg 			opt->policydigest_len = digest_len;
82847f9c279SSumit Garg 			break;
82947f9c279SSumit Garg 		case Opt_policyhandle:
83047f9c279SSumit Garg 			if (!tpm2)
83147f9c279SSumit Garg 				return -EINVAL;
83247f9c279SSumit Garg 			res = kstrtoul(args[0].from, 16, &handle);
83347f9c279SSumit Garg 			if (res < 0)
83447f9c279SSumit Garg 				return -EINVAL;
83547f9c279SSumit Garg 			opt->policyhandle = handle;
83647f9c279SSumit Garg 			break;
83747f9c279SSumit Garg 		default:
83847f9c279SSumit Garg 			return -EINVAL;
83947f9c279SSumit Garg 		}
84047f9c279SSumit Garg 	}
84147f9c279SSumit Garg 	return 0;
84247f9c279SSumit Garg }
84347f9c279SSumit Garg 
84447f9c279SSumit Garg /*
84547f9c279SSumit Garg  * datablob_parse - parse the keyctl data and fill in the
84647f9c279SSumit Garg  * 		    payload and options structures
84747f9c279SSumit Garg  *
84847f9c279SSumit Garg  * On success returns 0, otherwise -EINVAL.
84947f9c279SSumit Garg  */
85047f9c279SSumit Garg static int datablob_parse(char *datablob, struct trusted_key_payload *p,
85147f9c279SSumit Garg 			  struct trusted_key_options *o)
85247f9c279SSumit Garg {
85347f9c279SSumit Garg 	substring_t args[MAX_OPT_ARGS];
85447f9c279SSumit Garg 	long keylen;
85547f9c279SSumit Garg 	int ret = -EINVAL;
85647f9c279SSumit Garg 	int key_cmd;
85747f9c279SSumit Garg 	char *c;
85847f9c279SSumit Garg 
85947f9c279SSumit Garg 	/* main command */
86047f9c279SSumit Garg 	c = strsep(&datablob, " \t");
86147f9c279SSumit Garg 	if (!c)
86247f9c279SSumit Garg 		return -EINVAL;
86347f9c279SSumit Garg 	key_cmd = match_token(c, key_tokens, args);
86447f9c279SSumit Garg 	switch (key_cmd) {
86547f9c279SSumit Garg 	case Opt_new:
86647f9c279SSumit Garg 		/* first argument is key size */
86747f9c279SSumit Garg 		c = strsep(&datablob, " \t");
86847f9c279SSumit Garg 		if (!c)
86947f9c279SSumit Garg 			return -EINVAL;
87047f9c279SSumit Garg 		ret = kstrtol(c, 10, &keylen);
87147f9c279SSumit Garg 		if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE)
87247f9c279SSumit Garg 			return -EINVAL;
87347f9c279SSumit Garg 		p->key_len = keylen;
87447f9c279SSumit Garg 		ret = getoptions(datablob, p, o);
87547f9c279SSumit Garg 		if (ret < 0)
87647f9c279SSumit Garg 			return ret;
87747f9c279SSumit Garg 		ret = Opt_new;
87847f9c279SSumit Garg 		break;
87947f9c279SSumit Garg 	case Opt_load:
88047f9c279SSumit Garg 		/* first argument is sealed blob */
88147f9c279SSumit Garg 		c = strsep(&datablob, " \t");
88247f9c279SSumit Garg 		if (!c)
88347f9c279SSumit Garg 			return -EINVAL;
88447f9c279SSumit Garg 		p->blob_len = strlen(c) / 2;
88547f9c279SSumit Garg 		if (p->blob_len > MAX_BLOB_SIZE)
88647f9c279SSumit Garg 			return -EINVAL;
88747f9c279SSumit Garg 		ret = hex2bin(p->blob, c, p->blob_len);
88847f9c279SSumit Garg 		if (ret < 0)
88947f9c279SSumit Garg 			return -EINVAL;
89047f9c279SSumit Garg 		ret = getoptions(datablob, p, o);
89147f9c279SSumit Garg 		if (ret < 0)
89247f9c279SSumit Garg 			return ret;
89347f9c279SSumit Garg 		ret = Opt_load;
89447f9c279SSumit Garg 		break;
89547f9c279SSumit Garg 	case Opt_update:
89647f9c279SSumit Garg 		/* all arguments are options */
89747f9c279SSumit Garg 		ret = getoptions(datablob, p, o);
89847f9c279SSumit Garg 		if (ret < 0)
89947f9c279SSumit Garg 			return ret;
90047f9c279SSumit Garg 		ret = Opt_update;
90147f9c279SSumit Garg 		break;
90247f9c279SSumit Garg 	case Opt_err:
90347f9c279SSumit Garg 		return -EINVAL;
90447f9c279SSumit Garg 		break;
90547f9c279SSumit Garg 	}
90647f9c279SSumit Garg 	return ret;
90747f9c279SSumit Garg }
90847f9c279SSumit Garg 
90947f9c279SSumit Garg static struct trusted_key_options *trusted_options_alloc(void)
91047f9c279SSumit Garg {
91147f9c279SSumit Garg 	struct trusted_key_options *options;
91247f9c279SSumit Garg 	int tpm2;
91347f9c279SSumit Garg 
91447f9c279SSumit Garg 	tpm2 = tpm_is_tpm2(chip);
91547f9c279SSumit Garg 	if (tpm2 < 0)
91647f9c279SSumit Garg 		return NULL;
91747f9c279SSumit Garg 
91847f9c279SSumit Garg 	options = kzalloc(sizeof *options, GFP_KERNEL);
91947f9c279SSumit Garg 	if (options) {
92047f9c279SSumit Garg 		/* set any non-zero defaults */
92147f9c279SSumit Garg 		options->keytype = SRK_keytype;
92247f9c279SSumit Garg 
92347f9c279SSumit Garg 		if (!tpm2)
92447f9c279SSumit Garg 			options->keyhandle = SRKHANDLE;
92547f9c279SSumit Garg 	}
92647f9c279SSumit Garg 	return options;
92747f9c279SSumit Garg }
92847f9c279SSumit Garg 
92947f9c279SSumit Garg static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
93047f9c279SSumit Garg {
93147f9c279SSumit Garg 	struct trusted_key_payload *p = NULL;
93247f9c279SSumit Garg 	int ret;
93347f9c279SSumit Garg 
93447f9c279SSumit Garg 	ret = key_payload_reserve(key, sizeof *p);
93547f9c279SSumit Garg 	if (ret < 0)
93647f9c279SSumit Garg 		return p;
93747f9c279SSumit Garg 	p = kzalloc(sizeof *p, GFP_KERNEL);
93847f9c279SSumit Garg 	if (p)
93947f9c279SSumit Garg 		p->migratable = 1; /* migratable by default */
94047f9c279SSumit Garg 	return p;
94147f9c279SSumit Garg }
94247f9c279SSumit Garg 
94347f9c279SSumit Garg /*
94447f9c279SSumit Garg  * trusted_instantiate - create a new trusted key
94547f9c279SSumit Garg  *
94647f9c279SSumit Garg  * Unseal an existing trusted blob or, for a new key, get a
94747f9c279SSumit Garg  * random key, then seal and create a trusted key-type key,
94847f9c279SSumit Garg  * adding it to the specified keyring.
94947f9c279SSumit Garg  *
95047f9c279SSumit Garg  * On success, return 0. Otherwise return errno.
95147f9c279SSumit Garg  */
95247f9c279SSumit Garg static int trusted_instantiate(struct key *key,
95347f9c279SSumit Garg 			       struct key_preparsed_payload *prep)
95447f9c279SSumit Garg {
95547f9c279SSumit Garg 	struct trusted_key_payload *payload = NULL;
95647f9c279SSumit Garg 	struct trusted_key_options *options = NULL;
95747f9c279SSumit Garg 	size_t datalen = prep->datalen;
95847f9c279SSumit Garg 	char *datablob;
95947f9c279SSumit Garg 	int ret = 0;
96047f9c279SSumit Garg 	int key_cmd;
96147f9c279SSumit Garg 	size_t key_len;
96247f9c279SSumit Garg 	int tpm2;
96347f9c279SSumit Garg 
96447f9c279SSumit Garg 	tpm2 = tpm_is_tpm2(chip);
96547f9c279SSumit Garg 	if (tpm2 < 0)
96647f9c279SSumit Garg 		return tpm2;
96747f9c279SSumit Garg 
96847f9c279SSumit Garg 	if (datalen <= 0 || datalen > 32767 || !prep->data)
96947f9c279SSumit Garg 		return -EINVAL;
97047f9c279SSumit Garg 
97147f9c279SSumit Garg 	datablob = kmalloc(datalen + 1, GFP_KERNEL);
97247f9c279SSumit Garg 	if (!datablob)
97347f9c279SSumit Garg 		return -ENOMEM;
97447f9c279SSumit Garg 	memcpy(datablob, prep->data, datalen);
97547f9c279SSumit Garg 	datablob[datalen] = '\0';
97647f9c279SSumit Garg 
97747f9c279SSumit Garg 	options = trusted_options_alloc();
97847f9c279SSumit Garg 	if (!options) {
97947f9c279SSumit Garg 		ret = -ENOMEM;
98047f9c279SSumit Garg 		goto out;
98147f9c279SSumit Garg 	}
98247f9c279SSumit Garg 	payload = trusted_payload_alloc(key);
98347f9c279SSumit Garg 	if (!payload) {
98447f9c279SSumit Garg 		ret = -ENOMEM;
98547f9c279SSumit Garg 		goto out;
98647f9c279SSumit Garg 	}
98747f9c279SSumit Garg 
98847f9c279SSumit Garg 	key_cmd = datablob_parse(datablob, payload, options);
98947f9c279SSumit Garg 	if (key_cmd < 0) {
99047f9c279SSumit Garg 		ret = key_cmd;
99147f9c279SSumit Garg 		goto out;
99247f9c279SSumit Garg 	}
99347f9c279SSumit Garg 
99447f9c279SSumit Garg 	if (!options->keyhandle) {
99547f9c279SSumit Garg 		ret = -EINVAL;
99647f9c279SSumit Garg 		goto out;
99747f9c279SSumit Garg 	}
99847f9c279SSumit Garg 
99947f9c279SSumit Garg 	dump_payload(payload);
100047f9c279SSumit Garg 	dump_options(options);
100147f9c279SSumit Garg 
100247f9c279SSumit Garg 	switch (key_cmd) {
100347f9c279SSumit Garg 	case Opt_load:
100447f9c279SSumit Garg 		if (tpm2)
10052e19e101SSumit Garg 			ret = tpm2_unseal_trusted(chip, payload, options);
100647f9c279SSumit Garg 		else
100747f9c279SSumit Garg 			ret = key_unseal(payload, options);
100847f9c279SSumit Garg 		dump_payload(payload);
100947f9c279SSumit Garg 		dump_options(options);
101047f9c279SSumit Garg 		if (ret < 0)
101147f9c279SSumit Garg 			pr_info("trusted_key: key_unseal failed (%d)\n", ret);
101247f9c279SSumit Garg 		break;
101347f9c279SSumit Garg 	case Opt_new:
101447f9c279SSumit Garg 		key_len = payload->key_len;
101547f9c279SSumit Garg 		ret = tpm_get_random(chip, payload->key, key_len);
101647f9c279SSumit Garg 		if (ret != key_len) {
101747f9c279SSumit Garg 			pr_info("trusted_key: key_create failed (%d)\n", ret);
101847f9c279SSumit Garg 			goto out;
101947f9c279SSumit Garg 		}
102047f9c279SSumit Garg 		if (tpm2)
10212e19e101SSumit Garg 			ret = tpm2_seal_trusted(chip, payload, options);
102247f9c279SSumit Garg 		else
102347f9c279SSumit Garg 			ret = key_seal(payload, options);
102447f9c279SSumit Garg 		if (ret < 0)
102547f9c279SSumit Garg 			pr_info("trusted_key: key_seal failed (%d)\n", ret);
102647f9c279SSumit Garg 		break;
102747f9c279SSumit Garg 	default:
102847f9c279SSumit Garg 		ret = -EINVAL;
102947f9c279SSumit Garg 		goto out;
103047f9c279SSumit Garg 	}
103147f9c279SSumit Garg 	if (!ret && options->pcrlock)
103247f9c279SSumit Garg 		ret = pcrlock(options->pcrlock);
103347f9c279SSumit Garg out:
1034453431a5SWaiman Long 	kfree_sensitive(datablob);
1035453431a5SWaiman Long 	kfree_sensitive(options);
103647f9c279SSumit Garg 	if (!ret)
103747f9c279SSumit Garg 		rcu_assign_keypointer(key, payload);
103847f9c279SSumit Garg 	else
1039453431a5SWaiman Long 		kfree_sensitive(payload);
104047f9c279SSumit Garg 	return ret;
104147f9c279SSumit Garg }
104247f9c279SSumit Garg 
104347f9c279SSumit Garg static void trusted_rcu_free(struct rcu_head *rcu)
104447f9c279SSumit Garg {
104547f9c279SSumit Garg 	struct trusted_key_payload *p;
104647f9c279SSumit Garg 
104747f9c279SSumit Garg 	p = container_of(rcu, struct trusted_key_payload, rcu);
1048453431a5SWaiman Long 	kfree_sensitive(p);
104947f9c279SSumit Garg }
105047f9c279SSumit Garg 
105147f9c279SSumit Garg /*
105247f9c279SSumit Garg  * trusted_update - reseal an existing key with new PCR values
105347f9c279SSumit Garg  */
105447f9c279SSumit Garg static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
105547f9c279SSumit Garg {
105647f9c279SSumit Garg 	struct trusted_key_payload *p;
105747f9c279SSumit Garg 	struct trusted_key_payload *new_p;
105847f9c279SSumit Garg 	struct trusted_key_options *new_o;
105947f9c279SSumit Garg 	size_t datalen = prep->datalen;
106047f9c279SSumit Garg 	char *datablob;
106147f9c279SSumit Garg 	int ret = 0;
106247f9c279SSumit Garg 
106347f9c279SSumit Garg 	if (key_is_negative(key))
106447f9c279SSumit Garg 		return -ENOKEY;
106547f9c279SSumit Garg 	p = key->payload.data[0];
106647f9c279SSumit Garg 	if (!p->migratable)
106747f9c279SSumit Garg 		return -EPERM;
106847f9c279SSumit Garg 	if (datalen <= 0 || datalen > 32767 || !prep->data)
106947f9c279SSumit Garg 		return -EINVAL;
107047f9c279SSumit Garg 
107147f9c279SSumit Garg 	datablob = kmalloc(datalen + 1, GFP_KERNEL);
107247f9c279SSumit Garg 	if (!datablob)
107347f9c279SSumit Garg 		return -ENOMEM;
107447f9c279SSumit Garg 	new_o = trusted_options_alloc();
107547f9c279SSumit Garg 	if (!new_o) {
107647f9c279SSumit Garg 		ret = -ENOMEM;
107747f9c279SSumit Garg 		goto out;
107847f9c279SSumit Garg 	}
107947f9c279SSumit Garg 	new_p = trusted_payload_alloc(key);
108047f9c279SSumit Garg 	if (!new_p) {
108147f9c279SSumit Garg 		ret = -ENOMEM;
108247f9c279SSumit Garg 		goto out;
108347f9c279SSumit Garg 	}
108447f9c279SSumit Garg 
108547f9c279SSumit Garg 	memcpy(datablob, prep->data, datalen);
108647f9c279SSumit Garg 	datablob[datalen] = '\0';
108747f9c279SSumit Garg 	ret = datablob_parse(datablob, new_p, new_o);
108847f9c279SSumit Garg 	if (ret != Opt_update) {
108947f9c279SSumit Garg 		ret = -EINVAL;
1090453431a5SWaiman Long 		kfree_sensitive(new_p);
109147f9c279SSumit Garg 		goto out;
109247f9c279SSumit Garg 	}
109347f9c279SSumit Garg 
109447f9c279SSumit Garg 	if (!new_o->keyhandle) {
109547f9c279SSumit Garg 		ret = -EINVAL;
1096453431a5SWaiman Long 		kfree_sensitive(new_p);
109747f9c279SSumit Garg 		goto out;
109847f9c279SSumit Garg 	}
109947f9c279SSumit Garg 
110047f9c279SSumit Garg 	/* copy old key values, and reseal with new pcrs */
110147f9c279SSumit Garg 	new_p->migratable = p->migratable;
110247f9c279SSumit Garg 	new_p->key_len = p->key_len;
110347f9c279SSumit Garg 	memcpy(new_p->key, p->key, p->key_len);
110447f9c279SSumit Garg 	dump_payload(p);
110547f9c279SSumit Garg 	dump_payload(new_p);
110647f9c279SSumit Garg 
110747f9c279SSumit Garg 	ret = key_seal(new_p, new_o);
110847f9c279SSumit Garg 	if (ret < 0) {
110947f9c279SSumit Garg 		pr_info("trusted_key: key_seal failed (%d)\n", ret);
1110453431a5SWaiman Long 		kfree_sensitive(new_p);
111147f9c279SSumit Garg 		goto out;
111247f9c279SSumit Garg 	}
111347f9c279SSumit Garg 	if (new_o->pcrlock) {
111447f9c279SSumit Garg 		ret = pcrlock(new_o->pcrlock);
111547f9c279SSumit Garg 		if (ret < 0) {
111647f9c279SSumit Garg 			pr_info("trusted_key: pcrlock failed (%d)\n", ret);
1117453431a5SWaiman Long 			kfree_sensitive(new_p);
111847f9c279SSumit Garg 			goto out;
111947f9c279SSumit Garg 		}
112047f9c279SSumit Garg 	}
112147f9c279SSumit Garg 	rcu_assign_keypointer(key, new_p);
112247f9c279SSumit Garg 	call_rcu(&p->rcu, trusted_rcu_free);
112347f9c279SSumit Garg out:
1124453431a5SWaiman Long 	kfree_sensitive(datablob);
1125453431a5SWaiman Long 	kfree_sensitive(new_o);
112647f9c279SSumit Garg 	return ret;
112747f9c279SSumit Garg }
112847f9c279SSumit Garg 
112947f9c279SSumit Garg /*
113047f9c279SSumit Garg  * trusted_read - copy the sealed blob data to userspace in hex.
113147f9c279SSumit Garg  * On success, return to userspace the trusted key datablob size.
113247f9c279SSumit Garg  */
1133d3ec10aaSWaiman Long static long trusted_read(const struct key *key, char *buffer,
113447f9c279SSumit Garg 			 size_t buflen)
113547f9c279SSumit Garg {
113647f9c279SSumit Garg 	const struct trusted_key_payload *p;
113747f9c279SSumit Garg 	char *bufp;
113847f9c279SSumit Garg 	int i;
113947f9c279SSumit Garg 
114047f9c279SSumit Garg 	p = dereference_key_locked(key);
114147f9c279SSumit Garg 	if (!p)
114247f9c279SSumit Garg 		return -EINVAL;
114347f9c279SSumit Garg 
114447f9c279SSumit Garg 	if (buffer && buflen >= 2 * p->blob_len) {
1145d3ec10aaSWaiman Long 		bufp = buffer;
114647f9c279SSumit Garg 		for (i = 0; i < p->blob_len; i++)
114747f9c279SSumit Garg 			bufp = hex_byte_pack(bufp, p->blob[i]);
114847f9c279SSumit Garg 	}
114947f9c279SSumit Garg 	return 2 * p->blob_len;
115047f9c279SSumit Garg }
115147f9c279SSumit Garg 
115247f9c279SSumit Garg /*
115347f9c279SSumit Garg  * trusted_destroy - clear and free the key's payload
115447f9c279SSumit Garg  */
115547f9c279SSumit Garg static void trusted_destroy(struct key *key)
115647f9c279SSumit Garg {
1157453431a5SWaiman Long 	kfree_sensitive(key->payload.data[0]);
115847f9c279SSumit Garg }
115947f9c279SSumit Garg 
116047f9c279SSumit Garg struct key_type key_type_trusted = {
116147f9c279SSumit Garg 	.name = "trusted",
116247f9c279SSumit Garg 	.instantiate = trusted_instantiate,
116347f9c279SSumit Garg 	.update = trusted_update,
116447f9c279SSumit Garg 	.destroy = trusted_destroy,
116547f9c279SSumit Garg 	.describe = user_describe,
116647f9c279SSumit Garg 	.read = trusted_read,
116747f9c279SSumit Garg };
116847f9c279SSumit Garg 
116947f9c279SSumit Garg EXPORT_SYMBOL_GPL(key_type_trusted);
117047f9c279SSumit Garg 
117147f9c279SSumit Garg static void trusted_shash_release(void)
117247f9c279SSumit Garg {
117347f9c279SSumit Garg 	if (hashalg)
117447f9c279SSumit Garg 		crypto_free_shash(hashalg);
117547f9c279SSumit Garg 	if (hmacalg)
117647f9c279SSumit Garg 		crypto_free_shash(hmacalg);
117747f9c279SSumit Garg }
117847f9c279SSumit Garg 
117947f9c279SSumit Garg static int __init trusted_shash_alloc(void)
118047f9c279SSumit Garg {
118147f9c279SSumit Garg 	int ret;
118247f9c279SSumit Garg 
118347f9c279SSumit Garg 	hmacalg = crypto_alloc_shash(hmac_alg, 0, 0);
118447f9c279SSumit Garg 	if (IS_ERR(hmacalg)) {
118547f9c279SSumit Garg 		pr_info("trusted_key: could not allocate crypto %s\n",
118647f9c279SSumit Garg 			hmac_alg);
118747f9c279SSumit Garg 		return PTR_ERR(hmacalg);
118847f9c279SSumit Garg 	}
118947f9c279SSumit Garg 
119047f9c279SSumit Garg 	hashalg = crypto_alloc_shash(hash_alg, 0, 0);
119147f9c279SSumit Garg 	if (IS_ERR(hashalg)) {
119247f9c279SSumit Garg 		pr_info("trusted_key: could not allocate crypto %s\n",
119347f9c279SSumit Garg 			hash_alg);
119447f9c279SSumit Garg 		ret = PTR_ERR(hashalg);
119547f9c279SSumit Garg 		goto hashalg_fail;
119647f9c279SSumit Garg 	}
119747f9c279SSumit Garg 
119847f9c279SSumit Garg 	return 0;
119947f9c279SSumit Garg 
120047f9c279SSumit Garg hashalg_fail:
120147f9c279SSumit Garg 	crypto_free_shash(hmacalg);
120247f9c279SSumit Garg 	return ret;
120347f9c279SSumit Garg }
120447f9c279SSumit Garg 
120547f9c279SSumit Garg static int __init init_digests(void)
120647f9c279SSumit Garg {
120747f9c279SSumit Garg 	int i;
120847f9c279SSumit Garg 
120947f9c279SSumit Garg 	digests = kcalloc(chip->nr_allocated_banks, sizeof(*digests),
121047f9c279SSumit Garg 			  GFP_KERNEL);
121147f9c279SSumit Garg 	if (!digests)
121247f9c279SSumit Garg 		return -ENOMEM;
121347f9c279SSumit Garg 
121447f9c279SSumit Garg 	for (i = 0; i < chip->nr_allocated_banks; i++)
121547f9c279SSumit Garg 		digests[i].alg_id = chip->allocated_banks[i].alg_id;
121647f9c279SSumit Garg 
121747f9c279SSumit Garg 	return 0;
121847f9c279SSumit Garg }
121947f9c279SSumit Garg 
122047f9c279SSumit Garg static int __init init_trusted(void)
122147f9c279SSumit Garg {
122247f9c279SSumit Garg 	int ret;
122347f9c279SSumit Garg 
122447f9c279SSumit Garg 	/* encrypted_keys.ko depends on successful load of this module even if
122547f9c279SSumit Garg 	 * TPM is not used.
122647f9c279SSumit Garg 	 */
122747f9c279SSumit Garg 	chip = tpm_default_chip();
122847f9c279SSumit Garg 	if (!chip)
122947f9c279SSumit Garg 		return 0;
123047f9c279SSumit Garg 
123147f9c279SSumit Garg 	ret = init_digests();
123247f9c279SSumit Garg 	if (ret < 0)
123347f9c279SSumit Garg 		goto err_put;
123447f9c279SSumit Garg 	ret = trusted_shash_alloc();
123547f9c279SSumit Garg 	if (ret < 0)
123647f9c279SSumit Garg 		goto err_free;
123747f9c279SSumit Garg 	ret = register_key_type(&key_type_trusted);
123847f9c279SSumit Garg 	if (ret < 0)
123947f9c279SSumit Garg 		goto err_release;
124047f9c279SSumit Garg 	return 0;
124147f9c279SSumit Garg err_release:
124247f9c279SSumit Garg 	trusted_shash_release();
124347f9c279SSumit Garg err_free:
124447f9c279SSumit Garg 	kfree(digests);
124547f9c279SSumit Garg err_put:
124647f9c279SSumit Garg 	put_device(&chip->dev);
124747f9c279SSumit Garg 	return ret;
124847f9c279SSumit Garg }
124947f9c279SSumit Garg 
125047f9c279SSumit Garg static void __exit cleanup_trusted(void)
125147f9c279SSumit Garg {
125247f9c279SSumit Garg 	if (chip) {
125347f9c279SSumit Garg 		put_device(&chip->dev);
125447f9c279SSumit Garg 		kfree(digests);
125547f9c279SSumit Garg 		trusted_shash_release();
125647f9c279SSumit Garg 		unregister_key_type(&key_type_trusted);
125747f9c279SSumit Garg 	}
125847f9c279SSumit Garg }
125947f9c279SSumit Garg 
126047f9c279SSumit Garg late_initcall(init_trusted);
126147f9c279SSumit Garg module_exit(cleanup_trusted);
126247f9c279SSumit Garg 
126347f9c279SSumit Garg MODULE_LICENSE("GPL");
1264