Commit | Line | Data |
---|---|---|
d5e72745 DK |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #define pr_fmt(fmt) "TPM-PARSER: "fmt | |
3 | #include <linux/module.h> | |
4 | #include <linux/kernel.h> | |
5 | #include <linux/export.h> | |
6 | #include <linux/slab.h> | |
7 | #include <linux/err.h> | |
8 | #include <keys/asymmetric-subtype.h> | |
9 | #include <keys/asymmetric-parser.h> | |
10 | #include <crypto/asym_tpm_subtype.h> | |
11 | #include "tpm.asn1.h" | |
12 | ||
13 | struct tpm_parse_context { | |
14 | const void *blob; | |
15 | u32 blob_len; | |
16 | }; | |
17 | ||
18 | /* | |
19 | * Note the key data of the ASN.1 blob. | |
20 | */ | |
21 | int tpm_note_key(void *context, size_t hdrlen, | |
22 | unsigned char tag, | |
23 | const void *value, size_t vlen) | |
24 | { | |
25 | struct tpm_parse_context *ctx = context; | |
26 | ||
27 | ctx->blob = value; | |
28 | ctx->blob_len = vlen; | |
29 | ||
30 | return 0; | |
31 | } | |
32 | ||
33 | /* | |
34 | * Parse a TPM-encrypted private key blob. | |
35 | */ | |
36 | static struct tpm_key *tpm_parse(const void *data, size_t datalen) | |
37 | { | |
38 | struct tpm_parse_context ctx; | |
39 | long ret; | |
40 | ||
41 | memset(&ctx, 0, sizeof(ctx)); | |
42 | ||
43 | /* Attempt to decode the private key */ | |
44 | ret = asn1_ber_decoder(&tpm_decoder, &ctx, data, datalen); | |
45 | if (ret < 0) | |
46 | goto error; | |
47 | ||
48 | return tpm_key_create(ctx.blob, ctx.blob_len); | |
49 | ||
50 | error: | |
51 | return ERR_PTR(ret); | |
52 | } | |
53 | /* | |
54 | * Attempt to parse a data blob for a key as a TPM private key blob. | |
55 | */ | |
56 | static int tpm_key_preparse(struct key_preparsed_payload *prep) | |
57 | { | |
58 | struct tpm_key *tk; | |
59 | ||
60 | /* | |
61 | * TPM 1.2 keys are max 2048 bits long, so assume the blob is no | |
62 | * more than 4x that | |
63 | */ | |
64 | if (prep->datalen > 256 * 4) | |
65 | return -EMSGSIZE; | |
66 | ||
67 | tk = tpm_parse(prep->data, prep->datalen); | |
68 | ||
69 | if (IS_ERR(tk)) | |
70 | return PTR_ERR(tk); | |
71 | ||
72 | /* We're pinning the module by being linked against it */ | |
73 | __module_get(asym_tpm_subtype.owner); | |
74 | prep->payload.data[asym_subtype] = &asym_tpm_subtype; | |
75 | prep->payload.data[asym_key_ids] = NULL; | |
76 | prep->payload.data[asym_crypto] = tk; | |
77 | prep->payload.data[asym_auth] = NULL; | |
78 | prep->quotalen = 100; | |
79 | return 0; | |
80 | } | |
81 | ||
82 | static struct asymmetric_key_parser tpm_key_parser = { | |
83 | .owner = THIS_MODULE, | |
84 | .name = "tpm_parser", | |
85 | .parse = tpm_key_preparse, | |
86 | }; | |
87 | ||
88 | static int __init tpm_key_init(void) | |
89 | { | |
90 | return register_asymmetric_key_parser(&tpm_key_parser); | |
91 | } | |
92 | ||
93 | static void __exit tpm_key_exit(void) | |
94 | { | |
95 | unregister_asymmetric_key_parser(&tpm_key_parser); | |
96 | } | |
97 | ||
98 | module_init(tpm_key_init); | |
99 | module_exit(tpm_key_exit); | |
100 | ||
101 | MODULE_DESCRIPTION("TPM private key-blob parser"); | |
102 | MODULE_LICENSE("GPL v2"); |