diff options
-rw-r--r-- | crypto/asymmetric_keys/verify_pefile.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index aec7c509404e..2f5268cb843d 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/pe.h> | 17 | #include <linux/pe.h> |
18 | #include <linux/asn1.h> | ||
18 | #include <crypto/pkcs7.h> | 19 | #include <crypto/pkcs7.h> |
19 | #include <crypto/hash.h> | 20 | #include <crypto/hash.h> |
20 | #include "verify_pefile.h" | 21 | #include "verify_pefile.h" |
@@ -118,6 +119,72 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen, | |||
118 | return 0; | 119 | return 0; |
119 | } | 120 | } |
120 | 121 | ||
122 | /* | ||
123 | * Check and strip the PE wrapper from around the signature and check that the | ||
124 | * remnant looks something like PKCS#7. | ||
125 | */ | ||
126 | static int pefile_strip_sig_wrapper(const void *pebuf, | ||
127 | struct pefile_context *ctx) | ||
128 | { | ||
129 | struct win_certificate wrapper; | ||
130 | const u8 *pkcs7; | ||
131 | |||
132 | if (ctx->sig_len < sizeof(wrapper)) { | ||
133 | pr_debug("Signature wrapper too short\n"); | ||
134 | return -ELIBBAD; | ||
135 | } | ||
136 | |||
137 | memcpy(&wrapper, pebuf + ctx->sig_offset, sizeof(wrapper)); | ||
138 | pr_debug("sig wrapper = { %x, %x, %x }\n", | ||
139 | wrapper.length, wrapper.revision, wrapper.cert_type); | ||
140 | |||
141 | /* Both pesign and sbsign round up the length of certificate table | ||
142 | * (in optional header data directories) to 8 byte alignment. | ||
143 | */ | ||
144 | if (round_up(wrapper.length, 8) != ctx->sig_len) { | ||
145 | pr_debug("Signature wrapper len wrong\n"); | ||
146 | return -ELIBBAD; | ||
147 | } | ||
148 | if (wrapper.revision != WIN_CERT_REVISION_2_0) { | ||
149 | pr_debug("Signature is not revision 2.0\n"); | ||
150 | return -ENOTSUPP; | ||
151 | } | ||
152 | if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) { | ||
153 | pr_debug("Signature certificate type is not PKCS\n"); | ||
154 | return -ENOTSUPP; | ||
155 | } | ||
156 | |||
157 | /* Looks like actual pkcs signature length is in wrapper->length. | ||
158 | * size obtained from data dir entries lists the total size of | ||
159 | * certificate table which is also aligned to octawrod boundary. | ||
160 | * | ||
161 | * So set signature length field appropriately. | ||
162 | */ | ||
163 | ctx->sig_len = wrapper.length; | ||
164 | ctx->sig_offset += sizeof(wrapper); | ||
165 | ctx->sig_len -= sizeof(wrapper); | ||
166 | if (ctx->sig_len == 0) { | ||
167 | pr_debug("Signature data missing\n"); | ||
168 | return -EKEYREJECTED; | ||
169 | } | ||
170 | |||
171 | /* What's left should a PKCS#7 cert */ | ||
172 | pkcs7 = pebuf + ctx->sig_offset; | ||
173 | if (pkcs7[0] == (ASN1_CONS_BIT | ASN1_SEQ)) { | ||
174 | if (pkcs7[1] == 0x82 && | ||
175 | pkcs7[2] == (((ctx->sig_len - 4) >> 8) & 0xff) && | ||
176 | pkcs7[3] == ((ctx->sig_len - 4) & 0xff)) | ||
177 | return 0; | ||
178 | if (pkcs7[1] == 0x80) | ||
179 | return 0; | ||
180 | if (pkcs7[1] > 0x82) | ||
181 | return -EMSGSIZE; | ||
182 | } | ||
183 | |||
184 | pr_debug("Signature data not PKCS#7\n"); | ||
185 | return -ELIBBAD; | ||
186 | } | ||
187 | |||
121 | /** | 188 | /** |
122 | * verify_pefile_signature - Verify the signature on a PE binary image | 189 | * verify_pefile_signature - Verify the signature on a PE binary image |
123 | * @pebuf: Buffer containing the PE binary image | 190 | * @pebuf: Buffer containing the PE binary image |
@@ -159,5 +226,9 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen, | |||
159 | if (ret < 0) | 226 | if (ret < 0) |
160 | return ret; | 227 | return ret; |
161 | 228 | ||
229 | ret = pefile_strip_sig_wrapper(pebuf, &ctx); | ||
230 | if (ret < 0) | ||
231 | return ret; | ||
232 | |||
162 | return -ENOANO; // Not yet complete | 233 | return -ENOANO; // Not yet complete |
163 | } | 234 | } |