blob: 79dee27421b219193a124666e85ac96a492dec3a [file] [log] [blame]
AKASHI Takahiro1faaca42020-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 Takahiro14afd062020-07-21 19:35:22 +090013#include <crypto/pkcs7.h>
AKASHI Takahiro6ec67672020-04-21 09:38:17 +090014#include <crypto/pkcs7_parser.h>
AKASHI Takahiro14afd062020-07-21 19:35:22 +090015#include <crypto/public_key.h>
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090016#include <linux/compat.h>
17#include <linux/oid_registry.h>
18#include <u-boot/rsa.h>
19#include <u-boot/sha256.h>
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090020
21const efi_guid_t efi_guid_image_security_database =
22 EFI_IMAGE_SECURITY_DATABASE_GUID;
23const efi_guid_t efi_guid_sha256 = EFI_CERT_SHA256_GUID;
24const efi_guid_t efi_guid_cert_rsa2048 = EFI_CERT_RSA2048_GUID;
25const efi_guid_t efi_guid_cert_x509 = EFI_CERT_X509_GUID;
26const efi_guid_t efi_guid_cert_x509_sha256 = EFI_CERT_X509_SHA256_GUID;
AKASHI Takahiro5ed9ada2020-05-29 15:41:18 +090027const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090028
29#ifdef CONFIG_EFI_SECURE_BOOT
30
31/**
32 * efi_hash_regions - calculate a hash value
AKASHI Takahiroddbfa612020-07-08 14:01:55 +090033 * @regs: Array of regions
34 * @count: Number of regions
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090035 * @hash: Pointer to a pointer to buffer holding a hash value
36 * @size: Size of buffer to be returned
37 *
38 * Calculate a sha256 value of @regs and return a value in @hash.
39 *
40 * Return: true on success, false on error
41 */
AKASHI Takahiroddbfa612020-07-08 14:01:55 +090042static bool efi_hash_regions(struct image_region *regs, int count,
43 void **hash, size_t *size)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090044{
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090045 if (!*hash) {
AKASHI Takahiroddbfa612020-07-08 14:01:55 +090046 *hash = calloc(1, SHA256_SUM_LEN);
47 if (!*hash) {
48 EFI_PRINT("Out of memory\n");
49 return false;
50 }
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090051 }
AKASHI Takahiroddbfa612020-07-08 14:01:55 +090052 if (size)
53 *size = SHA256_SUM_LEN;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090054
AKASHI Takahiroddbfa612020-07-08 14:01:55 +090055 hash_calculate("sha256", regs, count, *hash);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090056#ifdef DEBUG
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +090057 EFI_PRINT("hash calculated:\n");
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090058 print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
59 *hash, SHA256_SUM_LEN, false);
60#endif
61
62 return true;
63}
64
65/**
AKASHI Takahirode924072020-07-08 14:01:57 +090066 * efi_signature_lookup_digest - search for an image's digest in sigdb
67 * @regs: List of regions to be authenticated
68 * @db: Signature database for trusted certificates
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090069 *
AKASHI Takahirode924072020-07-08 14:01:57 +090070 * A message digest of image pointed to by @regs is calculated and
71 * its hash value is compared to entries in signature database pointed
72 * to by @db.
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090073 *
AKASHI Takahirode924072020-07-08 14:01:57 +090074 * Return: true if found, false if not
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090075 */
AKASHI Takahirode924072020-07-08 14:01:57 +090076bool efi_signature_lookup_digest(struct efi_image_regions *regs,
77 struct efi_signature_store *db)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090078{
AKASHI Takahirode924072020-07-08 14:01:57 +090079 struct efi_signature_store *siglist;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090080 struct efi_sig_data *sig_data;
AKASHI Takahirode924072020-07-08 14:01:57 +090081 void *hash = NULL;
82 size_t size = 0;
83 bool found = false;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090084
AKASHI Takahirode924072020-07-08 14:01:57 +090085 EFI_PRINT("%s: Enter, %p, %p\n", __func__, regs, db);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090086
AKASHI Takahirode924072020-07-08 14:01:57 +090087 if (!regs || !db || !db->sig_data_list)
88 goto out;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090089
AKASHI Takahirode924072020-07-08 14:01:57 +090090 for (siglist = db; siglist; siglist = siglist->next) {
91 /* TODO: support other hash algorithms */
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090092 if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +090093 EFI_PRINT("Digest algorithm is not supported: %pUl\n",
94 &siglist->sig_type);
AKASHI Takahirode924072020-07-08 14:01:57 +090095 break;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090096 }
97
AKASHI Takahiroddbfa612020-07-08 14:01:55 +090098 if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
AKASHI Takahirode924072020-07-08 14:01:57 +090099 EFI_PRINT("Digesting an image failed\n");
100 break;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900101 }
102
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900103 for (sig_data = siglist->sig_data_list; sig_data;
104 sig_data = sig_data->next) {
105#ifdef DEBUG
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900106 EFI_PRINT("Msg digest in database:\n");
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900107 print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
108 sig_data->data, sig_data->size, false);
109#endif
AKASHI Takahirode924072020-07-08 14:01:57 +0900110 if (sig_data->size == size &&
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900111 !memcmp(sig_data->data, hash, size)) {
AKASHI Takahirode924072020-07-08 14:01:57 +0900112 found = true;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900113 free(hash);
114 goto out;
115 }
116 }
AKASHI Takahirode924072020-07-08 14:01:57 +0900117
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900118 free(hash);
AKASHI Takahirode924072020-07-08 14:01:57 +0900119 hash = NULL;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900120 }
121
AKASHI Takahirode924072020-07-08 14:01:57 +0900122out:
123 EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
124 return found;
125}
126
127/**
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900128 * efi_lookup_certificate - find a certificate within db
129 * @msg: Signature
130 * @db: Signature database
AKASHI Takahirode924072020-07-08 14:01:57 +0900131 *
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900132 * Search signature database pointed to by @db and find a certificate
133 * pointed to by @cert.
AKASHI Takahirode924072020-07-08 14:01:57 +0900134 *
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900135 * Return: true if found, false otherwise.
AKASHI Takahirode924072020-07-08 14:01:57 +0900136 */
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900137static bool efi_lookup_certificate(struct x509_certificate *cert,
138 struct efi_signature_store *db)
AKASHI Takahirode924072020-07-08 14:01:57 +0900139{
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900140 struct efi_signature_store *siglist;
AKASHI Takahirode924072020-07-08 14:01:57 +0900141 struct efi_sig_data *sig_data;
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900142 struct image_region reg[1];
143 void *hash = NULL, *hash_tmp = NULL;
144 size_t size = 0;
145 bool found = false;
AKASHI Takahirode924072020-07-08 14:01:57 +0900146
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900147 EFI_PRINT("%s: Enter, %p, %p\n", __func__, cert, db);
AKASHI Takahirode924072020-07-08 14:01:57 +0900148
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900149 if (!cert || !db || !db->sig_data_list)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900150 goto out;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900151
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900152 /*
153 * TODO: identify a certificate using sha256 digest
154 * Is there any better way?
155 */
156 /* calculate hash of TBSCertificate */
157 reg[0].data = cert->tbs;
158 reg[0].size = cert->tbs_size;
159 if (!efi_hash_regions(reg, 1, &hash, &size))
160 goto out;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900161
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900162 EFI_PRINT("%s: searching for %s\n", __func__, cert->subject);
163 for (siglist = db; siglist; siglist = siglist->next) {
164 /* only with x509 certificate */
165 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509))
166 continue;
167
168 for (sig_data = siglist->sig_data_list; sig_data;
169 sig_data = sig_data->next) {
170 struct x509_certificate *cert_tmp;
171
172 cert_tmp = x509_cert_parse(sig_data->data,
173 sig_data->size);
174 if (IS_ERR_OR_NULL(cert_tmp))
175 continue;
176
AKASHI Takahiro16411802020-08-14 14:39:23 +0900177 EFI_PRINT("%s: against %s\n", __func__,
178 cert_tmp->subject);
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900179 reg[0].data = cert_tmp->tbs;
180 reg[0].size = cert_tmp->tbs_size;
181 if (!efi_hash_regions(reg, 1, &hash_tmp, NULL))
182 goto out;
183
184 x509_free_certificate(cert_tmp);
185
186 if (!memcmp(hash, hash_tmp, size)) {
187 found = true;
188 goto out;
189 }
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900190 }
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900191 }
192out:
193 free(hash);
194 free(hash_tmp);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900195
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900196 EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
197 return found;
198}
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900199
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900200/**
201 * efi_verify_certificate - verify certificate's signature with database
202 * @signer: Certificate
203 * @db: Signature database
204 * @root: Certificate to verify @signer
205 *
206 * Determine if certificate pointed to by @signer may be verified
207 * by one of certificates in signature database pointed to by @db.
208 *
209 * Return: true if certificate is verified, false otherwise.
210 */
211static bool efi_verify_certificate(struct x509_certificate *signer,
212 struct efi_signature_store *db,
213 struct x509_certificate **root)
214{
215 struct efi_signature_store *siglist;
216 struct efi_sig_data *sig_data;
217 struct x509_certificate *cert;
218 bool verified = false;
219 int ret;
220
221 EFI_PRINT("%s: Enter, %p, %p\n", __func__, signer, db);
222
223 if (!signer || !db || !db->sig_data_list)
224 goto out;
225
226 for (siglist = db; siglist; siglist = siglist->next) {
227 /* only with x509 certificate */
228 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509))
229 continue;
230
231 for (sig_data = siglist->sig_data_list; sig_data;
232 sig_data = sig_data->next) {
233 cert = x509_cert_parse(sig_data->data, sig_data->size);
234 if (IS_ERR_OR_NULL(cert)) {
235 EFI_PRINT("Cannot parse x509 certificate\n");
236 continue;
237 }
238
239 ret = public_key_verify_signature(cert->pub,
240 signer->sig);
241 if (!ret) {
242 verified = true;
243 if (root)
244 *root = cert;
245 else
246 x509_free_certificate(cert);
247 goto out;
248 }
249 x509_free_certificate(cert);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900250 }
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900251 }
252
253out:
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900254 EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900255 return verified;
256}
257
258/**
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900259 * efi_signature_check_revocation - check revocation with dbx
260 * @sinfo: Signer's info
261 * @cert: x509 certificate
262 * @dbx: Revocation signature database
263 *
264 * Search revocation signature database pointed to by @dbx and find
265 * an entry matching to certificate pointed to by @cert.
266 *
267 * While this entry contains revocation time, we don't support timestamp
268 * protocol at this time and any image will be unconditionally revoked
269 * when this match occurs.
270 *
AKASHI Takahiro16411802020-08-14 14:39:23 +0900271 * Return: true if check passed (not found), false otherwise.
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900272 */
273static bool efi_signature_check_revocation(struct pkcs7_signed_info *sinfo,
274 struct x509_certificate *cert,
275 struct efi_signature_store *dbx)
276{
277 struct efi_signature_store *siglist;
278 struct efi_sig_data *sig_data;
279 struct image_region reg[1];
280 void *hash = NULL;
281 size_t size = 0;
282 time64_t revoc_time;
283 bool revoked = false;
284
285 EFI_PRINT("%s: Enter, %p, %p, %p\n", __func__, sinfo, cert, dbx);
286
287 if (!sinfo || !cert || !dbx || !dbx->sig_data_list)
288 goto out;
289
290 EFI_PRINT("Checking revocation against %s\n", cert->subject);
291 for (siglist = dbx; siglist; siglist = siglist->next) {
292 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256))
293 continue;
294
295 /* calculate hash of TBSCertificate */
296 reg[0].data = cert->tbs;
297 reg[0].size = cert->tbs_size;
298 if (!efi_hash_regions(reg, 1, &hash, &size))
299 goto out;
300
301 for (sig_data = siglist->sig_data_list; sig_data;
302 sig_data = sig_data->next) {
303 /*
304 * struct efi_cert_x509_sha256 {
305 * u8 tbs_hash[256/8];
306 * time64_t revocation_time;
307 * };
308 */
309#ifdef DEBUG
310 if (sig_data->size >= size) {
311 EFI_PRINT("hash in db:\n");
312 print_hex_dump(" ", DUMP_PREFIX_OFFSET,
313 16, 1,
314 sig_data->data, size, false);
315 }
316#endif
317 if ((sig_data->size < size + sizeof(time64_t)) ||
318 memcmp(sig_data->data, hash, size))
319 continue;
320
321 memcpy(&revoc_time, sig_data->data + size,
322 sizeof(revoc_time));
323 EFI_PRINT("revocation time: 0x%llx\n", revoc_time);
324 /*
325 * TODO: compare signing timestamp in sinfo
326 * with revocation time
327 */
328
329 revoked = true;
330 free(hash);
331 goto out;
332 }
333 free(hash);
334 hash = NULL;
335 }
336out:
337 EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
338 return !revoked;
339}
340
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900341/*
342 * efi_signature_verify - verify signatures with db and dbx
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900343 * @regs: List of regions to be authenticated
344 * @msg: Signature
345 * @db: Signature database for trusted certificates
346 * @dbx: Revocation signature database
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900347 *
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900348 * All the signature pointed to by @msg against image pointed to by @regs
349 * will be verified by signature database pointed to by @db and @dbx.
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900350 *
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900351 * Return: true if verification for all signatures passed, false otherwise
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900352 */
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900353bool efi_signature_verify(struct efi_image_regions *regs,
354 struct pkcs7_message *msg,
355 struct efi_signature_store *db,
356 struct efi_signature_store *dbx)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900357{
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900358 struct pkcs7_signed_info *sinfo;
359 struct x509_certificate *signer, *root;
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900360 bool verified = false;
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900361 int ret;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900362
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900363 EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, dbx);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900364
AKASHI Takahirode924072020-07-08 14:01:57 +0900365 if (!regs || !msg || !db || !db->sig_data_list)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900366 goto out;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900367
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900368 for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900369 EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900370 sinfo->sig->hash_algo, sinfo->sig->pkey_algo);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900371
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900372 /*
373 * only for authenticated variable.
374 *
375 * If this function is called for image,
376 * hash calculation will be done in
377 * pkcs7_verify_one().
378 */
379 if (!msg->data &&
380 !efi_hash_regions(regs->reg, regs->num,
381 (void **)&sinfo->sig->digest, NULL)) {
382 EFI_PRINT("Digesting an image failed\n");
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900383 goto out;
384 }
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900385
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900386 EFI_PRINT("Verifying certificate chain\n");
387 signer = NULL;
388 ret = pkcs7_verify_one(msg, sinfo, &signer);
389 if (ret == -ENOPKG)
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900390 continue;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900391
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900392 if (ret < 0 || !signer)
393 goto out;
394
395 if (sinfo->blacklisted)
396 goto out;
397
398 EFI_PRINT("Verifying last certificate in chain\n");
399 if (signer->self_signed) {
400 if (efi_lookup_certificate(signer, db))
401 if (efi_signature_check_revocation(sinfo,
402 signer, dbx))
AKASHI Takahiro16411802020-08-14 14:39:23 +0900403 break;
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900404 } else if (efi_verify_certificate(signer, db, &root)) {
405 bool check;
406
407 check = efi_signature_check_revocation(sinfo, root,
408 dbx);
409 x509_free_certificate(root);
410 if (check)
AKASHI Takahiro16411802020-08-14 14:39:23 +0900411 break;
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900412 }
413
414 EFI_PRINT("Certificate chain didn't reach trusted CA\n");
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900415 }
AKASHI Takahiro16411802020-08-14 14:39:23 +0900416 if (sinfo)
417 verified = true;
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900418out:
419 EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
420 return verified;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900421}
422
423/**
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900424 * efi_signature_check_signers - check revocation against all signers with dbx
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900425 * @msg: Signature
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900426 * @dbx: Revocation signature database
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900427 *
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900428 * Determine if none of signers' certificates in @msg are revoked
429 * by signature database pointed to by @dbx.
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900430 *
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900431 * Return: true if all signers passed, false otherwise.
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900432 */
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900433bool efi_signature_check_signers(struct pkcs7_message *msg,
434 struct efi_signature_store *dbx)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900435{
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900436 struct pkcs7_signed_info *sinfo;
437 bool revoked = false;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900438
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900439 EFI_PRINT("%s: Enter, %p, %p\n", __func__, msg, dbx);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900440
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900441 if (!msg || !dbx)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900442 goto out;
443
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900444 for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
445 if (sinfo->signer &&
446 !efi_signature_check_revocation(sinfo, sinfo->signer,
447 dbx)) {
448 revoked = true;
449 break;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900450 }
451 }
452out:
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900453 EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
454 return !revoked;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900455}
456
457/**
Heinrich Schuchardt623e5e52020-07-01 20:01:52 +0200458 * efi_image_region_add() - add an entry of region
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900459 * @regs: Pointer to array of regions
Heinrich Schuchardt623e5e52020-07-01 20:01:52 +0200460 * @start: Start address of region (included)
461 * @end: End address of region (excluded)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900462 * @nocheck: flag against overlapped regions
463 *
Heinrich Schuchardt623e5e52020-07-01 20:01:52 +0200464 * Take one entry of region [@start, @end[ and insert it into the list.
465 *
466 * * If @nocheck is false, the list will be sorted ascending by address.
467 * Overlapping entries will not be allowed.
468 *
469 * * If @nocheck is true, the list will be sorted ascending by sequence
470 * of adding the entries. Overlapping is allowed.
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900471 *
Heinrich Schuchardte2c43da2020-05-03 16:29:00 +0200472 * Return: status code
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900473 */
474efi_status_t efi_image_region_add(struct efi_image_regions *regs,
475 const void *start, const void *end,
476 int nocheck)
477{
478 struct image_region *reg;
479 int i, j;
480
481 if (regs->num >= regs->max) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900482 EFI_PRINT("%s: no more room for regions\n", __func__);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900483 return EFI_OUT_OF_RESOURCES;
484 }
485
486 if (end < start)
487 return EFI_INVALID_PARAMETER;
488
489 for (i = 0; i < regs->num; i++) {
490 reg = &regs->reg[i];
491 if (nocheck)
492 continue;
493
Heinrich Schuchardt623e5e52020-07-01 20:01:52 +0200494 /* new data after registered region */
495 if (start >= reg->data + reg->size)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900496 continue;
497
Heinrich Schuchardt623e5e52020-07-01 20:01:52 +0200498 /* new data preceding registered region */
499 if (end <= reg->data) {
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900500 for (j = regs->num - 1; j >= i; j--)
Heinrich Schuchardt623e5e52020-07-01 20:01:52 +0200501 memcpy(&regs->reg[j + 1], &regs->reg[j],
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900502 sizeof(*reg));
503 break;
504 }
Heinrich Schuchardt623e5e52020-07-01 20:01:52 +0200505
506 /* new data overlapping registered region */
507 EFI_PRINT("%s: new region already part of another\n", __func__);
508 return EFI_INVALID_PARAMETER;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900509 }
510
511 reg = &regs->reg[i];
512 reg->data = start;
513 reg->size = end - start;
514 regs->num++;
515
516 return EFI_SUCCESS;
517}
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900518
519/**
520 * efi_sigstore_free - free signature store
521 * @sigstore: Pointer to signature store structure
522 *
523 * Feee all the memories held in signature store and itself,
524 * which were allocated by efi_sigstore_parse_sigdb().
525 */
526void efi_sigstore_free(struct efi_signature_store *sigstore)
527{
528 struct efi_signature_store *sigstore_next;
529 struct efi_sig_data *sig_data, *sig_data_next;
530
531 while (sigstore) {
532 sigstore_next = sigstore->next;
533
534 sig_data = sigstore->sig_data_list;
535 while (sig_data) {
536 sig_data_next = sig_data->next;
537 free(sig_data->data);
538 free(sig_data);
539 sig_data = sig_data_next;
540 }
541
542 free(sigstore);
543 sigstore = sigstore_next;
544 }
545}
546
547/**
548 * efi_sigstore_parse_siglist - parse a signature list
549 * @name: Pointer to signature list
550 *
551 * Parse signature list and instantiate a signature store structure.
552 * Signature database is a simple concatenation of one or more
553 * signature list(s).
554 *
555 * Return: Pointer to signature store on success, NULL on error
556 */
557static struct efi_signature_store *
558efi_sigstore_parse_siglist(struct efi_signature_list *esl)
559{
560 struct efi_signature_store *siglist = NULL;
561 struct efi_sig_data *sig_data, *sig_data_next;
562 struct efi_signature_data *esd;
563 size_t left;
564
565 /*
566 * UEFI specification defines certificate types:
567 * for non-signed images,
568 * EFI_CERT_SHA256_GUID
569 * EFI_CERT_RSA2048_GUID
570 * EFI_CERT_RSA2048_SHA256_GUID
571 * EFI_CERT_SHA1_GUID
572 * EFI_CERT_RSA2048_SHA_GUID
573 * EFI_CERT_SHA224_GUID
574 * EFI_CERT_SHA384_GUID
575 * EFI_CERT_SHA512_GUID
576 *
577 * for signed images,
578 * EFI_CERT_X509_GUID
579 * NOTE: Each certificate will normally be in a separate
580 * EFI_SIGNATURE_LIST as the size may vary depending on
581 * its algo's.
582 *
583 * for timestamp revocation of certificate,
584 * EFI_CERT_X509_SHA512_GUID
585 * EFI_CERT_X509_SHA256_GUID
586 * EFI_CERT_X509_SHA384_GUID
587 */
588
589 if (esl->signature_list_size
590 <= (sizeof(*esl) + esl->signature_header_size)) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900591 EFI_PRINT("Siglist in wrong format\n");
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900592 return NULL;
593 }
594
595 /* Create a head */
596 siglist = calloc(sizeof(*siglist), 1);
597 if (!siglist) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900598 EFI_PRINT("Out of memory\n");
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900599 goto err;
600 }
601 memcpy(&siglist->sig_type, &esl->signature_type, sizeof(efi_guid_t));
602
603 /* Go through the list */
604 sig_data_next = NULL;
605 left = esl->signature_list_size
606 - (sizeof(*esl) + esl->signature_header_size);
607 esd = (struct efi_signature_data *)
608 ((u8 *)esl + sizeof(*esl) + esl->signature_header_size);
609
AKASHI Takahiroa075aa32020-04-21 09:38:57 +0900610 while (left > 0) {
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900611 /* Signature must exist if there is remaining data. */
612 if (left < esl->signature_size) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900613 EFI_PRINT("Certificate is too small\n");
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900614 goto err;
615 }
616
617 sig_data = calloc(esl->signature_size
618 - sizeof(esd->signature_owner), 1);
619 if (!sig_data) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900620 EFI_PRINT("Out of memory\n");
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900621 goto err;
622 }
623
624 /* Append signature data */
625 memcpy(&sig_data->owner, &esd->signature_owner,
626 sizeof(efi_guid_t));
627 sig_data->size = esl->signature_size
628 - sizeof(esd->signature_owner);
629 sig_data->data = malloc(sig_data->size);
630 if (!sig_data->data) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900631 EFI_PRINT("Out of memory\n");
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900632 goto err;
633 }
634 memcpy(sig_data->data, esd->signature_data, sig_data->size);
635
636 sig_data->next = sig_data_next;
637 sig_data_next = sig_data;
638
639 /* Next */
640 esd = (struct efi_signature_data *)
641 ((u8 *)esd + esl->signature_size);
642 left -= esl->signature_size;
643 }
644 siglist->sig_data_list = sig_data_next;
645
646 return siglist;
647
648err:
649 efi_sigstore_free(siglist);
650
651 return NULL;
652}
653
654/**
655 * efi_sigstore_parse_sigdb - parse a signature database variable
656 * @name: Variable's name
657 *
658 * Read in a value of signature database variable pointed to by
659 * @name, parse it and instantiate a signature store structure.
660 *
661 * Return: Pointer to signature store on success, NULL on error
662 */
663struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name)
664{
665 struct efi_signature_store *sigstore = NULL, *siglist;
666 struct efi_signature_list *esl;
667 const efi_guid_t *vendor;
668 void *db;
669 efi_uintn_t db_size;
670 efi_status_t ret;
671
672 if (!u16_strcmp(name, L"PK") || !u16_strcmp(name, L"KEK")) {
673 vendor = &efi_global_variable_guid;
674 } else if (!u16_strcmp(name, L"db") || !u16_strcmp(name, L"dbx")) {
675 vendor = &efi_guid_image_security_database;
676 } else {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900677 EFI_PRINT("unknown signature database, %ls\n", name);
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900678 return NULL;
679 }
680
681 /* retrieve variable data */
682 db_size = 0;
683 ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, NULL));
684 if (ret == EFI_NOT_FOUND) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900685 EFI_PRINT("variable, %ls, not found\n", name);
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900686 sigstore = calloc(sizeof(*sigstore), 1);
687 return sigstore;
688 } else if (ret != EFI_BUFFER_TOO_SMALL) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900689 EFI_PRINT("Getting variable, %ls, failed\n", name);
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900690 return NULL;
691 }
692
693 db = malloc(db_size);
694 if (!db) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900695 EFI_PRINT("Out of memory\n");
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900696 return NULL;
697 }
698
699 ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, db));
700 if (ret != EFI_SUCCESS) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900701 EFI_PRINT("Getting variable, %ls, failed\n", name);
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900702 goto err;
703 }
704
705 /* Parse siglist list */
706 esl = db;
707 while (db_size > 0) {
708 /* List must exist if there is remaining data. */
709 if (db_size < sizeof(*esl)) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900710 EFI_PRINT("variable, %ls, in wrong format\n", name);
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900711 goto err;
712 }
713
714 if (db_size < esl->signature_list_size) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900715 EFI_PRINT("variable, %ls, in wrong format\n", name);
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900716 goto err;
717 }
718
719 /* Parse a single siglist. */
720 siglist = efi_sigstore_parse_siglist(esl);
721 if (!siglist) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900722 EFI_PRINT("Parsing signature list of %ls failed\n",
723 name);
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900724 goto err;
725 }
726
727 /* Append siglist */
728 siglist->next = sigstore;
729 sigstore = siglist;
730
731 /* Next */
732 db_size -= esl->signature_list_size;
733 esl = (void *)esl + esl->signature_list_size;
734 }
735 free(db);
736
737 return sigstore;
738
739err:
740 efi_sigstore_free(sigstore);
741 free(db);
742
743 return NULL;
744}
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900745#endif /* CONFIG_EFI_SECURE_BOOT */