1
2
3
4
5
6
7
8
9
10
11
12#define pr_fmt(fmt) "PKCS7: "fmt
13#include <linux/kernel.h>
14#include <linux/export.h>
15#include <linux/slab.h>
16#include <linux/err.h>
17#include <linux/asn1.h>
18#include <crypto/hash.h>
19#include <crypto/public_key.h>
20#include "pkcs7_parser.h"
21
22
23
24
25static int pkcs7_digest(struct pkcs7_message *pkcs7,
26 struct pkcs7_signed_info *sinfo)
27{
28 struct public_key_signature *sig = sinfo->sig;
29 struct crypto_shash *tfm;
30 struct shash_desc *desc;
31 size_t desc_size;
32 int ret;
33
34 kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo);
35
36 if (!sinfo->sig->hash_algo)
37 return -ENOPKG;
38
39
40
41
42 tfm = crypto_alloc_shash(sinfo->sig->hash_algo, 0, 0);
43 if (IS_ERR(tfm))
44 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
45
46 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
47 sig->digest_size = crypto_shash_digestsize(tfm);
48
49 ret = -ENOMEM;
50 sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
51 if (!sig->digest)
52 goto error_no_desc;
53
54 desc = kzalloc(desc_size, GFP_KERNEL);
55 if (!desc)
56 goto error_no_desc;
57
58 desc->tfm = tfm;
59 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
60
61
62 ret = crypto_shash_init(desc);
63 if (ret < 0)
64 goto error;
65 ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len,
66 sig->digest);
67 if (ret < 0)
68 goto error;
69 pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest);
70
71
72
73
74
75 if (sinfo->authattrs) {
76 u8 tag;
77
78 if (!sinfo->msgdigest) {
79 pr_warn("Sig %u: No messageDigest\n", sinfo->index);
80 ret = -EKEYREJECTED;
81 goto error;
82 }
83
84 if (sinfo->msgdigest_len != sig->digest_size) {
85 pr_debug("Sig %u: Invalid digest size (%u)\n",
86 sinfo->index, sinfo->msgdigest_len);
87 ret = -EBADMSG;
88 goto error;
89 }
90
91 if (memcmp(sig->digest, sinfo->msgdigest,
92 sinfo->msgdigest_len) != 0) {
93 pr_debug("Sig %u: Message digest doesn't match\n",
94 sinfo->index);
95 ret = -EKEYREJECTED;
96 goto error;
97 }
98
99
100
101
102
103
104 memset(sig->digest, 0, sig->digest_size);
105
106 ret = crypto_shash_init(desc);
107 if (ret < 0)
108 goto error;
109 tag = ASN1_CONS_BIT | ASN1_SET;
110 ret = crypto_shash_update(desc, &tag, 1);
111 if (ret < 0)
112 goto error;
113 ret = crypto_shash_finup(desc, sinfo->authattrs,
114 sinfo->authattrs_len, sig->digest);
115 if (ret < 0)
116 goto error;
117 pr_devel("AADigest = [%*ph]\n", 8, sig->digest);
118 }
119
120error:
121 kfree(desc);
122error_no_desc:
123 crypto_free_shash(tfm);
124 kleave(" = %d", ret);
125 return ret;
126}
127
128
129
130
131
132
133
134static int pkcs7_find_key(struct pkcs7_message *pkcs7,
135 struct pkcs7_signed_info *sinfo)
136{
137 struct x509_certificate *x509;
138 unsigned certix = 1;
139
140 kenter("%u", sinfo->index);
141
142 for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) {
143
144
145
146
147
148 if (!asymmetric_key_id_same(x509->id, sinfo->sig->auth_ids[0]))
149 continue;
150 pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
151 sinfo->index, certix);
152
153 if (x509->pub->pkey_algo != sinfo->sig->pkey_algo) {
154 pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
155 sinfo->index);
156 continue;
157 }
158
159 sinfo->signer = x509;
160 return 0;
161 }
162
163
164
165
166 pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n",
167 sinfo->index,
168 sinfo->sig->auth_ids[0]->len, sinfo->sig->auth_ids[0]->data);
169 return 0;
170}
171
172
173
174
175static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
176 struct pkcs7_signed_info *sinfo)
177{
178 struct public_key_signature *sig;
179 struct x509_certificate *x509 = sinfo->signer, *p;
180 struct asymmetric_key_id *auth;
181 int ret;
182
183 kenter("");
184
185 for (p = pkcs7->certs; p; p = p->next)
186 p->seen = false;
187
188 for (;;) {
189 pr_debug("verify %s: %*phN\n",
190 x509->subject,
191 x509->raw_serial_size, x509->raw_serial);
192 x509->seen = true;
193 if (x509->unsupported_key)
194 goto unsupported_crypto_in_x509;
195
196 pr_debug("- issuer %s\n", x509->issuer);
197 sig = x509->sig;
198 if (sig->auth_ids[0])
199 pr_debug("- authkeyid.id %*phN\n",
200 sig->auth_ids[0]->len, sig->auth_ids[0]->data);
201 if (sig->auth_ids[1])
202 pr_debug("- authkeyid.skid %*phN\n",
203 sig->auth_ids[1]->len, sig->auth_ids[1]->data);
204
205 if (x509->self_signed) {
206
207
208
209
210
211 if (x509->unsupported_sig)
212 goto unsupported_crypto_in_x509;
213 x509->signer = x509;
214 pr_debug("- self-signed\n");
215 return 0;
216 }
217
218
219
220
221 auth = sig->auth_ids[0];
222 if (auth) {
223 pr_debug("- want %*phN\n", auth->len, auth->data);
224 for (p = pkcs7->certs; p; p = p->next) {
225 pr_debug("- cmp [%u] %*phN\n",
226 p->index, p->id->len, p->id->data);
227 if (asymmetric_key_id_same(p->id, auth))
228 goto found_issuer_check_skid;
229 }
230 } else if (sig->auth_ids[1]) {
231 auth = sig->auth_ids[1];
232 pr_debug("- want %*phN\n", auth->len, auth->data);
233 for (p = pkcs7->certs; p; p = p->next) {
234 if (!p->skid)
235 continue;
236 pr_debug("- cmp [%u] %*phN\n",
237 p->index, p->skid->len, p->skid->data);
238 if (asymmetric_key_id_same(p->skid, auth))
239 goto found_issuer;
240 }
241 }
242
243
244 pr_debug("- top\n");
245 return 0;
246
247 found_issuer_check_skid:
248
249
250
251 if (sig->auth_ids[1] &&
252 !asymmetric_key_id_same(p->skid, sig->auth_ids[1])) {
253 pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n",
254 sinfo->index, x509->index, p->index);
255 return -EKEYREJECTED;
256 }
257 found_issuer:
258 pr_debug("- subject %s\n", p->subject);
259 if (p->seen) {
260 pr_warn("Sig %u: X.509 chain contains loop\n",
261 sinfo->index);
262 return 0;
263 }
264 ret = public_key_verify_signature(p->pub, p->sig);
265 if (ret < 0)
266 return ret;
267 x509->signer = p;
268 if (x509 == p) {
269 pr_debug("- self-signed\n");
270 return 0;
271 }
272 x509 = p;
273 might_sleep();
274 }
275
276unsupported_crypto_in_x509:
277
278
279
280
281
282
283 return 0;
284}
285
286
287
288
289static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
290 struct pkcs7_signed_info *sinfo)
291{
292 int ret;
293
294 kenter(",%u", sinfo->index);
295
296
297
298
299 ret = pkcs7_digest(pkcs7, sinfo);
300 if (ret < 0)
301 return ret;
302
303
304 ret = pkcs7_find_key(pkcs7, sinfo);
305 if (ret < 0)
306 return ret;
307
308 if (!sinfo->signer)
309 return 0;
310
311 pr_devel("Using X.509[%u] for sig %u\n",
312 sinfo->signer->index, sinfo->index);
313
314
315
316
317
318 if (test_bit(sinfo_has_signing_time, &sinfo->aa_set)) {
319 if (sinfo->signing_time < sinfo->signer->valid_from ||
320 sinfo->signing_time > sinfo->signer->valid_to) {
321 pr_warn("Message signed outside of X.509 validity window\n");
322 return -EKEYREJECTED;
323 }
324 }
325
326
327 ret = public_key_verify_signature(sinfo->signer->pub, sinfo->sig);
328 if (ret < 0)
329 return ret;
330
331 pr_devel("Verified signature %u\n", sinfo->index);
332
333
334 return pkcs7_verify_sig_chain(pkcs7, sinfo);
335}
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366int pkcs7_verify(struct pkcs7_message *pkcs7,
367 enum key_being_used_for usage)
368{
369 struct pkcs7_signed_info *sinfo;
370 int enopkg = -ENOPKG;
371 int ret;
372
373 kenter("");
374
375 switch (usage) {
376 case VERIFYING_MODULE_SIGNATURE:
377 if (pkcs7->data_type != OID_data) {
378 pr_warn("Invalid module sig (not pkcs7-data)\n");
379 return -EKEYREJECTED;
380 }
381 if (pkcs7->have_authattrs) {
382 pr_warn("Invalid module sig (has authattrs)\n");
383 return -EKEYREJECTED;
384 }
385 break;
386 case VERIFYING_FIRMWARE_SIGNATURE:
387 if (pkcs7->data_type != OID_data) {
388 pr_warn("Invalid firmware sig (not pkcs7-data)\n");
389 return -EKEYREJECTED;
390 }
391 if (!pkcs7->have_authattrs) {
392 pr_warn("Invalid firmware sig (missing authattrs)\n");
393 return -EKEYREJECTED;
394 }
395 break;
396 case VERIFYING_KEXEC_PE_SIGNATURE:
397 if (pkcs7->data_type != OID_msIndirectData) {
398 pr_warn("Invalid kexec sig (not Authenticode)\n");
399 return -EKEYREJECTED;
400 }
401
402 break;
403 case VERIFYING_UNSPECIFIED_SIGNATURE:
404 if (pkcs7->data_type != OID_data) {
405 pr_warn("Invalid unspecified sig (not pkcs7-data)\n");
406 return -EKEYREJECTED;
407 }
408 break;
409 default:
410 return -EINVAL;
411 }
412
413 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
414 ret = pkcs7_verify_one(pkcs7, sinfo);
415 if (ret < 0) {
416 if (ret == -ENOPKG) {
417 sinfo->unsupported_crypto = true;
418 continue;
419 }
420 kleave(" = %d", ret);
421 return ret;
422 }
423 enopkg = 0;
424 }
425
426 kleave(" = %d", enopkg);
427 return enopkg;
428}
429EXPORT_SYMBOL_GPL(pkcs7_verify);
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
445 const void *data, size_t datalen)
446{
447 if (pkcs7->data) {
448 pr_debug("Data already supplied\n");
449 return -EINVAL;
450 }
451 pkcs7->data = data;
452 pkcs7->data_len = datalen;
453 return 0;
454}
455