diff options
author | Denis Kenzior <denkenz@gmail.com> | 2018-10-09 12:48:10 -0400 |
---|---|---|
committer | James Morris <james.morris@microsoft.com> | 2018-10-26 04:30:46 -0400 |
commit | f8c54e1ac4b82933dfcf88c37892da8ae35ccbe4 (patch) | |
tree | 9f11437c13e8e27429e009ab8d0481b07196d15c /crypto/asymmetric_keys | |
parent | 903be6bb84c544551150a6f5aab9fda1ed9a6895 (diff) |
KEYS: asym_tpm: extract key size & public key [ver #2]
The parsed BER/DER blob obtained from user space contains a TPM_Key
structure. This structure has some information about the key as well as
the public key portion.
This patch extracts this information for future use.
Signed-off-by: Denis Kenzior <denkenz@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Marcel Holtmann <marcel@holtmann.org>
Reviewed-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: James Morris <james.morris@microsoft.com>
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r-- | crypto/asymmetric_keys/asym_tpm.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/crypto/asymmetric_keys/asym_tpm.c b/crypto/asymmetric_keys/asym_tpm.c index d0b2b97e8e54..308c51e055a4 100644 --- a/crypto/asymmetric_keys/asym_tpm.c +++ b/crypto/asymmetric_keys/asym_tpm.c | |||
@@ -7,6 +7,7 @@ | |||
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 <asm/unaligned.h> | ||
10 | #include <keys/asymmetric-subtype.h> | 11 | #include <keys/asymmetric-subtype.h> |
11 | #include <crypto/asym_tpm_subtype.h> | 12 | #include <crypto/asym_tpm_subtype.h> |
12 | 13 | ||
@@ -37,6 +38,110 @@ static void asym_tpm_destroy(void *payload0, void *payload3) | |||
37 | kfree(tk); | 38 | kfree(tk); |
38 | } | 39 | } |
39 | 40 | ||
41 | /* | ||
42 | * Parse enough information out of TPM_KEY structure: | ||
43 | * TPM_STRUCT_VER -> 4 bytes | ||
44 | * TPM_KEY_USAGE -> 2 bytes | ||
45 | * TPM_KEY_FLAGS -> 4 bytes | ||
46 | * TPM_AUTH_DATA_USAGE -> 1 byte | ||
47 | * TPM_KEY_PARMS -> variable | ||
48 | * UINT32 PCRInfoSize -> 4 bytes | ||
49 | * BYTE* -> PCRInfoSize bytes | ||
50 | * TPM_STORE_PUBKEY | ||
51 | * UINT32 encDataSize; | ||
52 | * BYTE* -> encDataSize; | ||
53 | * | ||
54 | * TPM_KEY_PARMS: | ||
55 | * TPM_ALGORITHM_ID -> 4 bytes | ||
56 | * TPM_ENC_SCHEME -> 2 bytes | ||
57 | * TPM_SIG_SCHEME -> 2 bytes | ||
58 | * UINT32 parmSize -> 4 bytes | ||
59 | * BYTE* -> variable | ||
60 | */ | ||
61 | static int extract_key_parameters(struct tpm_key *tk) | ||
62 | { | ||
63 | const void *cur = tk->blob; | ||
64 | uint32_t len = tk->blob_len; | ||
65 | const void *pub_key; | ||
66 | uint32_t sz; | ||
67 | uint32_t key_len; | ||
68 | |||
69 | if (len < 11) | ||
70 | return -EBADMSG; | ||
71 | |||
72 | /* Ensure this is a legacy key */ | ||
73 | if (get_unaligned_be16(cur + 4) != 0x0015) | ||
74 | return -EBADMSG; | ||
75 | |||
76 | /* Skip to TPM_KEY_PARMS */ | ||
77 | cur += 11; | ||
78 | len -= 11; | ||
79 | |||
80 | if (len < 12) | ||
81 | return -EBADMSG; | ||
82 | |||
83 | /* Make sure this is an RSA key */ | ||
84 | if (get_unaligned_be32(cur) != 0x00000001) | ||
85 | return -EBADMSG; | ||
86 | |||
87 | /* Make sure this is TPM_ES_RSAESPKCSv15 encoding scheme */ | ||
88 | if (get_unaligned_be16(cur + 4) != 0x0002) | ||
89 | return -EBADMSG; | ||
90 | |||
91 | /* Make sure this is TPM_SS_RSASSAPKCS1v15_DER signature scheme */ | ||
92 | if (get_unaligned_be16(cur + 6) != 0x0003) | ||
93 | return -EBADMSG; | ||
94 | |||
95 | sz = get_unaligned_be32(cur + 8); | ||
96 | if (len < sz + 12) | ||
97 | return -EBADMSG; | ||
98 | |||
99 | /* Move to TPM_RSA_KEY_PARMS */ | ||
100 | len -= 12; | ||
101 | cur += 12; | ||
102 | |||
103 | /* Grab the RSA key length */ | ||
104 | key_len = get_unaligned_be32(cur); | ||
105 | |||
106 | switch (key_len) { | ||
107 | case 512: | ||
108 | case 1024: | ||
109 | case 1536: | ||
110 | case 2048: | ||
111 | break; | ||
112 | default: | ||
113 | return -EINVAL; | ||
114 | } | ||
115 | |||
116 | /* Move just past TPM_KEY_PARMS */ | ||
117 | cur += sz; | ||
118 | len -= sz; | ||
119 | |||
120 | if (len < 4) | ||
121 | return -EBADMSG; | ||
122 | |||
123 | sz = get_unaligned_be32(cur); | ||
124 | if (len < 4 + sz) | ||
125 | return -EBADMSG; | ||
126 | |||
127 | /* Move to TPM_STORE_PUBKEY */ | ||
128 | cur += 4 + sz; | ||
129 | len -= 4 + sz; | ||
130 | |||
131 | /* Grab the size of the public key, it should jive with the key size */ | ||
132 | sz = get_unaligned_be32(cur); | ||
133 | if (sz > 256) | ||
134 | return -EINVAL; | ||
135 | |||
136 | pub_key = cur + 4; | ||
137 | |||
138 | tk->key_len = key_len; | ||
139 | tk->pub_key = pub_key; | ||
140 | tk->pub_key_len = sz; | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
40 | /* Given the blob, parse it and load it into the TPM */ | 145 | /* Given the blob, parse it and load it into the TPM */ |
41 | struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len) | 146 | struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len) |
42 | { | 147 | { |
@@ -64,8 +169,15 @@ struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len) | |||
64 | 169 | ||
65 | tk->blob_len = blob_len; | 170 | tk->blob_len = blob_len; |
66 | 171 | ||
172 | r = extract_key_parameters(tk); | ||
173 | if (r < 0) | ||
174 | goto error_extract; | ||
175 | |||
67 | return tk; | 176 | return tk; |
68 | 177 | ||
178 | error_extract: | ||
179 | kfree(tk->blob); | ||
180 | tk->blob_len = 0; | ||
69 | error_memdup: | 181 | error_memdup: |
70 | kfree(tk); | 182 | kfree(tk); |
71 | error: | 183 | error: |