[PATCH v2 2/5] tpm: introduce tpm_pcr_algo_to_crypto() and tpm_pcr_algo_from_crypto()

Roberto Sassu roberto.sassu at huawei.com
Fri May 5 14:21:49 UTC 2017


tpm_pcr_algorithms() returns to its callers the IDs of the hash algorithms
supported by the TPM. This patch introduces tpm_pcr_algo_to_crypto(),
so that the callers can use the crypto subsystem to calculate the digest
to be passed to tpm_pcr_extend().

tpm_pcr_algo_from_crypto(), implemented for completeness, is instead used
by tpm2_seal_trusted() to perform the opposite conversion.

Signed-off-by: Roberto Sassu <roberto.sassu at huawei.com>
---
v2

- fixed return values of tpm2_pcr_algo_to_crypto() and
  tpm2_pcr_algo_from_crypto() if TPM support is disabled in the kernel

 drivers/char/tpm/tpm-interface.c | 51 ++++++++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm2-cmd.c      | 42 +++++++++------------------------
 include/linux/tpm.h              | 13 ++++++++++
 3 files changed, 75 insertions(+), 31 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index b90de3d..aac703e 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -956,6 +956,57 @@ int tpm_pcr_algorithms(u32 chip_num, int count,
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_algorithms);
 
+struct tpm2_hash {
+	unsigned int crypto_id;
+	unsigned int tpm_id;
+};
+
+static struct tpm2_hash tpm2_hash_map[] = {
+	{HASH_ALGO_SHA1, TPM2_ALG_SHA1},
+	{HASH_ALGO_SHA256, TPM2_ALG_SHA256},
+	{HASH_ALGO_SHA384, TPM2_ALG_SHA384},
+	{HASH_ALGO_SHA512, TPM2_ALG_SHA512},
+	{HASH_ALGO_SM3_256, TPM2_ALG_SM3_256},
+};
+
+/**
+ * tpm_pcr_algo_to_crypto() - convert from TPM ID to crypto ID
+ * @tpm_id:	TPM ID
+ *
+ * Return: crypto ID
+ */
+enum hash_algo tpm_pcr_algo_to_crypto(enum tpm2_algorithms tpm_id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
+		if (tpm_id == tpm2_hash_map[i].tpm_id)
+			return tpm2_hash_map[i].crypto_id;
+	}
+
+	return HASH_ALGO__LAST;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_algo_to_crypto);
+
+/**
+ * tpm_pcr_algo_from_crypto() - convert from crypto ID to TPM ID
+ * @crypto_id:	crypto ID
+ *
+ * Return: TPM ID
+ */
+enum tpm2_algorithms tpm_pcr_algo_from_crypto(enum hash_algo crypto_id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
+		if (crypto_id == tpm2_hash_map[i].crypto_id)
+			return tpm2_hash_map[i].tpm_id;
+	}
+
+	return TPM2_ALG_ERROR;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_algo_from_crypto);
+
 /**
  * tpm_do_selftest - have the TPM continue its selftest and wait until it
  *                   can receive further commands
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 3ee6883..828a688 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -92,19 +92,6 @@ struct tpm2_cmd {
 	union tpm2_cmd_params	params;
 } __packed;
 
-struct tpm2_hash {
-	unsigned int crypto_id;
-	unsigned int tpm_id;
-};
-
-static struct tpm2_hash tpm2_hash_map[] = {
-	{HASH_ALGO_SHA1, TPM2_ALG_SHA1},
-	{HASH_ALGO_SHA256, TPM2_ALG_SHA256},
-	{HASH_ALGO_SHA384, TPM2_ALG_SHA384},
-	{HASH_ALGO_SHA512, TPM2_ALG_SHA512},
-	{HASH_ALGO_SM3_256, TPM2_ALG_SM3_256},
-};
-
 /*
  * Array with one entry per ordinal defining the maximum amount
  * of time the chip could take to return the result. The values
@@ -301,7 +288,6 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
 	struct tpm2_null_auth_area auth_area;
 	int rc;
 	int i;
-	int j;
 
 	if (count > ARRAY_SIZE(chip->active_banks))
 		return -EINVAL;
@@ -323,14 +309,15 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
 	tpm_buf_append_u32(&buf, count);
 
 	for (i = 0; i < count; i++) {
-		for (j = 0; j < ARRAY_SIZE(tpm2_hash_map); j++) {
-			if (digests[i].alg_id != tpm2_hash_map[j].tpm_id)
-				continue;
-			tpm_buf_append_u16(&buf, digests[i].alg_id);
-			tpm_buf_append(&buf, (const unsigned char
-					      *)&digests[i].digest,
-			       hash_digest_size[tpm2_hash_map[j].crypto_id]);
-		}
+		enum tpm2_algorithms tpm_id = digests[i].alg_id;
+		enum hash_algo crypto_id = tpm_pcr_algo_to_crypto(tpm_id);
+
+		if (crypto_id == HASH_ALGO__LAST)
+			continue;
+
+		tpm_buf_append_u16(&buf, digests[i].alg_id);
+		tpm_buf_append(&buf, (const unsigned char *)&digests[i].digest,
+			       hash_digest_size[crypto_id]);
 	}
 
 	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
@@ -493,17 +480,10 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 	unsigned int blob_len;
 	struct tpm_buf buf;
 	u32 hash, rlength;
-	int i;
 	int rc;
 
-	for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
-		if (options->hash == tpm2_hash_map[i].crypto_id) {
-			hash = tpm2_hash_map[i].tpm_id;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(tpm2_hash_map))
+	hash = tpm_pcr_algo_from_crypto(options->hash);
+	if (hash == TPM2_ALG_ERROR)
 		return -EINVAL;
 
 	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index b0d0061..9ecd12c 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -22,6 +22,8 @@
 #ifndef __LINUX_TPM_H__
 #define __LINUX_TPM_H__
 
+#include <crypto/hash_info.h>
+
 #define TPM_DIGEST_SIZE 20	/* Max TPM v1.2 PCR size */
 #define TPM_ACTIVE_BANKS_MAX 7	/* Max num of active banks for TPM 2.0 */
 
@@ -71,6 +73,8 @@ extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
 extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
 extern int tpm_pcr_algorithms(u32 chip_num, int count,
 			      enum tpm2_algorithms *algorithms);
+extern enum hash_algo tpm_pcr_algo_to_crypto(enum tpm2_algorithms tpm_id);
+extern enum tpm2_algorithms tpm_pcr_algo_from_crypto(enum hash_algo crypto_id);
 extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
 extern int tpm_get_random(u32 chip_num, u8 *data, size_t max);
 extern int tpm_seal_trusted(u32 chip_num,
@@ -95,6 +99,15 @@ static inline int tpm_pcr_algorithms(u32 chip_num, int count,
 {
 	return -ENODEV;
 }
+static inline enum hash_algo tpm_pcr_algo_to_crypto(enum tpm2_algorithms tpm_id)
+{
+	return HASH_ALGO__LAST;
+}
+static inline enum tpm2_algorithms tpm_pcr_algo_from_crypto(
+						enum hash_algo crypto_id)
+{
+	return TPM2_ALG_ERROR;
+}
 static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) {
 	return -ENODEV;
 }
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the Linux-security-module-archive mailing list