diff options
author | David Howells <dhowells@redhat.com> | 2014-07-01 11:02:52 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2014-07-09 09:58:37 -0400 |
commit | 4c0b4b1d1ae0cbc86f150e2905a1c3d2a17b7c1e (patch) | |
tree | bbb779c5438a9cef8260569fae85493abf2522eb /crypto/asymmetric_keys | |
parent | 3968280c7699f11e27a21aeafacf50bc86c2ed25 (diff) |
pefile: Parse the "Microsoft individual code signing" data blob
The PKCS#7 certificate should contain a "Microsoft individual code signing"
data blob as its signed content. This blob contains a digest of the signed
content of the PE binary and the OID of the digest algorithm used (typically
SHA256).
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r-- | crypto/asymmetric_keys/Makefile | 9 | ||||
-rw-r--r-- | crypto/asymmetric_keys/mscode.asn1 | 28 | ||||
-rw-r--r-- | crypto/asymmetric_keys/mscode_parser.c | 120 | ||||
-rw-r--r-- | crypto/asymmetric_keys/verify_pefile.c | 7 | ||||
-rw-r--r-- | crypto/asymmetric_keys/verify_pefile.h | 5 |
5 files changed, 168 insertions, 1 deletions
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index 3e4de5297015..e47fcd9ac5e8 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile | |||
@@ -54,4 +54,11 @@ pkcs7_test_key-y := \ | |||
54 | obj-$(CONFIG_SIGNED_PE_FILE_VERIFICATION) += verify_signed_pefile.o | 54 | obj-$(CONFIG_SIGNED_PE_FILE_VERIFICATION) += verify_signed_pefile.o |
55 | 55 | ||
56 | verify_signed_pefile-y := \ | 56 | verify_signed_pefile-y := \ |
57 | verify_pefile.o | 57 | verify_pefile.o \ |
58 | mscode_parser.o \ | ||
59 | mscode-asn1.o | ||
60 | |||
61 | $(obj)/mscode_parser.o: $(obj)/mscode-asn1.h $(obj)/mscode-asn1.h | ||
62 | $(obj)/mscode-asn1.o: $(obj)/mscode-asn1.c $(obj)/mscode-asn1.h | ||
63 | |||
64 | clean-files += mscode-asn1.c mscode-asn1.h | ||
diff --git a/crypto/asymmetric_keys/mscode.asn1 b/crypto/asymmetric_keys/mscode.asn1 new file mode 100644 index 000000000000..6d09ba48c41c --- /dev/null +++ b/crypto/asymmetric_keys/mscode.asn1 | |||
@@ -0,0 +1,28 @@ | |||
1 | --- Microsoft individual code signing data blob parser | ||
2 | --- | ||
3 | --- Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | --- Written by David Howells (dhowells@redhat.com) | ||
5 | --- | ||
6 | --- This program is free software; you can redistribute it and/or | ||
7 | --- modify it under the terms of the GNU General Public Licence | ||
8 | --- as published by the Free Software Foundation; either version | ||
9 | --- 2 of the Licence, or (at your option) any later version. | ||
10 | --- | ||
11 | |||
12 | MSCode ::= SEQUENCE { | ||
13 | type SEQUENCE { | ||
14 | contentType ContentType, | ||
15 | parameters ANY | ||
16 | }, | ||
17 | content SEQUENCE { | ||
18 | digestAlgorithm DigestAlgorithmIdentifier, | ||
19 | digest OCTET STRING ({ mscode_note_digest }) | ||
20 | } | ||
21 | } | ||
22 | |||
23 | ContentType ::= OBJECT IDENTIFIER ({ mscode_note_content_type }) | ||
24 | |||
25 | DigestAlgorithmIdentifier ::= SEQUENCE { | ||
26 | algorithm OBJECT IDENTIFIER ({ mscode_note_digest_algo }), | ||
27 | parameters ANY OPTIONAL | ||
28 | } | ||
diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c new file mode 100644 index 000000000000..09336c32b3d4 --- /dev/null +++ b/crypto/asymmetric_keys/mscode_parser.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* Parse a Microsoft Individual Code Signing blob | ||
2 | * | ||
3 | * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) "MSCODE: "fmt | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/oid_registry.h> | ||
17 | #include <crypto/pkcs7.h> | ||
18 | #include "verify_pefile.h" | ||
19 | #include "mscode-asn1.h" | ||
20 | |||
21 | /* | ||
22 | * Parse a Microsoft Individual Code Signing blob | ||
23 | */ | ||
24 | int mscode_parse(struct pefile_context *ctx) | ||
25 | { | ||
26 | const void *content_data; | ||
27 | size_t data_len; | ||
28 | int ret; | ||
29 | |||
30 | ret = pkcs7_get_content_data(ctx->pkcs7, &content_data, &data_len, 1); | ||
31 | |||
32 | if (ret) { | ||
33 | pr_debug("PKCS#7 message does not contain data\n"); | ||
34 | return ret; | ||
35 | } | ||
36 | |||
37 | pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len), | ||
38 | content_data); | ||
39 | |||
40 | return asn1_ber_decoder(&mscode_decoder, ctx, content_data, data_len); | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * Check the content type OID | ||
45 | */ | ||
46 | int mscode_note_content_type(void *context, size_t hdrlen, | ||
47 | unsigned char tag, | ||
48 | const void *value, size_t vlen) | ||
49 | { | ||
50 | enum OID oid; | ||
51 | |||
52 | oid = look_up_OID(value, vlen); | ||
53 | if (oid == OID__NR) { | ||
54 | char buffer[50]; | ||
55 | |||
56 | sprint_oid(value, vlen, buffer, sizeof(buffer)); | ||
57 | pr_err("Unknown OID: %s\n", buffer); | ||
58 | return -EBADMSG; | ||
59 | } | ||
60 | |||
61 | if (oid != OID_msIndividualSPKeyPurpose) { | ||
62 | pr_err("Unexpected content type OID %u\n", oid); | ||
63 | return -EBADMSG; | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | * Note the digest algorithm OID | ||
71 | */ | ||
72 | int mscode_note_digest_algo(void *context, size_t hdrlen, | ||
73 | unsigned char tag, | ||
74 | const void *value, size_t vlen) | ||
75 | { | ||
76 | struct pefile_context *ctx = context; | ||
77 | char buffer[50]; | ||
78 | enum OID oid; | ||
79 | |||
80 | oid = look_up_OID(value, vlen); | ||
81 | switch (oid) { | ||
82 | case OID_md4: | ||
83 | ctx->digest_algo = HASH_ALGO_MD4; | ||
84 | break; | ||
85 | case OID_md5: | ||
86 | ctx->digest_algo = HASH_ALGO_MD5; | ||
87 | break; | ||
88 | case OID_sha1: | ||
89 | ctx->digest_algo = HASH_ALGO_SHA1; | ||
90 | break; | ||
91 | case OID_sha256: | ||
92 | ctx->digest_algo = HASH_ALGO_SHA256; | ||
93 | break; | ||
94 | |||
95 | case OID__NR: | ||
96 | sprint_oid(value, vlen, buffer, sizeof(buffer)); | ||
97 | pr_err("Unknown OID: %s\n", buffer); | ||
98 | return -EBADMSG; | ||
99 | |||
100 | default: | ||
101 | pr_err("Unsupported content type: %u\n", oid); | ||
102 | return -ENOPKG; | ||
103 | } | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * Note the digest we're guaranteeing with this certificate | ||
110 | */ | ||
111 | int mscode_note_digest(void *context, size_t hdrlen, | ||
112 | unsigned char tag, | ||
113 | const void *value, size_t vlen) | ||
114 | { | ||
115 | struct pefile_context *ctx = context; | ||
116 | |||
117 | ctx->digest = value; | ||
118 | ctx->digest_len = vlen; | ||
119 | return 0; | ||
120 | } | ||
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 13f3b44b5046..b975918e82d2 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c | |||
@@ -245,6 +245,13 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen, | |||
245 | goto error; | 245 | goto error; |
246 | } | 246 | } |
247 | 247 | ||
248 | ret = mscode_parse(&ctx); | ||
249 | if (ret < 0) | ||
250 | goto error; | ||
251 | |||
252 | pr_debug("Digest: %u [%*ph]\n", | ||
253 | ctx.digest_len, ctx.digest_len, ctx.digest); | ||
254 | |||
248 | ret = -ENOANO; // Not yet complete | 255 | ret = -ENOANO; // Not yet complete |
249 | 256 | ||
250 | error: | 257 | error: |
diff --git a/crypto/asymmetric_keys/verify_pefile.h b/crypto/asymmetric_keys/verify_pefile.h index e165d23458d4..55d5f7ebc45a 100644 --- a/crypto/asymmetric_keys/verify_pefile.h +++ b/crypto/asymmetric_keys/verify_pefile.h | |||
@@ -35,3 +35,8 @@ struct pefile_context { | |||
35 | pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) | 35 | pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) |
36 | #define kleave(FMT, ...) \ | 36 | #define kleave(FMT, ...) \ |
37 | pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) | 37 | pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) |
38 | |||
39 | /* | ||
40 | * mscode_parser.c | ||
41 | */ | ||
42 | extern int mscode_parse(struct pefile_context *ctx); | ||