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