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