mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	keys, trusted: select hash algorithm for TPM2 chips
Added 'hash=' option for selecting the hash algorithm for add_key() syscall and documentation for it. Added entry for sm3-256 to the following tables in order to support TPM_ALG_SM3_256: * hash_algo_name * hash_digest_size Includes support for the following hash algorithms: * sha1 * sha256 * sha384 * sha512 * sm3-256 Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Colin Ian King <colin.king@canonical.com> Reviewed-by: James Morris <james.l.morris@oracle.com> Reviewed-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Acked-by: Peter Huewe <peterhuewe@gmx.de>
This commit is contained in:
		
							parent
							
								
									5208cc8342
								
							
						
					
					
						commit
						5ca4c20cfd
					
				
					 9 changed files with 77 additions and 7 deletions
				
			
		| 
						 | 
					@ -38,6 +38,9 @@ Usage:
 | 
				
			||||||
       pcrlock=	  pcr number to be extended to "lock" blob
 | 
					       pcrlock=	  pcr number to be extended to "lock" blob
 | 
				
			||||||
       migratable= 0|1 indicating permission to reseal to new PCR values,
 | 
					       migratable= 0|1 indicating permission to reseal to new PCR values,
 | 
				
			||||||
                   default 1 (resealing allowed)
 | 
					                   default 1 (resealing allowed)
 | 
				
			||||||
 | 
					       hash=      hash algorithm name as a string. For TPM 1.x the only
 | 
				
			||||||
 | 
					                  allowed value is sha1. For TPM 2.x the allowed values
 | 
				
			||||||
 | 
							  are sha1, sha256, sha384, sha512 and sm3-256.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"keyctl print" returns an ascii hex copy of the sealed key, which is in standard
 | 
					"keyctl print" returns an ascii hex copy of the sealed key, which is in standard
 | 
				
			||||||
TPM_STORED_DATA format.  The key length for new keys are always in bytes.
 | 
					TPM_STORED_DATA format.  The key length for new keys are always in bytes.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ const char *const hash_algo_name[HASH_ALGO__LAST] = {
 | 
				
			||||||
	[HASH_ALGO_TGR_128]	= "tgr128",
 | 
						[HASH_ALGO_TGR_128]	= "tgr128",
 | 
				
			||||||
	[HASH_ALGO_TGR_160]	= "tgr160",
 | 
						[HASH_ALGO_TGR_160]	= "tgr160",
 | 
				
			||||||
	[HASH_ALGO_TGR_192]	= "tgr192",
 | 
						[HASH_ALGO_TGR_192]	= "tgr192",
 | 
				
			||||||
 | 
						[HASH_ALGO_SM3_256]	= "sm3-256",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
EXPORT_SYMBOL_GPL(hash_algo_name);
 | 
					EXPORT_SYMBOL_GPL(hash_algo_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,5 +53,6 @@ const int hash_digest_size[HASH_ALGO__LAST] = {
 | 
				
			||||||
	[HASH_ALGO_TGR_128]	= TGR128_DIGEST_SIZE,
 | 
						[HASH_ALGO_TGR_128]	= TGR128_DIGEST_SIZE,
 | 
				
			||||||
	[HASH_ALGO_TGR_160]	= TGR160_DIGEST_SIZE,
 | 
						[HASH_ALGO_TGR_160]	= TGR160_DIGEST_SIZE,
 | 
				
			||||||
	[HASH_ALGO_TGR_192]	= TGR192_DIGEST_SIZE,
 | 
						[HASH_ALGO_TGR_192]	= TGR192_DIGEST_SIZE,
 | 
				
			||||||
 | 
						[HASH_ALGO_SM3_256]	= SM3256_DIGEST_SIZE,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
EXPORT_SYMBOL_GPL(hash_digest_size);
 | 
					EXPORT_SYMBOL_GPL(hash_digest_size);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,16 +83,20 @@ enum tpm2_structures {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum tpm2_return_codes {
 | 
					enum tpm2_return_codes {
 | 
				
			||||||
	TPM2_RC_INITIALIZE	= 0x0100,
 | 
						TPM2_RC_HASH		= 0x0083, /* RC_FMT1 */
 | 
				
			||||||
	TPM2_RC_TESTING		= 0x090A,
 | 
						TPM2_RC_INITIALIZE	= 0x0100, /* RC_VER1 */
 | 
				
			||||||
	TPM2_RC_DISABLED	= 0x0120,
 | 
						TPM2_RC_DISABLED	= 0x0120,
 | 
				
			||||||
 | 
						TPM2_RC_TESTING		= 0x090A, /* RC_WARN */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum tpm2_algorithms {
 | 
					enum tpm2_algorithms {
 | 
				
			||||||
	TPM2_ALG_SHA1		= 0x0004,
 | 
						TPM2_ALG_SHA1		= 0x0004,
 | 
				
			||||||
	TPM2_ALG_KEYEDHASH	= 0x0008,
 | 
						TPM2_ALG_KEYEDHASH	= 0x0008,
 | 
				
			||||||
	TPM2_ALG_SHA256		= 0x000B,
 | 
						TPM2_ALG_SHA256		= 0x000B,
 | 
				
			||||||
	TPM2_ALG_NULL		= 0x0010
 | 
						TPM2_ALG_SHA384		= 0x000C,
 | 
				
			||||||
 | 
						TPM2_ALG_SHA512		= 0x000D,
 | 
				
			||||||
 | 
						TPM2_ALG_NULL		= 0x0010,
 | 
				
			||||||
 | 
						TPM2_ALG_SM3_256	= 0x0012,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum tpm2_command_codes {
 | 
					enum tpm2_command_codes {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "tpm.h"
 | 
					#include "tpm.h"
 | 
				
			||||||
 | 
					#include <crypto/hash_info.h>
 | 
				
			||||||
#include <keys/trusted-type.h>
 | 
					#include <keys/trusted-type.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum tpm2_object_attributes {
 | 
					enum tpm2_object_attributes {
 | 
				
			||||||
| 
						 | 
					@ -104,6 +105,19 @@ struct tpm2_cmd {
 | 
				
			||||||
	union tpm2_cmd_params	params;
 | 
						union tpm2_cmd_params	params;
 | 
				
			||||||
} __packed;
 | 
					} __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
 | 
					 * Array with one entry per ordinal defining the maximum amount
 | 
				
			||||||
 * of time the chip could take to return the result. The values
 | 
					 * of time the chip could take to return the result. The values
 | 
				
			||||||
| 
						 | 
					@ -429,8 +443,20 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int blob_len;
 | 
						unsigned int blob_len;
 | 
				
			||||||
	struct tpm_buf buf;
 | 
						struct tpm_buf buf;
 | 
				
			||||||
 | 
						u32 hash;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
	int rc;
 | 
						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))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
 | 
						rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
		return rc;
 | 
							return rc;
 | 
				
			||||||
| 
						 | 
					@ -455,7 +481,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 | 
				
			||||||
	tpm_buf_append_u16(&buf, 14);
 | 
						tpm_buf_append_u16(&buf, 14);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
 | 
						tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
 | 
				
			||||||
	tpm_buf_append_u16(&buf, TPM2_ALG_SHA256);
 | 
						tpm_buf_append_u16(&buf, hash);
 | 
				
			||||||
	tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
 | 
						tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
 | 
				
			||||||
	tpm_buf_append_u16(&buf, 0); /* policy digest size */
 | 
						tpm_buf_append_u16(&buf, 0); /* policy digest size */
 | 
				
			||||||
	tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
 | 
						tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
 | 
				
			||||||
| 
						 | 
					@ -488,8 +514,12 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	tpm_buf_destroy(&buf);
 | 
						tpm_buf_destroy(&buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rc > 0)
 | 
						if (rc > 0) {
 | 
				
			||||||
		rc = -EPERM;
 | 
							if ((rc & TPM2_RC_HASH) == TPM2_RC_HASH)
 | 
				
			||||||
 | 
								rc = -EINVAL;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								rc = -EPERM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,9 @@
 | 
				
			||||||
#define TGR160_DIGEST_SIZE 20
 | 
					#define TGR160_DIGEST_SIZE 20
 | 
				
			||||||
#define TGR192_DIGEST_SIZE 24
 | 
					#define TGR192_DIGEST_SIZE 24
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* not defined in include/crypto/ */
 | 
				
			||||||
 | 
					#define SM3256_DIGEST_SIZE 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const char *const hash_algo_name[HASH_ALGO__LAST];
 | 
					extern const char *const hash_algo_name[HASH_ALGO__LAST];
 | 
				
			||||||
extern const int hash_digest_size[HASH_ALGO__LAST];
 | 
					extern const int hash_digest_size[HASH_ALGO__LAST];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,7 @@ struct trusted_key_options {
 | 
				
			||||||
	uint32_t pcrinfo_len;
 | 
						uint32_t pcrinfo_len;
 | 
				
			||||||
	unsigned char pcrinfo[MAX_PCRINFO_SIZE];
 | 
						unsigned char pcrinfo[MAX_PCRINFO_SIZE];
 | 
				
			||||||
	int pcrlock;
 | 
						int pcrlock;
 | 
				
			||||||
 | 
						uint32_t hash;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct key_type key_type_trusted;
 | 
					extern struct key_type key_type_trusted;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ enum hash_algo {
 | 
				
			||||||
	HASH_ALGO_TGR_128,
 | 
						HASH_ALGO_TGR_128,
 | 
				
			||||||
	HASH_ALGO_TGR_160,
 | 
						HASH_ALGO_TGR_160,
 | 
				
			||||||
	HASH_ALGO_TGR_192,
 | 
						HASH_ALGO_TGR_192,
 | 
				
			||||||
 | 
						HASH_ALGO_SM3_256,
 | 
				
			||||||
	HASH_ALGO__LAST
 | 
						HASH_ALGO__LAST
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,6 +54,7 @@ config TRUSTED_KEYS
 | 
				
			||||||
	select CRYPTO
 | 
						select CRYPTO
 | 
				
			||||||
	select CRYPTO_HMAC
 | 
						select CRYPTO_HMAC
 | 
				
			||||||
	select CRYPTO_SHA1
 | 
						select CRYPTO_SHA1
 | 
				
			||||||
 | 
						select CRYPTO_HASH_INFO
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  This option provides support for creating, sealing, and unsealing
 | 
						  This option provides support for creating, sealing, and unsealing
 | 
				
			||||||
	  keys in the kernel. Trusted keys are random number symmetric keys,
 | 
						  keys in the kernel. Trusted keys are random number symmetric keys,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,7 @@
 | 
				
			||||||
 * See Documentation/security/keys-trusted-encrypted.txt
 | 
					 * See Documentation/security/keys-trusted-encrypted.txt
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <crypto/hash_info.h>
 | 
				
			||||||
#include <linux/uaccess.h>
 | 
					#include <linux/uaccess.h>
 | 
				
			||||||
#include <linux/module.h>
 | 
					#include <linux/module.h>
 | 
				
			||||||
#include <linux/init.h>
 | 
					#include <linux/init.h>
 | 
				
			||||||
| 
						 | 
					@ -710,7 +711,8 @@ enum {
 | 
				
			||||||
	Opt_err = -1,
 | 
						Opt_err = -1,
 | 
				
			||||||
	Opt_new, Opt_load, Opt_update,
 | 
						Opt_new, Opt_load, Opt_update,
 | 
				
			||||||
	Opt_keyhandle, Opt_keyauth, Opt_blobauth,
 | 
						Opt_keyhandle, Opt_keyauth, Opt_blobauth,
 | 
				
			||||||
	Opt_pcrinfo, Opt_pcrlock, Opt_migratable
 | 
						Opt_pcrinfo, Opt_pcrlock, Opt_migratable,
 | 
				
			||||||
 | 
						Opt_hash,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const match_table_t key_tokens = {
 | 
					static const match_table_t key_tokens = {
 | 
				
			||||||
| 
						 | 
					@ -723,6 +725,7 @@ static const match_table_t key_tokens = {
 | 
				
			||||||
	{Opt_pcrinfo, "pcrinfo=%s"},
 | 
						{Opt_pcrinfo, "pcrinfo=%s"},
 | 
				
			||||||
	{Opt_pcrlock, "pcrlock=%s"},
 | 
						{Opt_pcrlock, "pcrlock=%s"},
 | 
				
			||||||
	{Opt_migratable, "migratable=%s"},
 | 
						{Opt_migratable, "migratable=%s"},
 | 
				
			||||||
 | 
						{Opt_hash, "hash=%s"},
 | 
				
			||||||
	{Opt_err, NULL}
 | 
						{Opt_err, NULL}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -737,6 +740,14 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 | 
				
			||||||
	unsigned long handle;
 | 
						unsigned long handle;
 | 
				
			||||||
	unsigned long lock;
 | 
						unsigned long lock;
 | 
				
			||||||
	unsigned long token_mask = 0;
 | 
						unsigned long token_mask = 0;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						int tpm2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tpm2 = tpm_is_tpm2(TPM_ANY_NUM);
 | 
				
			||||||
 | 
						if (tpm2 < 0)
 | 
				
			||||||
 | 
							return tpm2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((p = strsep(&c, " \t"))) {
 | 
						while ((p = strsep(&c, " \t"))) {
 | 
				
			||||||
		if (*p == '\0' || *p == ' ' || *p == '\t')
 | 
							if (*p == '\0' || *p == ' ' || *p == '\t')
 | 
				
			||||||
| 
						 | 
					@ -790,6 +801,20 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 | 
				
			||||||
				return -EINVAL;
 | 
									return -EINVAL;
 | 
				
			||||||
			opt->pcrlock = lock;
 | 
								opt->pcrlock = lock;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case Opt_hash:
 | 
				
			||||||
 | 
								for (i = 0; i < HASH_ALGO__LAST; i++) {
 | 
				
			||||||
 | 
									if (!strcmp(args[0].from, hash_algo_name[i])) {
 | 
				
			||||||
 | 
										opt->hash = i;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (i == HASH_ALGO__LAST)
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
								if  (!tpm2 && i != HASH_ALGO_SHA1) {
 | 
				
			||||||
 | 
									pr_info("trusted_key: TPM 1.x only supports SHA-1.\n");
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue