blob: 3243e2c60de0aa536f9014acca88795cd91c1749 [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>
Heinrich Schuchardtcaeb73b2021-09-09 08:25:08 +020010#include <efi_variable.h>
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090011#include <image.h>
12#include <hexdump.h>
13#include <malloc.h>
AKASHI Takahiro14afd062020-07-21 19:35:22 +090014#include <crypto/pkcs7.h>
AKASHI Takahiro6ec67672020-04-21 09:38:17 +090015#include <crypto/pkcs7_parser.h>
AKASHI Takahiro14afd062020-07-21 19:35:22 +090016#include <crypto/public_key.h>
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090017#include <linux/compat.h>
18#include <linux/oid_registry.h>
Masahisa Kojima915e4272021-05-14 09:53:36 +090019#include <u-boot/hash-checksum.h>
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090020#include <u-boot/rsa.h>
21#include <u-boot/sha256.h>
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090022
AKASHI Takahiro1faaca42020-04-14 11:51:39 +090023const 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
Sughosh Ganuea350082020-12-30 19:27:07 +053029static u8 pkcs7_hdr[] = {
30 /* SEQUENCE */
31 0x30, 0x82, 0x05, 0xc7,
32 /* OID: pkcs7-signedData */
33 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02,
34 /* Context Structured? */
35 0xa0, 0x82, 0x05, 0xb8,
36};
37
38/**
39 * efi_parse_pkcs7_header - parse a signature in payload
40 * @buf: Pointer to payload's value
41 * @buflen: Length of @buf
42 * @tmpbuf: Pointer to temporary buffer
43 *
44 * Parse a signature embedded in payload's value and instantiate
45 * a pkcs7_message structure. Since pkcs7_parse_message() accepts only
46 * pkcs7's signedData, some header needed be prepended for correctly
47 * parsing authentication data
48 * A temporary buffer will be allocated if needed, and it should be
49 * kept valid during the authentication because some data in the buffer
50 * will be referenced by efi_signature_verify().
51 *
52 * Return: Pointer to pkcs7_message structure on success, NULL on error
53 */
54struct pkcs7_message *efi_parse_pkcs7_header(const void *buf,
55 size_t buflen,
56 u8 **tmpbuf)
57{
58 u8 *ebuf;
59 size_t ebuflen, len;
60 struct pkcs7_message *msg;
61
62 /*
63 * This is the best assumption to check if the binary is
64 * already in a form of pkcs7's signedData.
65 */
66 if (buflen > sizeof(pkcs7_hdr) &&
67 !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) {
68 msg = pkcs7_parse_message(buf, buflen);
69 if (IS_ERR(msg))
70 return NULL;
71 return msg;
72 }
73
74 /*
75 * Otherwise, we should add a dummy prefix sequence for pkcs7
76 * message parser to be able to process.
77 * NOTE: EDK2 also uses similar hack in WrapPkcs7Data()
78 * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c
79 * TODO:
80 * The header should be composed in a more refined manner.
81 */
82 EFI_PRINT("Makeshift prefix added to authentication data\n");
83 ebuflen = sizeof(pkcs7_hdr) + buflen;
84 if (ebuflen <= 0x7f) {
85 EFI_PRINT("Data is too short\n");
86 return NULL;
87 }
88
89 ebuf = malloc(ebuflen);
90 if (!ebuf) {
91 EFI_PRINT("Out of memory\n");
92 return NULL;
93 }
94
95 memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr));
96 memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen);
97 len = ebuflen - 4;
98 ebuf[2] = (len >> 8) & 0xff;
99 ebuf[3] = len & 0xff;
100 len = ebuflen - 0x13;
101 ebuf[0x11] = (len >> 8) & 0xff;
102 ebuf[0x12] = len & 0xff;
103
104 msg = pkcs7_parse_message(ebuf, ebuflen);
105
106 if (IS_ERR(msg)) {
107 free(ebuf);
108 return NULL;
109 }
110
111 *tmpbuf = ebuf;
112 return msg;
113}
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900114
115/**
116 * efi_hash_regions - calculate a hash value
AKASHI Takahiroddbfa612020-07-08 14:01:55 +0900117 * @regs: Array of regions
118 * @count: Number of regions
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900119 * @hash: Pointer to a pointer to buffer holding a hash value
120 * @size: Size of buffer to be returned
121 *
122 * Calculate a sha256 value of @regs and return a value in @hash.
123 *
124 * Return: true on success, false on error
125 */
AKASHI Takahiroddbfa612020-07-08 14:01:55 +0900126static bool efi_hash_regions(struct image_region *regs, int count,
127 void **hash, size_t *size)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900128{
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900129 if (!*hash) {
AKASHI Takahiroddbfa612020-07-08 14:01:55 +0900130 *hash = calloc(1, SHA256_SUM_LEN);
131 if (!*hash) {
132 EFI_PRINT("Out of memory\n");
133 return false;
134 }
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900135 }
AKASHI Takahiroddbfa612020-07-08 14:01:55 +0900136 if (size)
137 *size = SHA256_SUM_LEN;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900138
AKASHI Takahiroddbfa612020-07-08 14:01:55 +0900139 hash_calculate("sha256", regs, count, *hash);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900140#ifdef DEBUG
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900141 EFI_PRINT("hash calculated:\n");
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900142 print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
143 *hash, SHA256_SUM_LEN, false);
144#endif
145
146 return true;
147}
148
149/**
AKASHI Takahirode924072020-07-08 14:01:57 +0900150 * efi_signature_lookup_digest - search for an image's digest in sigdb
151 * @regs: List of regions to be authenticated
152 * @db: Signature database for trusted certificates
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900153 *
AKASHI Takahirode924072020-07-08 14:01:57 +0900154 * A message digest of image pointed to by @regs is calculated and
155 * its hash value is compared to entries in signature database pointed
156 * to by @db.
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900157 *
AKASHI Takahirode924072020-07-08 14:01:57 +0900158 * Return: true if found, false if not
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900159 */
AKASHI Takahirode924072020-07-08 14:01:57 +0900160bool efi_signature_lookup_digest(struct efi_image_regions *regs,
161 struct efi_signature_store *db)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900162{
AKASHI Takahirode924072020-07-08 14:01:57 +0900163 struct efi_signature_store *siglist;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900164 struct efi_sig_data *sig_data;
AKASHI Takahirode924072020-07-08 14:01:57 +0900165 void *hash = NULL;
166 size_t size = 0;
167 bool found = false;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900168
AKASHI Takahirode924072020-07-08 14:01:57 +0900169 EFI_PRINT("%s: Enter, %p, %p\n", __func__, regs, db);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900170
AKASHI Takahirode924072020-07-08 14:01:57 +0900171 if (!regs || !db || !db->sig_data_list)
172 goto out;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900173
AKASHI Takahirode924072020-07-08 14:01:57 +0900174 for (siglist = db; siglist; siglist = siglist->next) {
175 /* TODO: support other hash algorithms */
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900176 if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) {
Heinrich Schuchardt282249d2022-01-16 14:15:31 +0100177 EFI_PRINT("Digest algorithm is not supported: %pUs\n",
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900178 &siglist->sig_type);
AKASHI Takahirode924072020-07-08 14:01:57 +0900179 break;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900180 }
181
AKASHI Takahiroddbfa612020-07-08 14:01:55 +0900182 if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
AKASHI Takahirode924072020-07-08 14:01:57 +0900183 EFI_PRINT("Digesting an image failed\n");
184 break;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900185 }
186
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900187 for (sig_data = siglist->sig_data_list; sig_data;
188 sig_data = sig_data->next) {
189#ifdef DEBUG
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900190 EFI_PRINT("Msg digest in database:\n");
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900191 print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
192 sig_data->data, sig_data->size, false);
193#endif
AKASHI Takahirode924072020-07-08 14:01:57 +0900194 if (sig_data->size == size &&
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900195 !memcmp(sig_data->data, hash, size)) {
AKASHI Takahirode924072020-07-08 14:01:57 +0900196 found = true;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900197 free(hash);
198 goto out;
199 }
200 }
AKASHI Takahirode924072020-07-08 14:01:57 +0900201
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900202 free(hash);
AKASHI Takahirode924072020-07-08 14:01:57 +0900203 hash = NULL;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900204 }
205
AKASHI Takahirode924072020-07-08 14:01:57 +0900206out:
207 EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
208 return found;
209}
210
211/**
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900212 * efi_lookup_certificate - find a certificate within db
213 * @msg: Signature
214 * @db: Signature database
AKASHI Takahirode924072020-07-08 14:01:57 +0900215 *
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900216 * Search signature database pointed to by @db and find a certificate
217 * pointed to by @cert.
AKASHI Takahirode924072020-07-08 14:01:57 +0900218 *
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900219 * Return: true if found, false otherwise.
AKASHI Takahirode924072020-07-08 14:01:57 +0900220 */
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900221static bool efi_lookup_certificate(struct x509_certificate *cert,
222 struct efi_signature_store *db)
AKASHI Takahirode924072020-07-08 14:01:57 +0900223{
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900224 struct efi_signature_store *siglist;
AKASHI Takahirode924072020-07-08 14:01:57 +0900225 struct efi_sig_data *sig_data;
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900226 struct image_region reg[1];
227 void *hash = NULL, *hash_tmp = NULL;
228 size_t size = 0;
229 bool found = false;
AKASHI Takahirode924072020-07-08 14:01:57 +0900230
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900231 EFI_PRINT("%s: Enter, %p, %p\n", __func__, cert, db);
AKASHI Takahirode924072020-07-08 14:01:57 +0900232
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900233 if (!cert || !db || !db->sig_data_list)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900234 goto out;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900235
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900236 /*
237 * TODO: identify a certificate using sha256 digest
238 * Is there any better way?
239 */
240 /* calculate hash of TBSCertificate */
241 reg[0].data = cert->tbs;
242 reg[0].size = cert->tbs_size;
243 if (!efi_hash_regions(reg, 1, &hash, &size))
244 goto out;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900245
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900246 EFI_PRINT("%s: searching for %s\n", __func__, cert->subject);
247 for (siglist = db; siglist; siglist = siglist->next) {
248 /* only with x509 certificate */
249 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509))
250 continue;
251
252 for (sig_data = siglist->sig_data_list; sig_data;
253 sig_data = sig_data->next) {
254 struct x509_certificate *cert_tmp;
255
256 cert_tmp = x509_cert_parse(sig_data->data,
257 sig_data->size);
258 if (IS_ERR_OR_NULL(cert_tmp))
259 continue;
260
AKASHI Takahiro16411802020-08-14 14:39:23 +0900261 EFI_PRINT("%s: against %s\n", __func__,
262 cert_tmp->subject);
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900263 reg[0].data = cert_tmp->tbs;
264 reg[0].size = cert_tmp->tbs_size;
265 if (!efi_hash_regions(reg, 1, &hash_tmp, NULL))
266 goto out;
267
268 x509_free_certificate(cert_tmp);
269
270 if (!memcmp(hash, hash_tmp, size)) {
271 found = true;
272 goto out;
273 }
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900274 }
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900275 }
276out:
277 free(hash);
278 free(hash_tmp);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900279
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900280 EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
281 return found;
282}
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900283
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900284/**
285 * efi_verify_certificate - verify certificate's signature with database
286 * @signer: Certificate
287 * @db: Signature database
288 * @root: Certificate to verify @signer
289 *
290 * Determine if certificate pointed to by @signer may be verified
291 * by one of certificates in signature database pointed to by @db.
292 *
293 * Return: true if certificate is verified, false otherwise.
294 */
295static bool efi_verify_certificate(struct x509_certificate *signer,
296 struct efi_signature_store *db,
297 struct x509_certificate **root)
298{
299 struct efi_signature_store *siglist;
300 struct efi_sig_data *sig_data;
301 struct x509_certificate *cert;
302 bool verified = false;
303 int ret;
304
305 EFI_PRINT("%s: Enter, %p, %p\n", __func__, signer, db);
306
307 if (!signer || !db || !db->sig_data_list)
308 goto out;
309
310 for (siglist = db; siglist; siglist = siglist->next) {
311 /* only with x509 certificate */
312 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509))
313 continue;
314
315 for (sig_data = siglist->sig_data_list; sig_data;
316 sig_data = sig_data->next) {
317 cert = x509_cert_parse(sig_data->data, sig_data->size);
318 if (IS_ERR_OR_NULL(cert)) {
319 EFI_PRINT("Cannot parse x509 certificate\n");
320 continue;
321 }
322
323 ret = public_key_verify_signature(cert->pub,
324 signer->sig);
325 if (!ret) {
326 verified = true;
327 if (root)
328 *root = cert;
329 else
330 x509_free_certificate(cert);
331 goto out;
332 }
333 x509_free_certificate(cert);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900334 }
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900335 }
336
337out:
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900338 EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900339 return verified;
340}
341
342/**
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900343 * efi_signature_check_revocation - check revocation with dbx
344 * @sinfo: Signer's info
345 * @cert: x509 certificate
346 * @dbx: Revocation signature database
347 *
348 * Search revocation signature database pointed to by @dbx and find
349 * an entry matching to certificate pointed to by @cert.
350 *
351 * While this entry contains revocation time, we don't support timestamp
352 * protocol at this time and any image will be unconditionally revoked
353 * when this match occurs.
354 *
AKASHI Takahiro16411802020-08-14 14:39:23 +0900355 * Return: true if check passed (not found), false otherwise.
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900356 */
357static bool efi_signature_check_revocation(struct pkcs7_signed_info *sinfo,
358 struct x509_certificate *cert,
359 struct efi_signature_store *dbx)
360{
361 struct efi_signature_store *siglist;
362 struct efi_sig_data *sig_data;
363 struct image_region reg[1];
364 void *hash = NULL;
365 size_t size = 0;
366 time64_t revoc_time;
367 bool revoked = false;
368
369 EFI_PRINT("%s: Enter, %p, %p, %p\n", __func__, sinfo, cert, dbx);
370
371 if (!sinfo || !cert || !dbx || !dbx->sig_data_list)
372 goto out;
373
374 EFI_PRINT("Checking revocation against %s\n", cert->subject);
375 for (siglist = dbx; siglist; siglist = siglist->next) {
376 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256))
377 continue;
378
379 /* calculate hash of TBSCertificate */
380 reg[0].data = cert->tbs;
381 reg[0].size = cert->tbs_size;
382 if (!efi_hash_regions(reg, 1, &hash, &size))
383 goto out;
384
385 for (sig_data = siglist->sig_data_list; sig_data;
386 sig_data = sig_data->next) {
387 /*
388 * struct efi_cert_x509_sha256 {
389 * u8 tbs_hash[256/8];
390 * time64_t revocation_time;
391 * };
392 */
393#ifdef DEBUG
394 if (sig_data->size >= size) {
395 EFI_PRINT("hash in db:\n");
396 print_hex_dump(" ", DUMP_PREFIX_OFFSET,
397 16, 1,
398 sig_data->data, size, false);
399 }
400#endif
401 if ((sig_data->size < size + sizeof(time64_t)) ||
402 memcmp(sig_data->data, hash, size))
403 continue;
404
405 memcpy(&revoc_time, sig_data->data + size,
406 sizeof(revoc_time));
407 EFI_PRINT("revocation time: 0x%llx\n", revoc_time);
408 /*
409 * TODO: compare signing timestamp in sinfo
410 * with revocation time
411 */
412
413 revoked = true;
414 free(hash);
415 goto out;
416 }
417 free(hash);
418 hash = NULL;
419 }
420out:
421 EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
422 return !revoked;
423}
424
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900425/*
426 * efi_signature_verify - verify signatures with db and dbx
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900427 * @regs: List of regions to be authenticated
428 * @msg: Signature
429 * @db: Signature database for trusted certificates
430 * @dbx: Revocation signature database
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900431 *
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900432 * All the signature pointed to by @msg against image pointed to by @regs
433 * will be verified by signature database pointed to by @db and @dbx.
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900434 *
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900435 * Return: true if verification for all signatures passed, false otherwise
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900436 */
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900437bool efi_signature_verify(struct efi_image_regions *regs,
438 struct pkcs7_message *msg,
439 struct efi_signature_store *db,
440 struct efi_signature_store *dbx)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900441{
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900442 struct pkcs7_signed_info *sinfo;
443 struct x509_certificate *signer, *root;
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900444 bool verified = false;
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900445 int ret;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900446
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900447 EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, dbx);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900448
AKASHI Takahirode924072020-07-08 14:01:57 +0900449 if (!regs || !msg || !db || !db->sig_data_list)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900450 goto out;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900451
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900452 for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900453 EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900454 sinfo->sig->hash_algo, sinfo->sig->pkey_algo);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900455
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900456 /*
457 * only for authenticated variable.
458 *
459 * If this function is called for image,
460 * hash calculation will be done in
461 * pkcs7_verify_one().
462 */
463 if (!msg->data &&
464 !efi_hash_regions(regs->reg, regs->num,
465 (void **)&sinfo->sig->digest, NULL)) {
466 EFI_PRINT("Digesting an image failed\n");
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900467 goto out;
468 }
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900469
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900470 EFI_PRINT("Verifying certificate chain\n");
471 signer = NULL;
472 ret = pkcs7_verify_one(msg, sinfo, &signer);
473 if (ret == -ENOPKG)
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900474 continue;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900475
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900476 if (ret < 0 || !signer)
477 goto out;
478
479 if (sinfo->blacklisted)
480 goto out;
481
482 EFI_PRINT("Verifying last certificate in chain\n");
483 if (signer->self_signed) {
484 if (efi_lookup_certificate(signer, db))
485 if (efi_signature_check_revocation(sinfo,
486 signer, dbx))
AKASHI Takahiro16411802020-08-14 14:39:23 +0900487 break;
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900488 } else if (efi_verify_certificate(signer, db, &root)) {
489 bool check;
490
491 check = efi_signature_check_revocation(sinfo, root,
492 dbx);
493 x509_free_certificate(root);
494 if (check)
AKASHI Takahiro16411802020-08-14 14:39:23 +0900495 break;
AKASHI Takahiro14afd062020-07-21 19:35:22 +0900496 }
497
498 EFI_PRINT("Certificate chain didn't reach trusted CA\n");
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900499 }
AKASHI Takahiro16411802020-08-14 14:39:23 +0900500 if (sinfo)
501 verified = true;
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900502out:
503 EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
504 return verified;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900505}
506
507/**
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900508 * efi_signature_check_signers - check revocation against all signers with dbx
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900509 * @msg: Signature
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900510 * @dbx: Revocation signature database
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900511 *
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900512 * Determine if none of signers' certificates in @msg are revoked
513 * by signature database pointed to by @dbx.
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900514 *
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900515 * Return: true if all signers passed, false otherwise.
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900516 */
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900517bool efi_signature_check_signers(struct pkcs7_message *msg,
518 struct efi_signature_store *dbx)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900519{
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900520 struct pkcs7_signed_info *sinfo;
521 bool revoked = false;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900522
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900523 EFI_PRINT("%s: Enter, %p, %p\n", __func__, msg, dbx);
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900524
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900525 if (!msg || !dbx)
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900526 goto out;
527
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900528 for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
529 if (sinfo->signer &&
530 !efi_signature_check_revocation(sinfo, sinfo->signer,
531 dbx)) {
532 revoked = true;
533 break;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900534 }
535 }
536out:
AKASHI Takahiro4154b642020-07-08 14:01:56 +0900537 EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
538 return !revoked;
AKASHI Takahiro1faaca42020-04-14 11:51:39 +0900539}
540
541/**
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900542 * efi_sigstore_free - free signature store
543 * @sigstore: Pointer to signature store structure
544 *
545 * Feee all the memories held in signature store and itself,
546 * which were allocated by efi_sigstore_parse_sigdb().
547 */
548void efi_sigstore_free(struct efi_signature_store *sigstore)
549{
550 struct efi_signature_store *sigstore_next;
551 struct efi_sig_data *sig_data, *sig_data_next;
552
553 while (sigstore) {
554 sigstore_next = sigstore->next;
555
556 sig_data = sigstore->sig_data_list;
557 while (sig_data) {
558 sig_data_next = sig_data->next;
559 free(sig_data->data);
560 free(sig_data);
561 sig_data = sig_data_next;
562 }
563
564 free(sigstore);
565 sigstore = sigstore_next;
566 }
567}
568
569/**
570 * efi_sigstore_parse_siglist - parse a signature list
571 * @name: Pointer to signature list
572 *
573 * Parse signature list and instantiate a signature store structure.
574 * Signature database is a simple concatenation of one or more
575 * signature list(s).
576 *
577 * Return: Pointer to signature store on success, NULL on error
578 */
579static struct efi_signature_store *
580efi_sigstore_parse_siglist(struct efi_signature_list *esl)
581{
582 struct efi_signature_store *siglist = NULL;
583 struct efi_sig_data *sig_data, *sig_data_next;
584 struct efi_signature_data *esd;
585 size_t left;
586
587 /*
588 * UEFI specification defines certificate types:
589 * for non-signed images,
590 * EFI_CERT_SHA256_GUID
591 * EFI_CERT_RSA2048_GUID
592 * EFI_CERT_RSA2048_SHA256_GUID
593 * EFI_CERT_SHA1_GUID
594 * EFI_CERT_RSA2048_SHA_GUID
595 * EFI_CERT_SHA224_GUID
596 * EFI_CERT_SHA384_GUID
597 * EFI_CERT_SHA512_GUID
598 *
599 * for signed images,
600 * EFI_CERT_X509_GUID
601 * NOTE: Each certificate will normally be in a separate
602 * EFI_SIGNATURE_LIST as the size may vary depending on
603 * its algo's.
604 *
605 * for timestamp revocation of certificate,
606 * EFI_CERT_X509_SHA512_GUID
607 * EFI_CERT_X509_SHA256_GUID
608 * EFI_CERT_X509_SHA384_GUID
609 */
610
611 if (esl->signature_list_size
612 <= (sizeof(*esl) + esl->signature_header_size)) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900613 EFI_PRINT("Siglist in wrong format\n");
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900614 return NULL;
615 }
616
617 /* Create a head */
618 siglist = calloc(sizeof(*siglist), 1);
619 if (!siglist) {
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 memcpy(&siglist->sig_type, &esl->signature_type, sizeof(efi_guid_t));
624
625 /* Go through the list */
626 sig_data_next = NULL;
627 left = esl->signature_list_size
628 - (sizeof(*esl) + esl->signature_header_size);
629 esd = (struct efi_signature_data *)
630 ((u8 *)esl + sizeof(*esl) + esl->signature_header_size);
631
AKASHI Takahiroa075aa32020-04-21 09:38:57 +0900632 while (left > 0) {
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900633 /* Signature must exist if there is remaining data. */
634 if (left < esl->signature_size) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900635 EFI_PRINT("Certificate is too small\n");
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900636 goto err;
637 }
638
639 sig_data = calloc(esl->signature_size
640 - sizeof(esd->signature_owner), 1);
641 if (!sig_data) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900642 EFI_PRINT("Out of memory\n");
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900643 goto err;
644 }
645
646 /* Append signature data */
647 memcpy(&sig_data->owner, &esd->signature_owner,
648 sizeof(efi_guid_t));
649 sig_data->size = esl->signature_size
650 - sizeof(esd->signature_owner);
651 sig_data->data = malloc(sig_data->size);
652 if (!sig_data->data) {
AKASHI Takahiro10a9fa82020-06-09 14:09:33 +0900653 EFI_PRINT("Out of memory\n");
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900654 goto err;
655 }
656 memcpy(sig_data->data, esd->signature_data, sig_data->size);
657
658 sig_data->next = sig_data_next;
659 sig_data_next = sig_data;
660
661 /* Next */
662 esd = (struct efi_signature_data *)
663 ((u8 *)esd + esl->signature_size);
664 left -= esl->signature_size;
665 }
666 siglist->sig_data_list = sig_data_next;
667
668 return siglist;
669
670err:
671 efi_sigstore_free(siglist);
672
673 return NULL;
674}
675
676/**
Sughosh Ganufa0faa62020-12-30 19:27:08 +0530677 * efi_sigstore_parse_sigdb - parse the signature list and populate
678 * the signature store
679 *
680 * @sig_list: Pointer to the signature list
681 * @size: Size of the signature list
682 *
683 * Parse the efi signature list and instantiate a signature store
684 * structure.
685 *
686 * Return: Pointer to signature store on success, NULL on error
687 */
688struct efi_signature_store *efi_build_signature_store(void *sig_list,
689 efi_uintn_t size)
690{
691 struct efi_signature_list *esl;
692 struct efi_signature_store *sigstore = NULL, *siglist;
693
694 esl = sig_list;
695 while (size > 0) {
696 /* List must exist if there is remaining data. */
697 if (size < sizeof(*esl)) {
698 EFI_PRINT("Signature list in wrong format\n");
699 goto err;
700 }
701
702 if (size < esl->signature_list_size) {
703 EFI_PRINT("Signature list in wrong format\n");
704 goto err;
705 }
706
707 /* Parse a single siglist. */
708 siglist = efi_sigstore_parse_siglist(esl);
709 if (!siglist) {
710 EFI_PRINT("Parsing of signature list of failed\n");
711 goto err;
712 }
713
714 /* Append siglist */
715 siglist->next = sigstore;
716 sigstore = siglist;
717
718 /* Next */
719 size -= esl->signature_list_size;
720 esl = (void *)esl + esl->signature_list_size;
721 }
722 free(sig_list);
723
724 return sigstore;
725
726err:
727 efi_sigstore_free(sigstore);
728 free(sig_list);
729
730 return NULL;
731}
732
733/**
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900734 * efi_sigstore_parse_sigdb - parse a signature database variable
735 * @name: Variable's name
736 *
737 * Read in a value of signature database variable pointed to by
738 * @name, parse it and instantiate a signature store structure.
739 *
740 * Return: Pointer to signature store on success, NULL on error
741 */
742struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name)
743{
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900744 const efi_guid_t *vendor;
745 void *db;
746 efi_uintn_t db_size;
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900747
Heinrich Schuchardtcaeb73b2021-09-09 08:25:08 +0200748 vendor = efi_auth_var_get_guid(name);
749 db = efi_get_var(name, vendor, &db_size);
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900750 if (!db) {
Heinrich Schuchardtcaeb73b2021-09-09 08:25:08 +0200751 EFI_PRINT("variable, %ls, not found\n", name);
752 return calloc(sizeof(struct efi_signature_store), 1);
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900753 }
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900754
Sughosh Ganufa0faa62020-12-30 19:27:08 +0530755 return efi_build_signature_store(db, db_size);
AKASHI Takahirod2cefc82020-04-14 11:51:40 +0900756}