Skip to content

Commit 033ee84

Browse files
James Bottomleyjarkkojs
authored andcommitted
tpm: Add TCG mandated Key Derivation Functions (KDFs)
The TCG mandates two Key derivation functions called KDFa and KDFe used to derive keys from seeds and elliptic curve points respectively. The definitions for these functions are found in the TPM 2.0 Library Specification Part 1 - Architecture Guide https://trustedcomputinggroup.org/resource/tpm-library-specification/ Implement a cut down version of each of these functions sufficient to support the key derivation needs of HMAC sessions. Signed-off-by: James Bottomley <[email protected]> Reviewed-by: Jarkko Sakkinen <[email protected]> Tested-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Jarkko Sakkinen <[email protected]>
1 parent d2add27 commit 033ee84

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

drivers/char/tpm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ if TCG_TPM
3030
config TCG_TPM2_HMAC
3131
bool "Use HMAC and encrypted transactions on the TPM bus"
3232
default y
33+
select CRYPTO_LIB_SHA256
3334
help
3435
Setting this causes us to deploy a scheme which uses request
3536
and response HMACs in addition to encryption for

drivers/char/tpm/tpm2-sessions.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,111 @@
77

88
#include "tpm.h"
99
#include <asm/unaligned.h>
10+
#include <crypto/hash.h>
11+
#include <crypto/hmac.h>
12+
13+
/*
14+
* It turns out the crypto hmac(sha256) is hard for us to consume
15+
* because it assumes a fixed key and the TPM seems to change the key
16+
* on every operation, so we weld the hmac init and final functions in
17+
* here to give it the same usage characteristics as a regular hash
18+
*/
19+
static void tpm2_hmac_init(struct sha256_state *sctx, u8 *key, u32 key_len)
20+
{
21+
u8 pad[SHA256_BLOCK_SIZE];
22+
int i;
23+
24+
sha256_init(sctx);
25+
for (i = 0; i < sizeof(pad); i++) {
26+
if (i < key_len)
27+
pad[i] = key[i];
28+
else
29+
pad[i] = 0;
30+
pad[i] ^= HMAC_IPAD_VALUE;
31+
}
32+
sha256_update(sctx, pad, sizeof(pad));
33+
}
34+
35+
static void tpm2_hmac_final(struct sha256_state *sctx, u8 *key, u32 key_len,
36+
u8 *out)
37+
{
38+
u8 pad[SHA256_BLOCK_SIZE];
39+
int i;
40+
41+
for (i = 0; i < sizeof(pad); i++) {
42+
if (i < key_len)
43+
pad[i] = key[i];
44+
else
45+
pad[i] = 0;
46+
pad[i] ^= HMAC_OPAD_VALUE;
47+
}
48+
49+
/* collect the final hash; use out as temporary storage */
50+
sha256_final(sctx, out);
51+
52+
sha256_init(sctx);
53+
sha256_update(sctx, pad, sizeof(pad));
54+
sha256_update(sctx, out, SHA256_DIGEST_SIZE);
55+
sha256_final(sctx, out);
56+
}
57+
58+
/*
59+
* assume hash sha256 and nonces u, v of size SHA256_DIGEST_SIZE but
60+
* otherwise standard tpm2_KDFa. Note output is in bytes not bits.
61+
*/
62+
static void tpm2_KDFa(u8 *key, u32 key_len, const char *label, u8 *u,
63+
u8 *v, u32 bytes, u8 *out)
64+
{
65+
u32 counter = 1;
66+
const __be32 bits = cpu_to_be32(bytes * 8);
67+
68+
while (bytes > 0) {
69+
struct sha256_state sctx;
70+
__be32 c = cpu_to_be32(counter);
71+
72+
tpm2_hmac_init(&sctx, key, key_len);
73+
sha256_update(&sctx, (u8 *)&c, sizeof(c));
74+
sha256_update(&sctx, label, strlen(label)+1);
75+
sha256_update(&sctx, u, SHA256_DIGEST_SIZE);
76+
sha256_update(&sctx, v, SHA256_DIGEST_SIZE);
77+
sha256_update(&sctx, (u8 *)&bits, sizeof(bits));
78+
tpm2_hmac_final(&sctx, key, key_len, out);
79+
80+
bytes -= SHA256_DIGEST_SIZE;
81+
counter++;
82+
out += SHA256_DIGEST_SIZE;
83+
}
84+
}
85+
86+
/*
87+
* Somewhat of a bastardization of the real KDFe. We're assuming
88+
* we're working with known point sizes for the input parameters and
89+
* the hash algorithm is fixed at sha256. Because we know that the
90+
* point size is 32 bytes like the hash size, there's no need to loop
91+
* in this KDF.
92+
*/
93+
static void tpm2_KDFe(u8 z[EC_PT_SZ], const char *str, u8 *pt_u, u8 *pt_v,
94+
u8 *out)
95+
{
96+
struct sha256_state sctx;
97+
/*
98+
* this should be an iterative counter, but because we know
99+
* we're only taking 32 bytes for the point using a sha256
100+
* hash which is also 32 bytes, there's only one loop
101+
*/
102+
__be32 c = cpu_to_be32(1);
103+
104+
sha256_init(&sctx);
105+
/* counter (BE) */
106+
sha256_update(&sctx, (u8 *)&c, sizeof(c));
107+
/* secret value */
108+
sha256_update(&sctx, z, EC_PT_SZ);
109+
/* string including trailing zero */
110+
sha256_update(&sctx, str, strlen(str)+1);
111+
sha256_update(&sctx, pt_u, EC_PT_SZ);
112+
sha256_update(&sctx, pt_v, EC_PT_SZ);
113+
sha256_final(&sctx, out);
114+
}
10115

11116
/**
12117
* tpm2_parse_create_primary() - parse the data returned from TPM_CC_CREATE_PRIMARY

0 commit comments

Comments
 (0)