summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2018-10-09 12:48:58 -0400
committerJames Morris <james.morris@microsoft.com>2018-10-26 04:30:47 -0400
commit0c36264aa1d5b77eb21f646f83223134e4528cfe (patch)
treea6415d4abbaffbd4aa103f51616db71560cf9d3f
parent22447981fc050b5f1bdd0e7cbee89b4152a2b2d8 (diff)
KEYS: asym_tpm: Add loadkey2 and flushspecific [ver #2]
This commit adds TPM_LoadKey2 and TPM_FlushSpecific operations. Signed-off-by: Denis Kenzior <denkenz@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: James Morris <james.morris@microsoft.com> Tested-by: Marcel Holtmann <marcel@holtmann.org> Reviewed-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: James Morris <james.morris@microsoft.com>
-rw-r--r--crypto/asymmetric_keys/asym_tpm.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/crypto/asymmetric_keys/asym_tpm.c b/crypto/asymmetric_keys/asym_tpm.c
index 8edca3c4c193..6a2d33014ecc 100644
--- a/crypto/asymmetric_keys/asym_tpm.c
+++ b/crypto/asymmetric_keys/asym_tpm.c
@@ -7,11 +7,105 @@
7#include <linux/seq_file.h> 7#include <linux/seq_file.h>
8#include <linux/scatterlist.h> 8#include <linux/scatterlist.h>
9#include <linux/tpm.h> 9#include <linux/tpm.h>
10#include <linux/tpm_command.h>
10#include <crypto/akcipher.h> 11#include <crypto/akcipher.h>
12#include <crypto/hash.h>
13#include <crypto/sha.h>
11#include <asm/unaligned.h> 14#include <asm/unaligned.h>
12#include <keys/asymmetric-subtype.h> 15#include <keys/asymmetric-subtype.h>
16#include <keys/trusted.h>
13#include <crypto/asym_tpm_subtype.h> 17#include <crypto/asym_tpm_subtype.h>
14 18
19#define TPM_ORD_FLUSHSPECIFIC 186
20#define TPM_ORD_LOADKEY2 65
21#define TPM_LOADKEY2_SIZE 59
22#define TPM_FLUSHSPECIFIC_SIZE 18
23
24#define TPM_RT_KEY 0x00000001
25
26/*
27 * Load a TPM key from the blob provided by userspace
28 */
29static int tpm_loadkey2(struct tpm_buf *tb,
30 uint32_t keyhandle, unsigned char *keyauth,
31 const unsigned char *keyblob, int keybloblen,
32 uint32_t *newhandle)
33{
34 unsigned char nonceodd[TPM_NONCE_SIZE];
35 unsigned char enonce[TPM_NONCE_SIZE];
36 unsigned char authdata[SHA1_DIGEST_SIZE];
37 uint32_t authhandle = 0;
38 unsigned char cont = 0;
39 uint32_t ordinal;
40 int ret;
41
42 ordinal = htonl(TPM_ORD_LOADKEY2);
43
44 /* session for loading the key */
45 ret = oiap(tb, &authhandle, enonce);
46 if (ret < 0) {
47 pr_info("oiap failed (%d)\n", ret);
48 return ret;
49 }
50
51 /* generate odd nonce */
52 ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE);
53 if (ret < 0) {
54 pr_info("tpm_get_random failed (%d)\n", ret);
55 return ret;
56 }
57
58 /* calculate authorization HMAC value */
59 ret = TSS_authhmac(authdata, keyauth, SHA1_DIGEST_SIZE, enonce,
60 nonceodd, cont, sizeof(uint32_t), &ordinal,
61 keybloblen, keyblob, 0, 0);
62 if (ret < 0)
63 return ret;
64
65 /* build the request buffer */
66 INIT_BUF(tb);
67 store16(tb, TPM_TAG_RQU_AUTH1_COMMAND);
68 store32(tb, TPM_LOADKEY2_SIZE + keybloblen);
69 store32(tb, TPM_ORD_LOADKEY2);
70 store32(tb, keyhandle);
71 storebytes(tb, keyblob, keybloblen);
72 store32(tb, authhandle);
73 storebytes(tb, nonceodd, TPM_NONCE_SIZE);
74 store8(tb, cont);
75 storebytes(tb, authdata, SHA1_DIGEST_SIZE);
76
77 ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
78 if (ret < 0) {
79 pr_info("authhmac failed (%d)\n", ret);
80 return ret;
81 }
82
83 ret = TSS_checkhmac1(tb->data, ordinal, nonceodd, keyauth,
84 SHA1_DIGEST_SIZE, 0, 0);
85 if (ret < 0) {
86 pr_info("TSS_checkhmac1 failed (%d)\n", ret);
87 return ret;
88 }
89
90 *newhandle = LOAD32(tb->data, TPM_DATA_OFFSET);
91 return 0;
92}
93
94/*
95 * Execute the FlushSpecific TPM command
96 */
97static int tpm_flushspecific(struct tpm_buf *tb, uint32_t handle)
98{
99 INIT_BUF(tb);
100 store16(tb, TPM_TAG_RQU_COMMAND);
101 store32(tb, TPM_FLUSHSPECIFIC_SIZE);
102 store32(tb, TPM_ORD_FLUSHSPECIFIC);
103 store32(tb, handle);
104 store32(tb, TPM_RT_KEY);
105
106 return trusted_tpm_send(tb->data, MAX_BUF_SIZE);
107}
108
15/* 109/*
16 * Maximum buffer size for the BER/DER encoded public key. The public key 110 * Maximum buffer size for the BER/DER encoded public key. The public key
17 * is of the form SEQUENCE { INTEGER n, INTEGER e } where n is a maximum 2048 111 * is of the form SEQUENCE { INTEGER n, INTEGER e } where n is a maximum 2048