mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-12 01:20:14 +00:00
Hi,
A few minor updates/fixes for keys. BR, Jarkko -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRE6pSOnaBC00OEHEIaerohdGur0gUCaOEv8gAKCRAaerohdGur 0q3BAPwLHEF9RDLyDbmUKMYXO2F7ckApZFW4zURYGAG9PpiE9wEA7daw0luUZGsB u3767QRyhKrhJc0ad+QF95rj8GKuSgg= =8Nni -----END PGP SIGNATURE----- Merge tag 'keys-next-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd Pull keys updates from Jarkko Sakkinen: "A few minor updates/fixes for keys" * tag 'keys-next-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd: security: keys: use menuconfig for KEYS symbol KEYS: encrypted: Use SHA-256 library instead of crypto_shash KEYS: trusted_tpm1: Move private functionality out of public header KEYS: trusted_tpm1: Use SHA-1 library instead of crypto_shash KEYS: trusted_tpm1: Compare HMAC values in constant time
This commit is contained in:
commit
b4e5bb5555
@ -5,41 +5,8 @@
|
||||
#include <keys/trusted-type.h>
|
||||
#include <linux/tpm_command.h>
|
||||
|
||||
/* implementation specific TPM constants */
|
||||
#define TPM_SIZE_OFFSET 2
|
||||
#define TPM_RETURN_OFFSET 6
|
||||
#define TPM_DATA_OFFSET 10
|
||||
|
||||
#define LOAD32(buffer, offset) (ntohl(*(uint32_t *)&buffer[offset]))
|
||||
#define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset])
|
||||
#define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset]))
|
||||
|
||||
extern struct trusted_key_ops trusted_key_tpm_ops;
|
||||
|
||||
struct osapsess {
|
||||
uint32_t handle;
|
||||
unsigned char secret[SHA1_DIGEST_SIZE];
|
||||
unsigned char enonce[TPM_NONCE_SIZE];
|
||||
};
|
||||
|
||||
/* discrete values, but have to store in uint16_t for TPM use */
|
||||
enum {
|
||||
SEAL_keytype = 1,
|
||||
SRK_keytype = 4
|
||||
};
|
||||
|
||||
int TSS_authhmac(unsigned char *digest, const unsigned char *key,
|
||||
unsigned int keylen, unsigned char *h1,
|
||||
unsigned char *h2, unsigned int h3, ...);
|
||||
int TSS_checkhmac1(unsigned char *buffer,
|
||||
const uint32_t command,
|
||||
const unsigned char *ononce,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen, ...);
|
||||
|
||||
int trusted_tpm_send(unsigned char *cmd, size_t buflen);
|
||||
int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce);
|
||||
|
||||
int tpm2_seal_trusted(struct tpm_chip *chip,
|
||||
struct trusted_key_payload *payload,
|
||||
struct trusted_key_options *options);
|
||||
@ -47,50 +14,4 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
|
||||
struct trusted_key_payload *payload,
|
||||
struct trusted_key_options *options);
|
||||
|
||||
#define TPM_DEBUG 0
|
||||
|
||||
#if TPM_DEBUG
|
||||
static inline void dump_options(struct trusted_key_options *o)
|
||||
{
|
||||
pr_info("sealing key type %d\n", o->keytype);
|
||||
pr_info("sealing key handle %0X\n", o->keyhandle);
|
||||
pr_info("pcrlock %d\n", o->pcrlock);
|
||||
pr_info("pcrinfo %d\n", o->pcrinfo_len);
|
||||
print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE,
|
||||
16, 1, o->pcrinfo, o->pcrinfo_len, 0);
|
||||
}
|
||||
|
||||
static inline void dump_sess(struct osapsess *s)
|
||||
{
|
||||
print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE,
|
||||
16, 1, &s->handle, 4, 0);
|
||||
pr_info("secret:\n");
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
|
||||
16, 1, &s->secret, SHA1_DIGEST_SIZE, 0);
|
||||
pr_info("trusted-key: enonce:\n");
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
|
||||
16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);
|
||||
}
|
||||
|
||||
static inline void dump_tpm_buf(unsigned char *buf)
|
||||
{
|
||||
int len;
|
||||
|
||||
pr_info("\ntpm buffer\n");
|
||||
len = LOAD32(buf, TPM_SIZE_OFFSET);
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
|
||||
}
|
||||
#else
|
||||
static inline void dump_options(struct trusted_key_options *o)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dump_sess(struct osapsess *s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dump_tpm_buf(unsigned char *buf)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
# Key management configuration
|
||||
#
|
||||
|
||||
config KEYS
|
||||
menuconfig KEYS
|
||||
bool "Enable access key retention support"
|
||||
select ASSOCIATIVE_ARRAY
|
||||
help
|
||||
@ -21,9 +21,10 @@ config KEYS
|
||||
|
||||
If you are unsure as to whether this is required, answer N.
|
||||
|
||||
if KEYS
|
||||
|
||||
config KEYS_REQUEST_CACHE
|
||||
bool "Enable temporary caching of the last request_key() result"
|
||||
depends on KEYS
|
||||
help
|
||||
This option causes the result of the last successful request_key()
|
||||
call that didn't upcall to the kernel to be cached temporarily in the
|
||||
@ -41,7 +42,6 @@ config KEYS_REQUEST_CACHE
|
||||
|
||||
config PERSISTENT_KEYRINGS
|
||||
bool "Enable register of persistent per-UID keyrings"
|
||||
depends on KEYS
|
||||
help
|
||||
This option provides a register of persistent per-UID keyrings,
|
||||
primarily aimed at Kerberos key storage. The keyrings are persistent
|
||||
@ -58,7 +58,6 @@ config PERSISTENT_KEYRINGS
|
||||
|
||||
config BIG_KEYS
|
||||
bool "Large payload keys"
|
||||
depends on KEYS
|
||||
depends on TMPFS
|
||||
select CRYPTO_LIB_CHACHA20POLY1305
|
||||
help
|
||||
@ -70,7 +69,6 @@ config BIG_KEYS
|
||||
|
||||
config TRUSTED_KEYS
|
||||
tristate "TRUSTED KEYS"
|
||||
depends on KEYS
|
||||
help
|
||||
This option provides support for creating, sealing, and unsealing
|
||||
keys in the kernel. Trusted keys are random number symmetric keys,
|
||||
@ -85,12 +83,10 @@ endif
|
||||
|
||||
config ENCRYPTED_KEYS
|
||||
tristate "ENCRYPTED KEYS"
|
||||
depends on KEYS
|
||||
select CRYPTO
|
||||
select CRYPTO_HMAC
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_CBC
|
||||
select CRYPTO_SHA256
|
||||
select CRYPTO_LIB_SHA256
|
||||
select CRYPTO_RNG
|
||||
help
|
||||
This option provides support for create/encrypting/decrypting keys
|
||||
@ -114,7 +110,6 @@ config USER_DECRYPTED_DATA
|
||||
|
||||
config KEY_DH_OPERATIONS
|
||||
bool "Diffie-Hellman operations on retained keys"
|
||||
depends on KEYS
|
||||
select CRYPTO
|
||||
select CRYPTO_KDF800108_CTR
|
||||
select CRYPTO_DH
|
||||
@ -127,9 +122,11 @@ config KEY_DH_OPERATIONS
|
||||
|
||||
config KEY_NOTIFICATIONS
|
||||
bool "Provide key/keyring change notifications"
|
||||
depends on KEYS && WATCH_QUEUE
|
||||
depends on WATCH_QUEUE
|
||||
help
|
||||
This option provides support for getting change notifications
|
||||
on keys and keyrings on which the caller has View permission.
|
||||
This makes use of pipes to handle the notification buffer and
|
||||
provides KEYCTL_WATCH_KEY to enable/disable watches.
|
||||
|
||||
endif # KEYS
|
||||
|
||||
@ -27,7 +27,6 @@
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/sha2.h>
|
||||
#include <crypto/skcipher.h>
|
||||
#include <crypto/utils.h>
|
||||
@ -37,8 +36,6 @@
|
||||
|
||||
static const char KEY_TRUSTED_PREFIX[] = "trusted:";
|
||||
static const char KEY_USER_PREFIX[] = "user:";
|
||||
static const char hash_alg[] = "sha256";
|
||||
static const char hmac_alg[] = "hmac(sha256)";
|
||||
static const char blkcipher_alg[] = "cbc(aes)";
|
||||
static const char key_format_default[] = "default";
|
||||
static const char key_format_ecryptfs[] = "ecryptfs";
|
||||
@ -54,8 +51,6 @@ static int blksize;
|
||||
#define MIN_DATA_SIZE 20
|
||||
#define KEY_ENC32_PAYLOAD_LEN 32
|
||||
|
||||
static struct crypto_shash *hash_tfm;
|
||||
|
||||
enum {
|
||||
Opt_new, Opt_load, Opt_update, Opt_err
|
||||
};
|
||||
@ -329,26 +324,6 @@ error:
|
||||
return ukey;
|
||||
}
|
||||
|
||||
static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen,
|
||||
const u8 *buf, unsigned int buflen)
|
||||
{
|
||||
struct crypto_shash *tfm;
|
||||
int err;
|
||||
|
||||
tfm = crypto_alloc_shash(hmac_alg, 0, 0);
|
||||
if (IS_ERR(tfm)) {
|
||||
pr_err("encrypted_key: can't alloc %s transform: %ld\n",
|
||||
hmac_alg, PTR_ERR(tfm));
|
||||
return PTR_ERR(tfm);
|
||||
}
|
||||
|
||||
err = crypto_shash_setkey(tfm, key, keylen);
|
||||
if (!err)
|
||||
err = crypto_shash_tfm_digest(tfm, buf, buflen, digest);
|
||||
crypto_free_shash(tfm);
|
||||
return err;
|
||||
}
|
||||
|
||||
enum derived_key_type { ENC_KEY, AUTH_KEY };
|
||||
|
||||
/* Derive authentication/encryption key from trusted key */
|
||||
@ -357,7 +332,6 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
|
||||
{
|
||||
u8 *derived_buf;
|
||||
unsigned int derived_buf_len;
|
||||
int ret;
|
||||
|
||||
derived_buf_len = strlen("AUTH_KEY") + 1 + master_keylen;
|
||||
if (derived_buf_len < HASH_SIZE)
|
||||
@ -374,10 +348,9 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
|
||||
|
||||
memcpy(derived_buf + strlen(derived_buf) + 1, master_key,
|
||||
master_keylen);
|
||||
ret = crypto_shash_tfm_digest(hash_tfm, derived_buf, derived_buf_len,
|
||||
derived_key);
|
||||
sha256(derived_buf, derived_buf_len, derived_key);
|
||||
kfree_sensitive(derived_buf);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct skcipher_request *init_skcipher_req(const u8 *key,
|
||||
@ -503,10 +476,10 @@ static int datablob_hmac_append(struct encrypted_key_payload *epayload,
|
||||
goto out;
|
||||
|
||||
digest = epayload->format + epayload->datablob_len;
|
||||
ret = calc_hmac(digest, derived_key, sizeof derived_key,
|
||||
epayload->format, epayload->datablob_len);
|
||||
if (!ret)
|
||||
dump_hmac(NULL, digest, HASH_SIZE);
|
||||
hmac_sha256_usingrawkey(derived_key, sizeof(derived_key),
|
||||
epayload->format, epayload->datablob_len,
|
||||
digest);
|
||||
dump_hmac(NULL, digest, HASH_SIZE);
|
||||
out:
|
||||
memzero_explicit(derived_key, sizeof(derived_key));
|
||||
return ret;
|
||||
@ -534,9 +507,8 @@ static int datablob_hmac_verify(struct encrypted_key_payload *epayload,
|
||||
} else
|
||||
p = epayload->format;
|
||||
|
||||
ret = calc_hmac(digest, derived_key, sizeof derived_key, p, len);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
hmac_sha256_usingrawkey(derived_key, sizeof(derived_key), p, len,
|
||||
digest);
|
||||
ret = crypto_memneq(digest, epayload->format + epayload->datablob_len,
|
||||
sizeof(digest));
|
||||
if (ret) {
|
||||
@ -1011,29 +983,14 @@ static int __init init_encrypted(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hash_tfm = crypto_alloc_shash(hash_alg, 0, 0);
|
||||
if (IS_ERR(hash_tfm)) {
|
||||
pr_err("encrypted_key: can't allocate %s transform: %ld\n",
|
||||
hash_alg, PTR_ERR(hash_tfm));
|
||||
return PTR_ERR(hash_tfm);
|
||||
}
|
||||
|
||||
ret = aes_get_sizes();
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = register_key_type(&key_type_encrypted);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
return 0;
|
||||
out:
|
||||
crypto_free_shash(hash_tfm);
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return register_key_type(&key_type_encrypted);
|
||||
}
|
||||
|
||||
static void __exit cleanup_encrypted(void)
|
||||
{
|
||||
crypto_free_shash(hash_tfm);
|
||||
unregister_key_type(&key_type_encrypted);
|
||||
}
|
||||
|
||||
|
||||
@ -5,10 +5,9 @@ config TRUSTED_KEYS_TPM
|
||||
bool "TPM-based trusted keys"
|
||||
depends on TCG_TPM >= TRUSTED_KEYS
|
||||
default y
|
||||
select CRYPTO
|
||||
select CRYPTO_HMAC
|
||||
select CRYPTO_SHA1
|
||||
select CRYPTO_HASH_INFO
|
||||
select CRYPTO_LIB_SHA1
|
||||
select CRYPTO_LIB_UTILS
|
||||
select ASN1_ENCODER
|
||||
select OID_REGISTRY
|
||||
select ASN1
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
*/
|
||||
|
||||
#include <crypto/hash_info.h>
|
||||
#include <crypto/sha1.h>
|
||||
#include <crypto/utils.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/parser.h>
|
||||
@ -14,78 +16,92 @@
|
||||
#include <linux/err.h>
|
||||
#include <keys/trusted-type.h>
|
||||
#include <linux/key-type.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/sha1.h>
|
||||
#include <linux/tpm.h>
|
||||
#include <linux/tpm_command.h>
|
||||
|
||||
#include <keys/trusted_tpm.h>
|
||||
|
||||
static const char hmac_alg[] = "hmac(sha1)";
|
||||
static const char hash_alg[] = "sha1";
|
||||
static struct tpm_chip *chip;
|
||||
static struct tpm_digest *digests;
|
||||
|
||||
struct sdesc {
|
||||
struct shash_desc shash;
|
||||
char ctx[];
|
||||
/* implementation specific TPM constants */
|
||||
#define TPM_SIZE_OFFSET 2
|
||||
#define TPM_RETURN_OFFSET 6
|
||||
#define TPM_DATA_OFFSET 10
|
||||
|
||||
#define LOAD32(buffer, offset) (ntohl(*(uint32_t *)&buffer[offset]))
|
||||
#define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset])
|
||||
#define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset]))
|
||||
|
||||
struct osapsess {
|
||||
uint32_t handle;
|
||||
unsigned char secret[SHA1_DIGEST_SIZE];
|
||||
unsigned char enonce[TPM_NONCE_SIZE];
|
||||
};
|
||||
|
||||
static struct crypto_shash *hashalg;
|
||||
static struct crypto_shash *hmacalg;
|
||||
/* discrete values, but have to store in uint16_t for TPM use */
|
||||
enum {
|
||||
SEAL_keytype = 1,
|
||||
SRK_keytype = 4
|
||||
};
|
||||
|
||||
static struct sdesc *init_sdesc(struct crypto_shash *alg)
|
||||
#define TPM_DEBUG 0
|
||||
|
||||
#if TPM_DEBUG
|
||||
static inline void dump_options(struct trusted_key_options *o)
|
||||
{
|
||||
struct sdesc *sdesc;
|
||||
int size;
|
||||
|
||||
size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
|
||||
sdesc = kmalloc(size, GFP_KERNEL);
|
||||
if (!sdesc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
sdesc->shash.tfm = alg;
|
||||
return sdesc;
|
||||
pr_info("sealing key type %d\n", o->keytype);
|
||||
pr_info("sealing key handle %0X\n", o->keyhandle);
|
||||
pr_info("pcrlock %d\n", o->pcrlock);
|
||||
pr_info("pcrinfo %d\n", o->pcrinfo_len);
|
||||
print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE,
|
||||
16, 1, o->pcrinfo, o->pcrinfo_len, 0);
|
||||
}
|
||||
|
||||
static int TSS_sha1(const unsigned char *data, unsigned int datalen,
|
||||
unsigned char *digest)
|
||||
static inline void dump_sess(struct osapsess *s)
|
||||
{
|
||||
struct sdesc *sdesc;
|
||||
int ret;
|
||||
|
||||
sdesc = init_sdesc(hashalg);
|
||||
if (IS_ERR(sdesc)) {
|
||||
pr_info("can't alloc %s\n", hash_alg);
|
||||
return PTR_ERR(sdesc);
|
||||
}
|
||||
|
||||
ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
|
||||
kfree_sensitive(sdesc);
|
||||
return ret;
|
||||
print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE,
|
||||
16, 1, &s->handle, 4, 0);
|
||||
pr_info("secret:\n");
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
|
||||
16, 1, &s->secret, SHA1_DIGEST_SIZE, 0);
|
||||
pr_info("trusted-key: enonce:\n");
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
|
||||
16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);
|
||||
}
|
||||
|
||||
static inline void dump_tpm_buf(unsigned char *buf)
|
||||
{
|
||||
int len;
|
||||
|
||||
pr_info("\ntpm buffer\n");
|
||||
len = LOAD32(buf, TPM_SIZE_OFFSET);
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
|
||||
}
|
||||
#else
|
||||
static inline void dump_options(struct trusted_key_options *o)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dump_sess(struct osapsess *s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dump_tpm_buf(unsigned char *buf)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,
|
||||
unsigned int keylen, ...)
|
||||
{
|
||||
struct sdesc *sdesc;
|
||||
struct hmac_sha1_ctx hmac_ctx;
|
||||
va_list argp;
|
||||
unsigned int dlen;
|
||||
unsigned char *data;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
sdesc = init_sdesc(hmacalg);
|
||||
if (IS_ERR(sdesc)) {
|
||||
pr_info("can't alloc %s\n", hmac_alg);
|
||||
return PTR_ERR(sdesc);
|
||||
}
|
||||
|
||||
ret = crypto_shash_setkey(hmacalg, key, keylen);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = crypto_shash_init(&sdesc->shash);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
hmac_sha1_init_usingrawkey(&hmac_ctx, key, keylen);
|
||||
|
||||
va_start(argp, keylen);
|
||||
for (;;) {
|
||||
@ -97,46 +113,34 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = crypto_shash_update(&sdesc->shash, data, dlen);
|
||||
if (ret < 0)
|
||||
break;
|
||||
hmac_sha1_update(&hmac_ctx, data, dlen);
|
||||
}
|
||||
va_end(argp);
|
||||
if (!ret)
|
||||
ret = crypto_shash_final(&sdesc->shash, digest);
|
||||
out:
|
||||
kfree_sensitive(sdesc);
|
||||
hmac_sha1_final(&hmac_ctx, digest);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate authorization info fields to send to TPM
|
||||
*/
|
||||
int TSS_authhmac(unsigned char *digest, const unsigned char *key,
|
||||
static int TSS_authhmac(unsigned char *digest, const unsigned char *key,
|
||||
unsigned int keylen, unsigned char *h1,
|
||||
unsigned char *h2, unsigned int h3, ...)
|
||||
{
|
||||
unsigned char paramdigest[SHA1_DIGEST_SIZE];
|
||||
struct sdesc *sdesc;
|
||||
struct sha1_ctx sha_ctx;
|
||||
unsigned int dlen;
|
||||
unsigned char *data;
|
||||
unsigned char c;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
va_list argp;
|
||||
|
||||
if (!chip)
|
||||
return -ENODEV;
|
||||
|
||||
sdesc = init_sdesc(hashalg);
|
||||
if (IS_ERR(sdesc)) {
|
||||
pr_info("can't alloc %s\n", hash_alg);
|
||||
return PTR_ERR(sdesc);
|
||||
}
|
||||
|
||||
c = !!h3;
|
||||
ret = crypto_shash_init(&sdesc->shash);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
sha1_init(&sha_ctx);
|
||||
va_start(argp, h3);
|
||||
for (;;) {
|
||||
dlen = va_arg(argp, unsigned int);
|
||||
@ -147,27 +151,22 @@ int TSS_authhmac(unsigned char *digest, const unsigned char *key,
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = crypto_shash_update(&sdesc->shash, data, dlen);
|
||||
if (ret < 0)
|
||||
break;
|
||||
sha1_update(&sha_ctx, data, dlen);
|
||||
}
|
||||
va_end(argp);
|
||||
if (!ret)
|
||||
ret = crypto_shash_final(&sdesc->shash, paramdigest);
|
||||
sha1_final(&sha_ctx, paramdigest);
|
||||
if (!ret)
|
||||
ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE,
|
||||
paramdigest, TPM_NONCE_SIZE, h1,
|
||||
TPM_NONCE_SIZE, h2, 1, &c, 0, 0);
|
||||
out:
|
||||
kfree_sensitive(sdesc);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(TSS_authhmac);
|
||||
|
||||
/*
|
||||
* verify the AUTH1_COMMAND (Seal) result from TPM
|
||||
*/
|
||||
int TSS_checkhmac1(unsigned char *buffer,
|
||||
static int TSS_checkhmac1(unsigned char *buffer,
|
||||
const uint32_t command,
|
||||
const unsigned char *ononce,
|
||||
const unsigned char *key,
|
||||
@ -182,7 +181,7 @@ int TSS_checkhmac1(unsigned char *buffer,
|
||||
unsigned char *authdata;
|
||||
unsigned char testhmac[SHA1_DIGEST_SIZE];
|
||||
unsigned char paramdigest[SHA1_DIGEST_SIZE];
|
||||
struct sdesc *sdesc;
|
||||
struct sha1_ctx sha_ctx;
|
||||
unsigned int dlen;
|
||||
unsigned int dpos;
|
||||
va_list argp;
|
||||
@ -203,51 +202,30 @@ int TSS_checkhmac1(unsigned char *buffer,
|
||||
continueflag = authdata - 1;
|
||||
enonce = continueflag - TPM_NONCE_SIZE;
|
||||
|
||||
sdesc = init_sdesc(hashalg);
|
||||
if (IS_ERR(sdesc)) {
|
||||
pr_info("can't alloc %s\n", hash_alg);
|
||||
return PTR_ERR(sdesc);
|
||||
}
|
||||
ret = crypto_shash_init(&sdesc->shash);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
|
||||
sizeof result);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
|
||||
sizeof ordinal);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
sha1_init(&sha_ctx);
|
||||
sha1_update(&sha_ctx, (const u8 *)&result, sizeof(result));
|
||||
sha1_update(&sha_ctx, (const u8 *)&ordinal, sizeof(ordinal));
|
||||
va_start(argp, keylen);
|
||||
for (;;) {
|
||||
dlen = va_arg(argp, unsigned int);
|
||||
if (dlen == 0)
|
||||
break;
|
||||
dpos = va_arg(argp, unsigned int);
|
||||
ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
|
||||
if (ret < 0)
|
||||
break;
|
||||
sha1_update(&sha_ctx, buffer + dpos, dlen);
|
||||
}
|
||||
va_end(argp);
|
||||
if (!ret)
|
||||
ret = crypto_shash_final(&sdesc->shash, paramdigest);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
sha1_final(&sha_ctx, paramdigest);
|
||||
|
||||
ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest,
|
||||
TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce,
|
||||
1, continueflag, 0, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
return ret;
|
||||
|
||||
if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE))
|
||||
ret = -EINVAL;
|
||||
out:
|
||||
kfree_sensitive(sdesc);
|
||||
return ret;
|
||||
if (crypto_memneq(testhmac, authdata, SHA1_DIGEST_SIZE))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(TSS_checkhmac1);
|
||||
|
||||
/*
|
||||
* verify the AUTH2_COMMAND (unseal) result from TPM
|
||||
@ -273,7 +251,7 @@ static int TSS_checkhmac2(unsigned char *buffer,
|
||||
unsigned char testhmac1[SHA1_DIGEST_SIZE];
|
||||
unsigned char testhmac2[SHA1_DIGEST_SIZE];
|
||||
unsigned char paramdigest[SHA1_DIGEST_SIZE];
|
||||
struct sdesc *sdesc;
|
||||
struct sha1_ctx sha_ctx;
|
||||
unsigned int dlen;
|
||||
unsigned int dpos;
|
||||
va_list argp;
|
||||
@ -296,22 +274,9 @@ static int TSS_checkhmac2(unsigned char *buffer,
|
||||
enonce1 = continueflag1 - TPM_NONCE_SIZE;
|
||||
enonce2 = continueflag2 - TPM_NONCE_SIZE;
|
||||
|
||||
sdesc = init_sdesc(hashalg);
|
||||
if (IS_ERR(sdesc)) {
|
||||
pr_info("can't alloc %s\n", hash_alg);
|
||||
return PTR_ERR(sdesc);
|
||||
}
|
||||
ret = crypto_shash_init(&sdesc->shash);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,
|
||||
sizeof result);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,
|
||||
sizeof ordinal);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
sha1_init(&sha_ctx);
|
||||
sha1_update(&sha_ctx, (const u8 *)&result, sizeof(result));
|
||||
sha1_update(&sha_ctx, (const u8 *)&ordinal, sizeof(ordinal));
|
||||
|
||||
va_start(argp, keylen2);
|
||||
for (;;) {
|
||||
@ -319,42 +284,33 @@ static int TSS_checkhmac2(unsigned char *buffer,
|
||||
if (dlen == 0)
|
||||
break;
|
||||
dpos = va_arg(argp, unsigned int);
|
||||
ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);
|
||||
if (ret < 0)
|
||||
break;
|
||||
sha1_update(&sha_ctx, buffer + dpos, dlen);
|
||||
}
|
||||
va_end(argp);
|
||||
if (!ret)
|
||||
ret = crypto_shash_final(&sdesc->shash, paramdigest);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
sha1_final(&sha_ctx, paramdigest);
|
||||
|
||||
ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE,
|
||||
paramdigest, TPM_NONCE_SIZE, enonce1,
|
||||
TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
return ret;
|
||||
if (crypto_memneq(testhmac1, authdata1, SHA1_DIGEST_SIZE))
|
||||
return -EINVAL;
|
||||
ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE,
|
||||
paramdigest, TPM_NONCE_SIZE, enonce2,
|
||||
TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE))
|
||||
ret = -EINVAL;
|
||||
out:
|
||||
kfree_sensitive(sdesc);
|
||||
return ret;
|
||||
return ret;
|
||||
if (crypto_memneq(testhmac2, authdata2, SHA1_DIGEST_SIZE))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For key specific tpm requests, we will generate and send our
|
||||
* own TPM command packets using the drivers send function.
|
||||
*/
|
||||
int trusted_tpm_send(unsigned char *cmd, size_t buflen)
|
||||
static int trusted_tpm_send(unsigned char *cmd, size_t buflen)
|
||||
{
|
||||
struct tpm_buf buf;
|
||||
int rc;
|
||||
@ -380,7 +336,6 @@ int trusted_tpm_send(unsigned char *cmd, size_t buflen)
|
||||
tpm_put_ops(chip);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(trusted_tpm_send);
|
||||
|
||||
/*
|
||||
* Lock a trusted key, by extending a selected PCR.
|
||||
@ -434,7 +389,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
|
||||
/*
|
||||
* Create an object independent authorisation protocol (oiap) session
|
||||
*/
|
||||
int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
|
||||
static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -451,7 +406,6 @@ int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
|
||||
TPM_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(oiap);
|
||||
|
||||
struct tpm_digests {
|
||||
unsigned char encauth[SHA1_DIGEST_SIZE];
|
||||
@ -498,9 +452,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
|
||||
/* calculate encrypted authorization value */
|
||||
memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE);
|
||||
memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE);
|
||||
ret = TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);
|
||||
|
||||
ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);
|
||||
if (ret < 0)
|
||||
@ -989,40 +941,6 @@ static int trusted_tpm_get_random(unsigned char *key, size_t key_len)
|
||||
return tpm_get_random(chip, key, key_len);
|
||||
}
|
||||
|
||||
static void trusted_shash_release(void)
|
||||
{
|
||||
if (hashalg)
|
||||
crypto_free_shash(hashalg);
|
||||
if (hmacalg)
|
||||
crypto_free_shash(hmacalg);
|
||||
}
|
||||
|
||||
static int __init trusted_shash_alloc(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hmacalg = crypto_alloc_shash(hmac_alg, 0, 0);
|
||||
if (IS_ERR(hmacalg)) {
|
||||
pr_info("could not allocate crypto %s\n",
|
||||
hmac_alg);
|
||||
return PTR_ERR(hmacalg);
|
||||
}
|
||||
|
||||
hashalg = crypto_alloc_shash(hash_alg, 0, 0);
|
||||
if (IS_ERR(hashalg)) {
|
||||
pr_info("could not allocate crypto %s\n",
|
||||
hash_alg);
|
||||
ret = PTR_ERR(hashalg);
|
||||
goto hashalg_fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
hashalg_fail:
|
||||
crypto_free_shash(hmacalg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init init_digests(void)
|
||||
{
|
||||
int i;
|
||||
@ -1049,15 +967,10 @@ static int __init trusted_tpm_init(void)
|
||||
ret = init_digests();
|
||||
if (ret < 0)
|
||||
goto err_put;
|
||||
ret = trusted_shash_alloc();
|
||||
if (ret < 0)
|
||||
goto err_free;
|
||||
ret = register_key_type(&key_type_trusted);
|
||||
if (ret < 0)
|
||||
goto err_release;
|
||||
goto err_free;
|
||||
return 0;
|
||||
err_release:
|
||||
trusted_shash_release();
|
||||
err_free:
|
||||
kfree(digests);
|
||||
err_put:
|
||||
@ -1070,7 +983,6 @@ static void trusted_tpm_exit(void)
|
||||
if (chip) {
|
||||
put_device(&chip->dev);
|
||||
kfree(digests);
|
||||
trusted_shash_release();
|
||||
unregister_key_type(&key_type_trusted);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user