From 41c89b64d7184a780f12f2cccdabe65cb2408893 Mon Sep 17 00:00:00 2001 From: Petko Manolov Date: Wed, 2 Dec 2015 17:47:55 +0200 Subject: IMA: create machine owner and blacklist keyrings This option creates IMA MOK and blacklist keyrings. IMA MOK is an intermediate keyring that sits between .system and .ima keyrings, effectively forming a simple CA hierarchy. To successfully import a key into .ima_mok it must be signed by a key which CA is in .system keyring. On turn any key that needs to go in .ima keyring must be signed by CA in either .system or .ima_mok keyrings. IMA MOK is empty at kernel boot. IMA blacklist keyring contains all revoked IMA keys. It is consulted before any other keyring. If the search is successful the requested operation is rejected and error is returned to the caller. Signed-off-by: Petko Manolov Signed-off-by: Mimi Zohar --- crypto/asymmetric_keys/x509_public_key.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'crypto') diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 2a44b3752471..9e9e5a6a9ed6 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -321,6 +321,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) goto error_free_cert; } else if (!prep->trusted) { ret = x509_validate_trust(cert, get_system_trusted_keyring()); + if (ret) + ret = x509_validate_trust(cert, get_ima_mok_keyring()); if (!ret) prep->trusted = 1; } -- cgit v1.2.3-70-g09d2 From 5ca4c20cfd37bac6486de040e9951b3b34755238 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Thu, 5 Nov 2015 21:43:06 +0200 Subject: 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 Tested-by: Colin Ian King Reviewed-by: James Morris Reviewed-by: Mimi Zohar Acked-by: Peter Huewe --- Documentation/security/keys-trusted-encrypted.txt | 3 ++ crypto/hash_info.c | 2 ++ drivers/char/tpm/tpm.h | 10 +++++-- drivers/char/tpm/tpm2-cmd.c | 36 +++++++++++++++++++++-- include/crypto/hash_info.h | 3 ++ include/keys/trusted-type.h | 1 + include/uapi/linux/hash_info.h | 1 + security/keys/Kconfig | 1 + security/keys/trusted.c | 27 ++++++++++++++++- 9 files changed, 77 insertions(+), 7 deletions(-) (limited to 'crypto') diff --git a/Documentation/security/keys-trusted-encrypted.txt b/Documentation/security/keys-trusted-encrypted.txt index e105ae97a4f5..fd2565b301e8 100644 --- a/Documentation/security/keys-trusted-encrypted.txt +++ b/Documentation/security/keys-trusted-encrypted.txt @@ -38,6 +38,9 @@ Usage: pcrlock= pcr number to be extended to "lock" blob migratable= 0|1 indicating permission to reseal to new PCR values, 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 TPM_STORED_DATA format. The key length for new keys are always in bytes. diff --git a/crypto/hash_info.c b/crypto/hash_info.c index 3e7ff46f26e8..7b1e0b188ce6 100644 --- a/crypto/hash_info.c +++ b/crypto/hash_info.c @@ -31,6 +31,7 @@ const char *const hash_algo_name[HASH_ALGO__LAST] = { [HASH_ALGO_TGR_128] = "tgr128", [HASH_ALGO_TGR_160] = "tgr160", [HASH_ALGO_TGR_192] = "tgr192", + [HASH_ALGO_SM3_256] = "sm3-256", }; 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_160] = TGR160_DIGEST_SIZE, [HASH_ALGO_TGR_192] = TGR192_DIGEST_SIZE, + [HASH_ALGO_SM3_256] = SM3256_DIGEST_SIZE, }; EXPORT_SYMBOL_GPL(hash_digest_size); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 347fc615bcc9..542a80cbfd9c 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -83,16 +83,20 @@ enum tpm2_structures { }; enum tpm2_return_codes { - TPM2_RC_INITIALIZE = 0x0100, - TPM2_RC_TESTING = 0x090A, + TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ + TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ TPM2_RC_DISABLED = 0x0120, + TPM2_RC_TESTING = 0x090A, /* RC_WARN */ }; enum tpm2_algorithms { TPM2_ALG_SHA1 = 0x0004, TPM2_ALG_KEYEDHASH = 0x0008, 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 { diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index c12130485fc1..d9d082206f6e 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -16,6 +16,7 @@ */ #include "tpm.h" +#include #include enum tpm2_object_attributes { @@ -104,6 +105,19 @@ 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 @@ -429,8 +443,20 @@ int tpm2_seal_trusted(struct tpm_chip *chip, { unsigned int blob_len; struct tpm_buf buf; + u32 hash; + 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)) + return -EINVAL; + rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); if (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, 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_u16(&buf, 0); /* policy digest size */ tpm_buf_append_u16(&buf, TPM2_ALG_NULL); @@ -488,8 +514,12 @@ int tpm2_seal_trusted(struct tpm_chip *chip, out: tpm_buf_destroy(&buf); - if (rc > 0) - rc = -EPERM; + if (rc > 0) { + if ((rc & TPM2_RC_HASH) == TPM2_RC_HASH) + rc = -EINVAL; + else + rc = -EPERM; + } return rc; } diff --git a/include/crypto/hash_info.h b/include/crypto/hash_info.h index e1e5a3e5dd1b..56f217d41f12 100644 --- a/include/crypto/hash_info.h +++ b/include/crypto/hash_info.h @@ -34,6 +34,9 @@ #define TGR160_DIGEST_SIZE 20 #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 int hash_digest_size[HASH_ALGO__LAST]; diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h index f91ecd9d1bb1..a6a100833ae9 100644 --- a/include/keys/trusted-type.h +++ b/include/keys/trusted-type.h @@ -36,6 +36,7 @@ struct trusted_key_options { uint32_t pcrinfo_len; unsigned char pcrinfo[MAX_PCRINFO_SIZE]; int pcrlock; + uint32_t hash; }; extern struct key_type key_type_trusted; diff --git a/include/uapi/linux/hash_info.h b/include/uapi/linux/hash_info.h index ca18c45f8304..ebf8fd885dd5 100644 --- a/include/uapi/linux/hash_info.h +++ b/include/uapi/linux/hash_info.h @@ -31,6 +31,7 @@ enum hash_algo { HASH_ALGO_TGR_128, HASH_ALGO_TGR_160, HASH_ALGO_TGR_192, + HASH_ALGO_SM3_256, HASH_ALGO__LAST }; diff --git a/security/keys/Kconfig b/security/keys/Kconfig index 72483b8f1be5..fe4d74e126a7 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -54,6 +54,7 @@ config TRUSTED_KEYS select CRYPTO select CRYPTO_HMAC select CRYPTO_SHA1 + select CRYPTO_HASH_INFO help This option provides support for creating, sealing, and unsealing keys in the kernel. Trusted keys are random number symmetric keys, diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 7c183c767a3a..8f1300cab38e 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -11,6 +11,7 @@ * See Documentation/security/keys-trusted-encrypted.txt */ +#include #include #include #include @@ -710,7 +711,8 @@ enum { Opt_err = -1, Opt_new, Opt_load, Opt_update, 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 = { @@ -723,6 +725,7 @@ static const match_table_t key_tokens = { {Opt_pcrinfo, "pcrinfo=%s"}, {Opt_pcrlock, "pcrlock=%s"}, {Opt_migratable, "migratable=%s"}, + {Opt_hash, "hash=%s"}, {Opt_err, NULL} }; @@ -737,6 +740,14 @@ static int getoptions(char *c, struct trusted_key_payload *pay, unsigned long handle; unsigned long lock; 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"))) { if (*p == '\0' || *p == ' ' || *p == '\t') @@ -790,6 +801,20 @@ static int getoptions(char *c, struct trusted_key_payload *pay, return -EINVAL; opt->pcrlock = lock; 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: return -EINVAL; } -- cgit v1.2.3-70-g09d2