blob: fc0314e6d48c03f7cd98c501c951caac78a6396a [file] [log] [blame]
AKASHI Takahiro593e17d2020-04-14 11:51:39 +09001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se>
4 * Copyright (c) 2019 Linaro Limited, Author: AKASHI Takahiro
5 */
6
7#include <common.h>
8#include <charset.h>
9#include <efi_loader.h>
10#include <image.h>
11#include <hexdump.h>
12#include <malloc.h>
AKASHI Takahiroe3f5c9c2020-04-21 09:38:17 +090013#include <crypto/pkcs7_parser.h>
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090014#include <linux/compat.h>
15#include <linux/oid_registry.h>
16#include <u-boot/rsa.h>
17#include <u-boot/sha256.h>
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090018
19const efi_guid_t efi_guid_image_security_database =
20 EFI_IMAGE_SECURITY_DATABASE_GUID;
21const efi_guid_t efi_guid_sha256 = EFI_CERT_SHA256_GUID;
22const efi_guid_t efi_guid_cert_rsa2048 = EFI_CERT_RSA2048_GUID;
23const efi_guid_t efi_guid_cert_x509 = EFI_CERT_X509_GUID;
24const efi_guid_t efi_guid_cert_x509_sha256 = EFI_CERT_X509_SHA256_GUID;
AKASHI Takahiroa4292ec2020-05-29 15:41:18 +090025const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090026
27#ifdef CONFIG_EFI_SECURE_BOOT
28
29/**
30 * efi_hash_regions - calculate a hash value
AKASHI Takahiro1e64d0b2020-07-08 14:01:55 +090031 * @regs: Array of regions
32 * @count: Number of regions
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090033 * @hash: Pointer to a pointer to buffer holding a hash value
34 * @size: Size of buffer to be returned
35 *
36 * Calculate a sha256 value of @regs and return a value in @hash.
37 *
38 * Return: true on success, false on error
39 */
AKASHI Takahiro1e64d0b2020-07-08 14:01:55 +090040static bool efi_hash_regions(struct image_region *regs, int count,
41 void **hash, size_t *size)
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090042{
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090043 if (!*hash) {
AKASHI Takahiro1e64d0b2020-07-08 14:01:55 +090044 *hash = calloc(1, SHA256_SUM_LEN);
45 if (!*hash) {
46 EFI_PRINT("Out of memory\n");
47 return false;
48 }
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090049 }
AKASHI Takahiro1e64d0b2020-07-08 14:01:55 +090050 if (size)
51 *size = SHA256_SUM_LEN;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090052
AKASHI Takahiro1e64d0b2020-07-08 14:01:55 +090053 hash_calculate("sha256", regs, count, *hash);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090054#ifdef DEBUG
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +090055 EFI_PRINT("hash calculated:\n");
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090056 print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
57 *hash, SHA256_SUM_LEN, false);
58#endif
59
60 return true;
61}
62
63/**
64 * efi_hash_msg_content - calculate a hash value of contentInfo
65 * @msg: Signature
66 * @hash: Pointer to a pointer to buffer holding a hash value
67 * @size: Size of buffer to be returned
68 *
69 * Calculate a sha256 value of contentInfo in @msg and return a value in @hash.
70 *
71 * Return: true on success, false on error
72 */
73static bool efi_hash_msg_content(struct pkcs7_message *msg, void **hash,
74 size_t *size)
75{
76 struct image_region regtmp;
77
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090078 regtmp.data = msg->data;
79 regtmp.size = msg->data_len;
80
AKASHI Takahiro1e64d0b2020-07-08 14:01:55 +090081 return efi_hash_regions(&regtmp, 1, hash, size);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +090082}
83
84/**
85 * efi_signature_verify - verify a signature with a certificate
86 * @regs: List of regions to be authenticated
87 * @signed_info: Pointer to PKCS7's signed_info
88 * @cert: x509 certificate
89 *
90 * Signature pointed to by @signed_info against image pointed to by @regs
91 * is verified by a certificate pointed to by @cert.
92 * @signed_info holds a signature, including a message digest which is to be
93 * compared with a hash value calculated from @regs.
94 *
95 * Return: true if signature is verified, false if not
96 */
97static bool efi_signature_verify(struct efi_image_regions *regs,
98 struct pkcs7_message *msg,
99 struct pkcs7_signed_info *ps_info,
100 struct x509_certificate *cert)
101{
102 struct image_sign_info info;
103 struct image_region regtmp[2];
104 void *hash;
105 size_t size;
106 char c;
107 bool verified;
108
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900109 EFI_PRINT("%s: Enter, %p, %p, %p(issuer: %s, subject: %s)\n", __func__,
110 regs, ps_info, cert, cert->issuer, cert->subject);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900111
112 verified = false;
113
114 memset(&info, '\0', sizeof(info));
115 info.padding = image_get_padding_algo("pkcs-1.5");
116 /*
117 * Note: image_get_[checksum|crypto]_algo takes an string
118 * argument like "<checksum>,<crypto>"
119 * TODO: support other hash algorithms
120 */
121 if (!strcmp(ps_info->sig->hash_algo, "sha1")) {
122 info.checksum = image_get_checksum_algo("sha1,rsa2048");
123 info.name = "sha1,rsa2048";
124 } else if (!strcmp(ps_info->sig->hash_algo, "sha256")) {
125 info.checksum = image_get_checksum_algo("sha256,rsa2048");
126 info.name = "sha256,rsa2048";
127 } else {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900128 EFI_PRINT("unknown msg digest algo: %s\n",
129 ps_info->sig->hash_algo);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900130 goto out;
131 }
132 info.crypto = image_get_crypto_algo(info.name);
133
134 info.key = cert->pub->key;
135 info.keylen = cert->pub->keylen;
136
137 /* verify signature */
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900138 EFI_PRINT("%s: crypto: %s, signature len:%x\n", __func__,
139 info.name, ps_info->sig->s_size);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900140 if (ps_info->aa_set & (1UL << sinfo_has_message_digest)) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900141 EFI_PRINT("%s: RSA verify authentication attribute\n",
142 __func__);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900143 /*
144 * NOTE: This path will be executed only for
145 * PE image authentication
146 */
147
148 /* check if hash matches digest first */
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900149 EFI_PRINT("checking msg digest first, len:0x%x\n",
150 ps_info->msgdigest_len);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900151
152#ifdef DEBUG
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900153 EFI_PRINT("hash in database:\n");
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900154 print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
155 ps_info->msgdigest, ps_info->msgdigest_len,
156 false);
157#endif
158 /* against contentInfo first */
AKASHI Takahiro1e64d0b2020-07-08 14:01:55 +0900159 hash = NULL;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900160 if ((msg->data && efi_hash_msg_content(msg, &hash, &size)) ||
161 /* for signed image */
AKASHI Takahiro1e64d0b2020-07-08 14:01:55 +0900162 efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900163 /* for authenticated variable */
164 if (ps_info->msgdigest_len != size ||
165 memcmp(hash, ps_info->msgdigest, size)) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900166 EFI_PRINT("Digest doesn't match\n");
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900167 free(hash);
168 goto out;
169 }
170
171 free(hash);
172 } else {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900173 EFI_PRINT("Digesting image failed\n");
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900174 goto out;
175 }
176
177 /* against digest */
178 c = 0x31;
179 regtmp[0].data = &c;
180 regtmp[0].size = 1;
181 regtmp[1].data = ps_info->authattrs;
182 regtmp[1].size = ps_info->authattrs_len;
183
184 if (!rsa_verify(&info, regtmp, 2,
185 ps_info->sig->s, ps_info->sig->s_size))
186 verified = true;
187 } else {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900188 EFI_PRINT("%s: RSA verify content data\n", __func__);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900189 /* against all data */
190 if (!rsa_verify(&info, regs->reg, regs->num,
191 ps_info->sig->s, ps_info->sig->s_size))
192 verified = true;
193 }
194
195out:
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900196 EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900197 return verified;
198}
199
200/**
AKASHI Takahiro7926dfb2020-07-08 14:01:57 +0900201 * efi_signature_lookup_digest - search for an image's digest in sigdb
202 * @regs: List of regions to be authenticated
203 * @db: Signature database for trusted certificates
204 *
205 * A message digest of image pointed to by @regs is calculated and
206 * its hash value is compared to entries in signature database pointed
207 * to by @db.
208 *
209 * Return: true if found, false if not
210 */
211bool efi_signature_lookup_digest(struct efi_image_regions *regs,
212 struct efi_signature_store *db)
213{
214 struct efi_signature_store *siglist;
215 struct efi_sig_data *sig_data;
216 void *hash = NULL;
217 size_t size = 0;
218 bool found = false;
219
220 EFI_PRINT("%s: Enter, %p, %p\n", __func__, regs, db);
221
222 if (!regs || !db || !db->sig_data_list)
223 goto out;
224
225 for (siglist = db; siglist; siglist = siglist->next) {
226 /* TODO: support other hash algorithms */
227 if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) {
228 EFI_PRINT("Digest algorithm is not supported: %pUl\n",
229 &siglist->sig_type);
230 break;
231 }
232
233 if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
234 EFI_PRINT("Digesting an image failed\n");
235 break;
236 }
237
238 for (sig_data = siglist->sig_data_list; sig_data;
239 sig_data = sig_data->next) {
240#ifdef DEBUG
241 EFI_PRINT("Msg digest in database:\n");
242 print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
243 sig_data->data, sig_data->size, false);
244#endif
245 if (sig_data->size == size &&
246 !memcmp(sig_data->data, hash, size)) {
247 found = true;
248 free(hash);
249 goto out;
250 }
251 }
252
253 free(hash);
254 hash = NULL;
255 }
256
257out:
258 EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
259 return found;
260}
261
262/**
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900263 * efi_signature_verify_with_list - verify a signature with signature list
264 * @regs: List of regions to be authenticated
265 * @msg: Signature
266 * @signed_info: Pointer to PKCS7's signed_info
267 * @siglist: Signature list for certificates
268 * @valid_cert: x509 certificate that verifies this signature
269 *
270 * Signature pointed to by @signed_info against image pointed to by @regs
271 * is verified by signature list pointed to by @siglist.
272 * Signature database is a simple concatenation of one or more
273 * signature list(s).
274 *
275 * Return: true if signature is verified, false if not
276 */
277static
278bool efi_signature_verify_with_list(struct efi_image_regions *regs,
279 struct pkcs7_message *msg,
280 struct pkcs7_signed_info *signed_info,
281 struct efi_signature_store *siglist,
282 struct x509_certificate **valid_cert)
283{
284 struct x509_certificate *cert;
285 struct efi_sig_data *sig_data;
286 bool verified = false;
287
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900288 EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__,
289 regs, signed_info, siglist, valid_cert);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900290
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900291 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509)) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900292 EFI_PRINT("Signature type is not supported: %pUl\n",
293 &siglist->sig_type);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900294 goto out;
295 }
296
297 /* go through the list */
298 for (sig_data = siglist->sig_data_list; sig_data;
299 sig_data = sig_data->next) {
300 /* TODO: support owner check based on policy */
301
302 cert = x509_cert_parse(sig_data->data, sig_data->size);
303 if (IS_ERR(cert)) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900304 EFI_PRINT("Parsing x509 certificate failed\n");
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900305 goto out;
306 }
307
308 verified = efi_signature_verify(regs, msg, signed_info, cert);
309
310 if (verified) {
311 if (valid_cert)
312 *valid_cert = cert;
313 else
314 x509_free_certificate(cert);
315 break;
316 }
317 x509_free_certificate(cert);
318 }
319
320out:
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900321 EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900322 return verified;
323}
324
325/**
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900326 * efi_signature_check_revocation - check revocation with dbx
327 * @sinfo: Signer's info
328 * @cert: x509 certificate
329 * @dbx: Revocation signature database
330 *
331 * Search revocation signature database pointed to by @dbx and find
332 * an entry matching to certificate pointed to by @cert.
333 *
334 * While this entry contains revocation time, we don't support timestamp
335 * protocol at this time and any image will be unconditionally revoked
336 * when this match occurs.
337 *
338 * Return: true if check passed, false otherwise.
339 */
340static bool efi_signature_check_revocation(struct pkcs7_signed_info *sinfo,
341 struct x509_certificate *cert,
342 struct efi_signature_store *dbx)
343{
344 struct efi_signature_store *siglist;
345 struct efi_sig_data *sig_data;
346 struct image_region reg[1];
347 void *hash = NULL;
348 size_t size = 0;
349 time64_t revoc_time;
350 bool revoked = false;
351
352 EFI_PRINT("%s: Enter, %p, %p, %p\n", __func__, sinfo, cert, dbx);
353
354 if (!sinfo || !cert || !dbx || !dbx->sig_data_list)
355 goto out;
356
357 EFI_PRINT("Checking revocation against %s\n", cert->subject);
358 for (siglist = dbx; siglist; siglist = siglist->next) {
359 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256))
360 continue;
361
362 /* calculate hash of TBSCertificate */
363 reg[0].data = cert->tbs;
364 reg[0].size = cert->tbs_size;
365 if (!efi_hash_regions(reg, 1, &hash, &size))
366 goto out;
367
368 for (sig_data = siglist->sig_data_list; sig_data;
369 sig_data = sig_data->next) {
370 /*
371 * struct efi_cert_x509_sha256 {
372 * u8 tbs_hash[256/8];
373 * time64_t revocation_time;
374 * };
375 */
376#ifdef DEBUG
377 if (sig_data->size >= size) {
378 EFI_PRINT("hash in db:\n");
379 print_hex_dump(" ", DUMP_PREFIX_OFFSET,
380 16, 1,
381 sig_data->data, size, false);
382 }
383#endif
384 if ((sig_data->size < size + sizeof(time64_t)) ||
385 memcmp(sig_data->data, hash, size))
386 continue;
387
388 memcpy(&revoc_time, sig_data->data + size,
389 sizeof(revoc_time));
390 EFI_PRINT("revocation time: 0x%llx\n", revoc_time);
391 /*
392 * TODO: compare signing timestamp in sinfo
393 * with revocation time
394 */
395
396 revoked = true;
397 free(hash);
398 goto out;
399 }
400 free(hash);
401 hash = NULL;
402 }
403out:
404 EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
405 return !revoked;
406}
407
408/**
409 * efi_signature_verify_one - verify signatures with database
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900410 * @regs: List of regions to be authenticated
411 * @msg: Signature
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900412 * @db: Signature database
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900413 *
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900414 * All the signature pointed to by @msg against image pointed to by @regs
415 * will be verified by signature database pointed to by @db.
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900416 *
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900417 * Return: true if verification for one of signatures passed, false
418 * otherwise
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900419 */
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900420bool efi_signature_verify_one(struct efi_image_regions *regs,
421 struct pkcs7_message *msg,
422 struct efi_signature_store *db)
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900423{
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900424 struct pkcs7_signed_info *sinfo;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900425 struct efi_signature_store *siglist;
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900426 struct x509_certificate *cert;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900427 bool verified = false;
428
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900429 EFI_PRINT("%s: Enter, %p, %p, %p\n", __func__, regs, msg, db);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900430
431 if (!db)
432 goto out;
433
434 if (!db->sig_data_list)
435 goto out;
436
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900437 EFI_PRINT("%s: Verify signed image with db\n", __func__);
438 for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
439 EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
440 sinfo->sig->hash_algo, sinfo->sig->pkey_algo);
441
442 for (siglist = db; siglist; siglist = siglist->next)
443 if (efi_signature_verify_with_list(regs, msg, sinfo,
444 siglist, &cert)) {
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900445 verified = true;
446 goto out;
447 }
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900448 EFI_PRINT("Valid certificate not in \"db\"\n");
449 }
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900450
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900451out:
452 EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
453 return verified;
454}
455
456/**
457 * efi_signature_verify_with_sigdb - verify signatures with db and dbx
458 * @regs: List of regions to be authenticated
459 * @msg: Signature
460 * @db: Signature database for trusted certificates
461 * @dbx: Revocation signature database
462 *
463 * All the signature pointed to by @msg against image pointed to by @regs
464 * will be verified by signature database pointed to by @db and @dbx.
465 *
466 * Return: true if verification for all signatures passed, false otherwise
467 */
468bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
469 struct pkcs7_message *msg,
470 struct efi_signature_store *db,
471 struct efi_signature_store *dbx)
472{
473 struct pkcs7_signed_info *info;
474 struct efi_signature_store *siglist;
475 struct x509_certificate *cert;
476 bool verified = false;
477
478 EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, dbx);
479
AKASHI Takahiro7926dfb2020-07-08 14:01:57 +0900480 if (!regs || !msg || !db || !db->sig_data_list)
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900481 goto out;
482
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900483 for (info = msg->signed_infos; info; info = info->next) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900484 EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
485 info->sig->hash_algo, info->sig->pkey_algo);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900486
487 for (siglist = db; siglist; siglist = siglist->next) {
488 if (efi_signature_verify_with_list(regs, msg, info,
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900489 siglist, &cert))
490 break;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900491 }
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900492 if (!siglist) {
493 EFI_PRINT("Valid certificate not in \"db\"\n");
494 goto out;
495 }
496
497 if (!dbx || efi_signature_check_revocation(info, cert, dbx))
498 continue;
499
500 EFI_PRINT("Certificate in \"dbx\"\n");
501 goto out;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900502 }
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900503 verified = true;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900504
505out:
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900506 EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900507 return verified;
508}
509
510/**
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900511 * efi_signature_check_signers - check revocation against all signers with dbx
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900512 * @msg: Signature
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900513 * @dbx: Revocation signature database
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900514 *
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900515 * Determine if none of signers' certificates in @msg are revoked
516 * by signature database pointed to by @dbx.
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900517 *
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900518 * Return: true if all signers passed, false otherwise.
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900519 */
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900520bool efi_signature_check_signers(struct pkcs7_message *msg,
521 struct efi_signature_store *dbx)
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900522{
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900523 struct pkcs7_signed_info *sinfo;
524 bool revoked = false;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900525
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900526 EFI_PRINT("%s: Enter, %p, %p\n", __func__, msg, dbx);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900527
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900528 if (!msg || !dbx)
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900529 goto out;
530
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900531 for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
532 if (sinfo->signer &&
533 !efi_signature_check_revocation(sinfo, sinfo->signer,
534 dbx)) {
535 revoked = true;
536 break;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900537 }
538 }
539out:
AKASHI Takahiro11bafb22020-07-08 14:01:56 +0900540 EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
541 return !revoked;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900542}
543
544/**
Heinrich Schuchardt28164c92020-07-01 20:01:52 +0200545 * efi_image_region_add() - add an entry of region
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900546 * @regs: Pointer to array of regions
Heinrich Schuchardt28164c92020-07-01 20:01:52 +0200547 * @start: Start address of region (included)
548 * @end: End address of region (excluded)
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900549 * @nocheck: flag against overlapped regions
550 *
Heinrich Schuchardt28164c92020-07-01 20:01:52 +0200551 * Take one entry of region [@start, @end[ and insert it into the list.
552 *
553 * * If @nocheck is false, the list will be sorted ascending by address.
554 * Overlapping entries will not be allowed.
555 *
556 * * If @nocheck is true, the list will be sorted ascending by sequence
557 * of adding the entries. Overlapping is allowed.
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900558 *
Heinrich Schuchardt30f92ce2020-05-03 16:29:00 +0200559 * Return: status code
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900560 */
561efi_status_t efi_image_region_add(struct efi_image_regions *regs,
562 const void *start, const void *end,
563 int nocheck)
564{
565 struct image_region *reg;
566 int i, j;
567
568 if (regs->num >= regs->max) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900569 EFI_PRINT("%s: no more room for regions\n", __func__);
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900570 return EFI_OUT_OF_RESOURCES;
571 }
572
573 if (end < start)
574 return EFI_INVALID_PARAMETER;
575
576 for (i = 0; i < regs->num; i++) {
577 reg = &regs->reg[i];
578 if (nocheck)
579 continue;
580
Heinrich Schuchardt28164c92020-07-01 20:01:52 +0200581 /* new data after registered region */
582 if (start >= reg->data + reg->size)
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900583 continue;
584
Heinrich Schuchardt28164c92020-07-01 20:01:52 +0200585 /* new data preceding registered region */
586 if (end <= reg->data) {
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900587 for (j = regs->num - 1; j >= i; j--)
Heinrich Schuchardt28164c92020-07-01 20:01:52 +0200588 memcpy(&regs->reg[j + 1], &regs->reg[j],
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900589 sizeof(*reg));
590 break;
591 }
Heinrich Schuchardt28164c92020-07-01 20:01:52 +0200592
593 /* new data overlapping registered region */
594 EFI_PRINT("%s: new region already part of another\n", __func__);
595 return EFI_INVALID_PARAMETER;
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900596 }
597
598 reg = &regs->reg[i];
599 reg->data = start;
600 reg->size = end - start;
601 regs->num++;
602
603 return EFI_SUCCESS;
604}
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900605
606/**
607 * efi_sigstore_free - free signature store
608 * @sigstore: Pointer to signature store structure
609 *
610 * Feee all the memories held in signature store and itself,
611 * which were allocated by efi_sigstore_parse_sigdb().
612 */
613void efi_sigstore_free(struct efi_signature_store *sigstore)
614{
615 struct efi_signature_store *sigstore_next;
616 struct efi_sig_data *sig_data, *sig_data_next;
617
618 while (sigstore) {
619 sigstore_next = sigstore->next;
620
621 sig_data = sigstore->sig_data_list;
622 while (sig_data) {
623 sig_data_next = sig_data->next;
624 free(sig_data->data);
625 free(sig_data);
626 sig_data = sig_data_next;
627 }
628
629 free(sigstore);
630 sigstore = sigstore_next;
631 }
632}
633
634/**
635 * efi_sigstore_parse_siglist - parse a signature list
636 * @name: Pointer to signature list
637 *
638 * Parse signature list and instantiate a signature store structure.
639 * Signature database is a simple concatenation of one or more
640 * signature list(s).
641 *
642 * Return: Pointer to signature store on success, NULL on error
643 */
644static struct efi_signature_store *
645efi_sigstore_parse_siglist(struct efi_signature_list *esl)
646{
647 struct efi_signature_store *siglist = NULL;
648 struct efi_sig_data *sig_data, *sig_data_next;
649 struct efi_signature_data *esd;
650 size_t left;
651
652 /*
653 * UEFI specification defines certificate types:
654 * for non-signed images,
655 * EFI_CERT_SHA256_GUID
656 * EFI_CERT_RSA2048_GUID
657 * EFI_CERT_RSA2048_SHA256_GUID
658 * EFI_CERT_SHA1_GUID
659 * EFI_CERT_RSA2048_SHA_GUID
660 * EFI_CERT_SHA224_GUID
661 * EFI_CERT_SHA384_GUID
662 * EFI_CERT_SHA512_GUID
663 *
664 * for signed images,
665 * EFI_CERT_X509_GUID
666 * NOTE: Each certificate will normally be in a separate
667 * EFI_SIGNATURE_LIST as the size may vary depending on
668 * its algo's.
669 *
670 * for timestamp revocation of certificate,
671 * EFI_CERT_X509_SHA512_GUID
672 * EFI_CERT_X509_SHA256_GUID
673 * EFI_CERT_X509_SHA384_GUID
674 */
675
676 if (esl->signature_list_size
677 <= (sizeof(*esl) + esl->signature_header_size)) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900678 EFI_PRINT("Siglist in wrong format\n");
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900679 return NULL;
680 }
681
682 /* Create a head */
683 siglist = calloc(sizeof(*siglist), 1);
684 if (!siglist) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900685 EFI_PRINT("Out of memory\n");
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900686 goto err;
687 }
688 memcpy(&siglist->sig_type, &esl->signature_type, sizeof(efi_guid_t));
689
690 /* Go through the list */
691 sig_data_next = NULL;
692 left = esl->signature_list_size
693 - (sizeof(*esl) + esl->signature_header_size);
694 esd = (struct efi_signature_data *)
695 ((u8 *)esl + sizeof(*esl) + esl->signature_header_size);
696
AKASHI Takahiro964d5322020-04-21 09:38:57 +0900697 while (left > 0) {
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900698 /* Signature must exist if there is remaining data. */
699 if (left < esl->signature_size) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900700 EFI_PRINT("Certificate is too small\n");
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900701 goto err;
702 }
703
704 sig_data = calloc(esl->signature_size
705 - sizeof(esd->signature_owner), 1);
706 if (!sig_data) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900707 EFI_PRINT("Out of memory\n");
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900708 goto err;
709 }
710
711 /* Append signature data */
712 memcpy(&sig_data->owner, &esd->signature_owner,
713 sizeof(efi_guid_t));
714 sig_data->size = esl->signature_size
715 - sizeof(esd->signature_owner);
716 sig_data->data = malloc(sig_data->size);
717 if (!sig_data->data) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900718 EFI_PRINT("Out of memory\n");
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900719 goto err;
720 }
721 memcpy(sig_data->data, esd->signature_data, sig_data->size);
722
723 sig_data->next = sig_data_next;
724 sig_data_next = sig_data;
725
726 /* Next */
727 esd = (struct efi_signature_data *)
728 ((u8 *)esd + esl->signature_size);
729 left -= esl->signature_size;
730 }
731 siglist->sig_data_list = sig_data_next;
732
733 return siglist;
734
735err:
736 efi_sigstore_free(siglist);
737
738 return NULL;
739}
740
741/**
742 * efi_sigstore_parse_sigdb - parse a signature database variable
743 * @name: Variable's name
744 *
745 * Read in a value of signature database variable pointed to by
746 * @name, parse it and instantiate a signature store structure.
747 *
748 * Return: Pointer to signature store on success, NULL on error
749 */
750struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name)
751{
752 struct efi_signature_store *sigstore = NULL, *siglist;
753 struct efi_signature_list *esl;
754 const efi_guid_t *vendor;
755 void *db;
756 efi_uintn_t db_size;
757 efi_status_t ret;
758
759 if (!u16_strcmp(name, L"PK") || !u16_strcmp(name, L"KEK")) {
760 vendor = &efi_global_variable_guid;
761 } else if (!u16_strcmp(name, L"db") || !u16_strcmp(name, L"dbx")) {
762 vendor = &efi_guid_image_security_database;
763 } else {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900764 EFI_PRINT("unknown signature database, %ls\n", name);
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900765 return NULL;
766 }
767
768 /* retrieve variable data */
769 db_size = 0;
770 ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, NULL));
771 if (ret == EFI_NOT_FOUND) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900772 EFI_PRINT("variable, %ls, not found\n", name);
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900773 sigstore = calloc(sizeof(*sigstore), 1);
774 return sigstore;
775 } else if (ret != EFI_BUFFER_TOO_SMALL) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900776 EFI_PRINT("Getting variable, %ls, failed\n", name);
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900777 return NULL;
778 }
779
780 db = malloc(db_size);
781 if (!db) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900782 EFI_PRINT("Out of memory\n");
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900783 return NULL;
784 }
785
786 ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, db));
787 if (ret != EFI_SUCCESS) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900788 EFI_PRINT("Getting variable, %ls, failed\n", name);
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900789 goto err;
790 }
791
792 /* Parse siglist list */
793 esl = db;
794 while (db_size > 0) {
795 /* List must exist if there is remaining data. */
796 if (db_size < sizeof(*esl)) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900797 EFI_PRINT("variable, %ls, in wrong format\n", name);
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900798 goto err;
799 }
800
801 if (db_size < esl->signature_list_size) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900802 EFI_PRINT("variable, %ls, in wrong format\n", name);
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900803 goto err;
804 }
805
806 /* Parse a single siglist. */
807 siglist = efi_sigstore_parse_siglist(esl);
808 if (!siglist) {
AKASHI Takahiro3e9019d2020-06-09 14:09:33 +0900809 EFI_PRINT("Parsing signature list of %ls failed\n",
810 name);
AKASHI Takahirobe6296d2020-04-14 11:51:40 +0900811 goto err;
812 }
813
814 /* Append siglist */
815 siglist->next = sigstore;
816 sigstore = siglist;
817
818 /* Next */
819 db_size -= esl->signature_list_size;
820 esl = (void *)esl + esl->signature_list_size;
821 }
822 free(db);
823
824 return sigstore;
825
826err:
827 efi_sigstore_free(sigstore);
828 free(db);
829
830 return NULL;
831}
AKASHI Takahiro593e17d2020-04-14 11:51:39 +0900832#endif /* CONFIG_EFI_SECURE_BOOT */