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:
Jarkko Sakkinen 2015-11-05 21:43:06 +02:00
parent 5208cc8342
commit 5ca4c20cfd
9 changed files with 77 additions and 7 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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 {

View File

@ -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) {
if ((rc & TPM2_RC_HASH) == TPM2_RC_HASH)
rc = -EINVAL;
else
rc = -EPERM; rc = -EPERM;
}
return rc; return rc;
} }

View File

@ -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];

View File

@ -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;

View File

@ -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
}; };

View File

@ -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,

View File

@ -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;
} }