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_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
125
126
127
128
129
130
131static int pkcs7_find_key(struct pkcs7_message *pkcs7,
132 struct pkcs7_signed_info *sinfo)
133{
134 struct x509_certificate *x509;
135 unsigned certix = 1;
136
137 kenter("%u", sinfo->index);
138
139 for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) {
140
141
142
143
144
145 if (!asymmetric_key_id_same(x509->id, sinfo->sig->auth_ids[0]))
146 continue;
147 pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
148 sinfo->index, certix);
149
150 if (strcmp(x509->pub->pkey_algo, sinfo->sig->pkey_algo) != 0) {
151 pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
152 sinfo->index);
153 continue;
154 }
155
156 sinfo->signer = x509;
157 return 0;
158 }
159
160
161
162
163 pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n",
164 sinfo->index,
165 sinfo->sig->auth_ids[0]->len, sinfo->sig->auth_ids[0]->data);
166 return 0;
167}
168
169
170
171
172static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
173 struct pkcs7_signed_info *sinfo)
174{
175 struct public_key_signature *sig;
176 struct x509_certificate *x509 = sinfo->signer, *p;
177 struct asymmetric_key_id *auth;
178 int ret;
179
180 kenter("");
181
182 for (p = pkcs7->certs; p; p = p->next)
183 p->seen = false;
184
185 for (;;) {
186 pr_debug("verify %s: %*phN\n",
187 x509->subject,
188 x509->raw_serial_size, x509->raw_serial);
189 x509->seen = true;
190
191 if (x509->blacklisted) {
192
193
194
195 sinfo->blacklisted = true;
196 for (p = sinfo->signer; p != x509; p = p->signer)
197 p->blacklisted = true;
198 pr_debug("- blacklisted\n");
199 return 0;
200 }
201
202 if (x509->unsupported_key)
203 goto unsupported_crypto_in_x509;
204
205 pr_debug("- issuer %s\n", x509->issuer);
206 sig = x509->sig;
207 if (sig->auth_ids[0])
208 pr_debug("- authkeyid.id %*phN\n",
209 sig->auth_ids[0]->len, sig->auth_ids[0]->data);
210 if (sig->auth_ids[1])
211 pr_debug("- authkeyid.skid %*phN\n",
212 sig->auth_ids[1]->len, sig->auth_ids[1]->data);
213
214 if (x509->self_signed) {
215
216
217
218
219
220 if (x509->unsupported_sig)
221 goto unsupported_crypto_in_x509;
222 x509->signer = x509;
223 pr_debug("- self-signed\n");
224 return 0;
225 }
226
227
228
229
230 auth = sig->auth_ids[0];
231 if (auth) {
232 pr_debug("- want %*phN\n", auth->len, auth->data);
233 for (p = pkcs7->certs; p; p = p->next) {
234 pr_debug("- cmp [%u] %*phN\n",
235 p->index, p->id->len, p->id->data);
236 if (asymmetric_key_id_same(p->id, auth))
237 goto found_issuer_check_skid;
238 }
239 } else if (sig->auth_ids[1]) {
240 auth = sig->auth_ids[1];
241 pr_debug("- want %*phN\n", auth->len, auth->data);
242 for (p = pkcs7->certs; p; p = p->next) {
243 if (!p->skid)
244 continue;
245 pr_debug("- cmp [%u] %*phN\n",
246 p->index, p->skid->len, p->skid->data);
247 if (asymmetric_key_id_same(p->skid, auth))
248 goto found_issuer;
249 }
250 }
251
252
253 pr_debug("- top\n");
254 return 0;
255
256 found_issuer_check_skid:
257
258
259
260 if (sig->auth_ids[1] &&
261 !asymmetric_key_id_same(p->skid, sig->auth_ids[1])) {
262 pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n",
263 sinfo->index, x509->index, p->index);
264 return -EKEYREJECTED;
265 }
266 found_issuer:
267 pr_debug("- subject %s\n", p->subject);
268 if (p->seen) {
269 pr_warn("Sig %u: X.509 chain contains loop\n",
270 sinfo->index);
271 return 0;
272 }
273 ret = public_key_verify_signature(p->pub, x509->sig);
274 if (ret < 0)
275 return ret;
276 x509->signer = p;
277 if (x509 == p) {
278 pr_debug("- self-signed\n");
279 return 0;
280 }
281 x509 = p;
282 might_sleep();
283 }
284
285unsupported_crypto_in_x509:
286
287
288
289
290
291
292 return 0;
293}
294
295
296
297
298static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
299 struct pkcs7_signed_info *sinfo)
300{
301 int ret;
302
303 kenter(",%u", sinfo->index);
304
305
306
307
308 ret = pkcs7_digest(pkcs7, sinfo);
309 if (ret < 0)
310 return ret;
311
312
313 ret = pkcs7_find_key(pkcs7, sinfo);
314 if (ret < 0)
315 return ret;
316
317 if (!sinfo->signer)
318 return 0;
319
320 pr_devel("Using X.509[%u] for sig %u\n",
321 sinfo->signer->index, sinfo->index);
322
323
324
325
326
327 if (test_bit(sinfo_has_signing_time, &sinfo->aa_set)) {
328 if (sinfo->signing_time < sinfo->signer->valid_from ||
329 sinfo->signing_time > sinfo->signer->valid_to) {
330 pr_warn("Message signed outside of X.509 validity window\n");
331 return -EKEYREJECTED;
332 }
333 }
334
335
336 ret = public_key_verify_signature(sinfo->signer->pub, sinfo->sig);
337 if (ret < 0)
338 return ret;
339
340 pr_devel("Verified signature %u\n", sinfo->index);
341
342
343 return pkcs7_verify_sig_chain(pkcs7, sinfo);
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
371
372
373
374
375
376int pkcs7_verify(struct pkcs7_message *pkcs7,
377 enum key_being_used_for usage)
378{
379 struct pkcs7_signed_info *sinfo;
380 int actual_ret = -ENOPKG;
381 int ret;
382
383 kenter("");
384
385 switch (usage) {
386 case VERIFYING_MODULE_SIGNATURE:
387 if (pkcs7->data_type != OID_data) {
388 pr_warn("Invalid module sig (not pkcs7-data)\n");
389 return -EKEYREJECTED;
390 }
391 if (pkcs7->have_authattrs) {
392 pr_warn("Invalid module sig (has authattrs)\n");
393 return -EKEYREJECTED;
394 }
395 break;
396 case VERIFYING_FIRMWARE_SIGNATURE:
397 if (pkcs7->data_type != OID_data) {
398 pr_warn("Invalid firmware sig (not pkcs7-data)\n");
399 return -EKEYREJECTED;
400 }
401 if (!pkcs7->have_authattrs) {
402 pr_warn("Invalid firmware sig (missing authattrs)\n");
403 return -EKEYREJECTED;
404 }
405 break;
406 case VERIFYING_KEXEC_PE_SIGNATURE:
407 if (pkcs7->data_type != OID_msIndirectData) {
408 pr_warn("Invalid kexec sig (not Authenticode)\n");
409 return -EKEYREJECTED;
410 }
411
412 break;
413 case VERIFYING_UNSPECIFIED_SIGNATURE:
414 if (pkcs7->data_type != OID_data) {
415 pr_warn("Invalid unspecified sig (not pkcs7-data)\n");
416 return -EKEYREJECTED;
417 }
418 break;
419 default:
420 return -EINVAL;
421 }
422
423 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
424 ret = pkcs7_verify_one(pkcs7, sinfo);
425 if (sinfo->blacklisted) {
426 if (actual_ret == -ENOPKG)
427 actual_ret = -EKEYREJECTED;
428 continue;
429 }
430 if (ret < 0) {
431 if (ret == -ENOPKG) {
432 sinfo->unsupported_crypto = true;
433 continue;
434 }
435 kleave(" = %d", ret);
436 return ret;
437 }
438 actual_ret = 0;
439 }
440
441 kleave(" = %d", actual_ret);
442 return actual_ret;
443}
444EXPORT_SYMBOL_GPL(pkcs7_verify);
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
460 const void *data, size_t datalen)
461{
462 if (pkcs7->data) {
463 pr_debug("Data already supplied\n");
464 return -EINVAL;
465 }
466 pkcs7->data = data;
467 pkcs7->data_len = datalen;
468 return 0;
469}
470