diff options
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r-- | crypto/asymmetric_keys/asym_tpm.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/crypto/asymmetric_keys/asym_tpm.c b/crypto/asymmetric_keys/asym_tpm.c index a38ba375675e..a5a5f913a74f 100644 --- a/crypto/asymmetric_keys/asym_tpm.c +++ b/crypto/asymmetric_keys/asym_tpm.c | |||
@@ -20,9 +20,11 @@ | |||
20 | #define TPM_ORD_FLUSHSPECIFIC 186 | 20 | #define TPM_ORD_FLUSHSPECIFIC 186 |
21 | #define TPM_ORD_LOADKEY2 65 | 21 | #define TPM_ORD_LOADKEY2 65 |
22 | #define TPM_ORD_UNBIND 30 | 22 | #define TPM_ORD_UNBIND 30 |
23 | #define TPM_ORD_SIGN 60 | ||
23 | #define TPM_LOADKEY2_SIZE 59 | 24 | #define TPM_LOADKEY2_SIZE 59 |
24 | #define TPM_FLUSHSPECIFIC_SIZE 18 | 25 | #define TPM_FLUSHSPECIFIC_SIZE 18 |
25 | #define TPM_UNBIND_SIZE 63 | 26 | #define TPM_UNBIND_SIZE 63 |
27 | #define TPM_SIGN_SIZE 63 | ||
26 | 28 | ||
27 | #define TPM_RT_KEY 0x00000001 | 29 | #define TPM_RT_KEY 0x00000001 |
28 | 30 | ||
@@ -190,6 +192,91 @@ static int tpm_unbind(struct tpm_buf *tb, | |||
190 | } | 192 | } |
191 | 193 | ||
192 | /* | 194 | /* |
195 | * Sign a blob provided by userspace (that has had the hash function applied) | ||
196 | * using a specific key handle. The handle is assumed to have been previously | ||
197 | * loaded by e.g. LoadKey2. | ||
198 | * | ||
199 | * Note that the key signature scheme of the used key should be set to | ||
200 | * TPM_SS_RSASSAPKCS1v15_DER. This allows the hashed input to be of any size | ||
201 | * up to key_length_in_bytes - 11 and not be limited to size 20 like the | ||
202 | * TPM_SS_RSASSAPKCS1v15_SHA1 signature scheme. | ||
203 | */ | ||
204 | static int tpm_sign(struct tpm_buf *tb, | ||
205 | uint32_t keyhandle, unsigned char *keyauth, | ||
206 | const unsigned char *blob, uint32_t bloblen, | ||
207 | void *out, uint32_t outlen) | ||
208 | { | ||
209 | unsigned char nonceodd[TPM_NONCE_SIZE]; | ||
210 | unsigned char enonce[TPM_NONCE_SIZE]; | ||
211 | unsigned char authdata[SHA1_DIGEST_SIZE]; | ||
212 | uint32_t authhandle = 0; | ||
213 | unsigned char cont = 0; | ||
214 | uint32_t ordinal; | ||
215 | uint32_t datalen; | ||
216 | int ret; | ||
217 | |||
218 | ordinal = htonl(TPM_ORD_SIGN); | ||
219 | datalen = htonl(bloblen); | ||
220 | |||
221 | /* session for loading the key */ | ||
222 | ret = oiap(tb, &authhandle, enonce); | ||
223 | if (ret < 0) { | ||
224 | pr_info("oiap failed (%d)\n", ret); | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | /* generate odd nonce */ | ||
229 | ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE); | ||
230 | if (ret < 0) { | ||
231 | pr_info("tpm_get_random failed (%d)\n", ret); | ||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | /* calculate authorization HMAC value */ | ||
236 | ret = TSS_authhmac(authdata, keyauth, SHA1_DIGEST_SIZE, enonce, | ||
237 | nonceodd, cont, sizeof(uint32_t), &ordinal, | ||
238 | sizeof(uint32_t), &datalen, | ||
239 | bloblen, blob, 0, 0); | ||
240 | if (ret < 0) | ||
241 | return ret; | ||
242 | |||
243 | /* build the request buffer */ | ||
244 | INIT_BUF(tb); | ||
245 | store16(tb, TPM_TAG_RQU_AUTH1_COMMAND); | ||
246 | store32(tb, TPM_SIGN_SIZE + bloblen); | ||
247 | store32(tb, TPM_ORD_SIGN); | ||
248 | store32(tb, keyhandle); | ||
249 | store32(tb, bloblen); | ||
250 | storebytes(tb, blob, bloblen); | ||
251 | store32(tb, authhandle); | ||
252 | storebytes(tb, nonceodd, TPM_NONCE_SIZE); | ||
253 | store8(tb, cont); | ||
254 | storebytes(tb, authdata, SHA1_DIGEST_SIZE); | ||
255 | |||
256 | ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); | ||
257 | if (ret < 0) { | ||
258 | pr_info("authhmac failed (%d)\n", ret); | ||
259 | return ret; | ||
260 | } | ||
261 | |||
262 | datalen = LOAD32(tb->data, TPM_DATA_OFFSET); | ||
263 | |||
264 | ret = TSS_checkhmac1(tb->data, ordinal, nonceodd, | ||
265 | keyauth, SHA1_DIGEST_SIZE, | ||
266 | sizeof(uint32_t), TPM_DATA_OFFSET, | ||
267 | datalen, TPM_DATA_OFFSET + sizeof(uint32_t), | ||
268 | 0, 0); | ||
269 | if (ret < 0) { | ||
270 | pr_info("TSS_checkhmac1 failed (%d)\n", ret); | ||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | memcpy(out, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), | ||
275 | min(datalen, outlen)); | ||
276 | |||
277 | return datalen; | ||
278 | } | ||
279 | /* | ||
193 | * Maximum buffer size for the BER/DER encoded public key. The public key | 280 | * Maximum buffer size for the BER/DER encoded public key. The public key |
194 | * is of the form SEQUENCE { INTEGER n, INTEGER e } where n is a maximum 2048 | 281 | * is of the form SEQUENCE { INTEGER n, INTEGER e } where n is a maximum 2048 |
195 | * bit key and e is usually 65537 | 282 | * bit key and e is usually 65537 |