]> git.proxmox.com Git - grub2.git/blame - grub-core/commands/verify.c
Add gcc_struct to all packed structures when compiling with mingw.
[grub2.git] / grub-core / commands / verify.c
CommitLineData
5e3b8dcb
VS
1/*
2 * GRUB -- GRand Unified Bootloader
1a78d573 3 * Copyright (C) 2013 Free Software Foundation, Inc.
5e3b8dcb
VS
4 *
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <grub/types.h>
20#include <grub/misc.h>
21#include <grub/mm.h>
22#include <grub/err.h>
23#include <grub/dl.h>
24#include <grub/file.h>
25#include <grub/command.h>
26#include <grub/crypto.h>
27#include <grub/i18n.h>
28#include <grub/gcrypt/gcrypt.h>
29#include <grub/pubkey.h>
30#include <grub/env.h>
31#include <grub/kernel.h>
0d711431 32#include <grub/extcmd.h>
5e3b8dcb
VS
33
34GRUB_MOD_LICENSE ("GPLv3+");
35
0d711431
VS
36enum
37 {
38 OPTION_SKIP_SIG = 0
39 };
40
41static const struct grub_arg_option options[] =
42 {
43 {"skip-sig", 's', 0,
44 N_("Skip signature-checking of the signature file."), 0, ARG_TYPE_NONE},
45 {0, 0, 0, 0, 0, 0}
46 };
47
5e3b8dcb
VS
48static grub_err_t
49read_packet_header (grub_file_t sig, grub_uint8_t *out_type, grub_size_t *len)
50{
51 grub_uint8_t type;
52 grub_uint8_t l;
53 grub_uint16_t l16;
54 grub_uint32_t l32;
55
56 /* New format. */
57 switch (grub_file_read (sig, &type, sizeof (type)))
58 {
59 case 1:
60 break;
61 case 0:
62 {
63 *out_type = 0xff;
64 return 0;
65 }
66 default:
67 if (grub_errno)
68 return grub_errno;
f8e98fee
VS
69 /* TRANSLATORS: it's about GNUPG signatures. */
70 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
71 }
72
73 if (type == 0)
74 {
75 *out_type = 0xfe;
76 return 0;
77 }
78
79 if (!(type & 0x80))
f8e98fee 80 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
81 if (type & 0x40)
82 {
83 *out_type = (type & 0x3f);
84 if (grub_file_read (sig, &l, sizeof (l)) != 1)
f8e98fee 85 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
86 if (l < 192)
87 {
88 *len = l;
89 return 0;
90 }
91 if (l < 224)
92 {
52eab656 93 *len = (l - 192) << GRUB_CHAR_BIT;
5e3b8dcb 94 if (grub_file_read (sig, &l, sizeof (l)) != 1)
f8e98fee 95 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
96 *len |= l;
97 return 0;
98 }
99 if (l == 255)
100 {
101 if (grub_file_read (sig, &l32, sizeof (l32)) != sizeof (l32))
f8e98fee 102 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
103 *len = grub_be_to_cpu32 (l32);
104 return 0;
105 }
f8e98fee 106 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
107 }
108 *out_type = ((type >> 2) & 0xf);
109 switch (type & 0x3)
110 {
111 case 0:
112 if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l))
f8e98fee 113 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
114 *len = l;
115 return 0;
116 case 1:
117 if (grub_file_read (sig, &l16, sizeof (l16)) != sizeof (l16))
f8e98fee 118 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
119 *len = grub_be_to_cpu16 (l16);
120 return 0;
121 case 2:
122 if (grub_file_read (sig, &l32, sizeof (l32)) != sizeof (l32))
f8e98fee 123 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
124 *len = grub_be_to_cpu32 (l32);
125 return 0;
126 }
f8e98fee 127 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
128}
129
130struct signature_v4_header
131{
132 grub_uint8_t type;
133 grub_uint8_t pkeyalgo;
134 grub_uint8_t hash;
135 grub_uint16_t hashed_sub;
7e47e27b 136} GRUB_PACKED;
5e3b8dcb
VS
137
138const char *hashes[] = {
40f1c000
AB
139 [0x01] = "md5",
140 [0x02] = "sha1",
141 [0x03] = "ripemd160",
d7a6506e
VS
142 [0x08] = "sha256",
143 [0x09] = "sha384",
144 [0x0a] = "sha512",
145 [0x0b] = "sha224"
5e3b8dcb
VS
146};
147
1106c3f0
VS
148struct gcry_pk_spec *grub_crypto_pk_dsa;
149struct gcry_pk_spec *grub_crypto_pk_ecdsa;
150struct gcry_pk_spec *grub_crypto_pk_rsa;
151
152static int
153dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
154 const gcry_md_spec_t *hash, struct grub_public_subkey *sk);
155static int
156rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
157 const gcry_md_spec_t *hash, struct grub_public_subkey *sk);
158
5e3b8dcb
VS
159struct
160{
161 const char *name;
162 grub_size_t nmpisig;
163 grub_size_t nmpipub;
1106c3f0
VS
164 struct gcry_pk_spec **algo;
165 int (*pad) (gcry_mpi_t *hmpi, grub_uint8_t *hval,
166 const gcry_md_spec_t *hash, struct grub_public_subkey *sk);
167 const char *module;
5e3b8dcb
VS
168} pkalgos[] =
169 {
1106c3f0
VS
170 [1] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" },
171 [3] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" },
172 [17] = { "dsa", 2, 4, &grub_crypto_pk_dsa, dsa_pad, "gcry_dsa" },
5e3b8dcb
VS
173 };
174
175struct grub_public_key
176{
177 struct grub_public_key *next;
178 struct grub_public_subkey *subkeys;
179};
180
181struct grub_public_subkey
182{
183 struct grub_public_subkey *next;
184 grub_uint8_t type;
185 grub_uint32_t fingerprint[5];
186 gcry_mpi_t mpis[10];
187};
188
189static void
190free_pk (struct grub_public_key *pk)
191{
192 struct grub_public_subkey *nsk, *sk;
193 for (sk = pk->subkeys; sk; sk = nsk)
194 {
7bbb60cf
VS
195 grub_size_t i;
196 for (i = 0; i < ARRAY_SIZE (sk->mpis); i++)
197 if (sk->mpis[i])
198 gcry_mpi_release (sk->mpis[i]);
5e3b8dcb
VS
199 nsk = sk->next;
200 grub_free (sk);
201 }
202 grub_free (pk);
203}
204
4f84ae0e
VS
205#define READBUF_SIZE 4096
206
5e3b8dcb
VS
207struct grub_public_key *
208grub_load_public_key (grub_file_t f)
209{
210 grub_err_t err;
211 struct grub_public_key *ret;
212 struct grub_public_subkey **last = 0;
4f84ae0e
VS
213 void *fingerprint_context = NULL;
214 grub_uint8_t *buffer = NULL;
5e3b8dcb
VS
215
216 ret = grub_zalloc (sizeof (*ret));
217 if (!ret)
1dcb2715
VS
218 {
219 grub_free (fingerprint_context);
220 return NULL;
221 }
5e3b8dcb 222
4f84ae0e
VS
223 buffer = grub_zalloc (READBUF_SIZE);
224 fingerprint_context = grub_zalloc (GRUB_MD_SHA1->contextsize);
225
226 if (!buffer || !fingerprint_context)
227 goto fail;
228
5e3b8dcb
VS
229 last = &ret->subkeys;
230
231 while (1)
232 {
233 grub_uint8_t type;
234 grub_size_t len;
235 grub_uint8_t v, pk;
236 grub_uint32_t creation_time;
237 grub_off_t pend;
238 struct grub_public_subkey *sk;
239 grub_size_t i;
240 grub_uint16_t len_be;
5e3b8dcb
VS
241
242 err = read_packet_header (f, &type, &len);
243
244 if (err)
245 goto fail;
246 if (type == 0xfe)
247 continue;
248 if (type == 0xff)
1dcb2715
VS
249 {
250 grub_free (fingerprint_context);
7bbb60cf 251 grub_free (buffer);
1dcb2715
VS
252 return ret;
253 }
5e3b8dcb
VS
254
255 grub_dprintf ("crypt", "len = %x\n", (int) len);
256
257 pend = grub_file_tell (f) + len;
258 if (type != 6 && type != 14
259 && type != 5 && type != 7)
260 {
261 grub_file_seek (f, pend);
262 continue;
263 }
264
265 if (grub_file_read (f, &v, sizeof (v)) != sizeof (v))
266 {
f8e98fee 267 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
268 goto fail;
269 }
270
271 grub_dprintf ("crypt", "v = %x\n", v);
272
273 if (v != 4)
274 {
f8e98fee 275 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
276 goto fail;
277 }
278 if (grub_file_read (f, &creation_time, sizeof (creation_time)) != sizeof (creation_time))
279 {
f8e98fee 280 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
281 goto fail;
282 }
283
284 grub_dprintf ("crypt", "time = %x\n", creation_time);
285
286 if (grub_file_read (f, &pk, sizeof (pk)) != sizeof (pk))
287 {
f8e98fee 288 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
289 goto fail;
290 }
291
292 grub_dprintf ("crypt", "pk = %x\n", pk);
293
294 if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL)
295 {
296 grub_file_seek (f, pend);
297 continue;
298 }
299
300 sk = grub_zalloc (sizeof (struct grub_public_subkey));
301 if (!sk)
302 goto fail;
303
304 grub_memset (fingerprint_context, 0, sizeof (fingerprint_context));
305 GRUB_MD_SHA1->init (fingerprint_context);
306 GRUB_MD_SHA1->write (fingerprint_context, "\x99", 1);
307 len_be = grub_cpu_to_be16 (len);
308 GRUB_MD_SHA1->write (fingerprint_context, &len_be, sizeof (len_be));
309 GRUB_MD_SHA1->write (fingerprint_context, &v, sizeof (v));
310 GRUB_MD_SHA1->write (fingerprint_context, &creation_time, sizeof (creation_time));
311 GRUB_MD_SHA1->write (fingerprint_context, &pk, sizeof (pk));
312
313 for (i = 0; i < pkalgos[pk].nmpipub; i++)
314 {
315 grub_uint16_t l;
316 grub_size_t lb;
5e3b8dcb
VS
317 if (grub_file_read (f, &l, sizeof (l)) != sizeof (l))
318 {
f8e98fee 319 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
320 goto fail;
321 }
322
52eab656 323 lb = (grub_be_to_cpu16 (l) + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT;
4f84ae0e 324 if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
5e3b8dcb 325 {
f8e98fee 326 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
327 goto fail;
328 }
329 if (grub_file_read (f, buffer + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
330 {
f8e98fee 331 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
332 goto fail;
333 }
334 grub_memcpy (buffer, &l, sizeof (l));
335
336 GRUB_MD_SHA1->write (fingerprint_context, buffer, lb + sizeof (grub_uint16_t));
337
338 if (gcry_mpi_scan (&sk->mpis[i], GCRYMPI_FMT_PGP,
339 buffer, lb + sizeof (grub_uint16_t), 0))
340 {
f8e98fee 341 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
342 goto fail;
343 }
344 }
345
346 GRUB_MD_SHA1->final (fingerprint_context);
347
348 grub_memcpy (sk->fingerprint, GRUB_MD_SHA1->read (fingerprint_context), 20);
349
350 *last = sk;
351 last = &sk->next;
352
5e3b8dcb
VS
353 grub_dprintf ("crypt", "actual pos: %x, expected: %x\n", (int)grub_file_tell (f), (int)pend);
354
355 grub_file_seek (f, pend);
356 }
357 fail:
358 free_pk (ret);
1dcb2715 359 grub_free (fingerprint_context);
4f84ae0e 360 grub_free (buffer);
5e3b8dcb
VS
361 return NULL;
362}
363
364struct grub_public_key *grub_pk_trusted;
365
366struct grub_public_subkey *
367grub_crypto_pk_locate_subkey (grub_uint64_t keyid, struct grub_public_key *pkey)
368{
369 struct grub_public_subkey *sk;
370 for (sk = pkey->subkeys; sk; sk = sk->next)
371 if (grub_memcmp (sk->fingerprint + 3, &keyid, 8) == 0)
372 return sk;
373 return 0;
374}
375
376struct grub_public_subkey *
377grub_crypto_pk_locate_subkey_in_trustdb (grub_uint64_t keyid)
378{
379 struct grub_public_key *pkey;
380 struct grub_public_subkey *sk;
381 for (pkey = grub_pk_trusted; pkey; pkey = pkey->next)
382 {
383 sk = grub_crypto_pk_locate_subkey (keyid, pkey);
384 if (sk)
385 return sk;
386 }
387 return 0;
388}
389
1106c3f0
VS
390
391static int
392dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
393 const gcry_md_spec_t *hash, struct grub_public_subkey *sk)
394{
395 unsigned nbits = gcry_mpi_get_nbits (sk->mpis[1]);
396 grub_dprintf ("crypt", "must be %u bits got %d bits\n", nbits,
397 (int)(8 * hash->mdlen));
398 return gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, hval,
399 nbits / 8 < (unsigned) hash->mdlen ? nbits / 8
400 : (unsigned) hash->mdlen, 0);
401}
402
403static int
404rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
405 const gcry_md_spec_t *hash, struct grub_public_subkey *sk)
406{
407 grub_size_t tlen, emlen, fflen;
408 grub_uint8_t *em, *emptr;
409 unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]);
410 int ret;
411 tlen = hash->mdlen + hash->asnlen;
412 emlen = (nbits + 7) / 8;
413 if (emlen < tlen + 11)
414 return 1;
415
416 em = grub_malloc (emlen);
417 if (!em)
418 return 1;
419
420 em[0] = 0x00;
421 em[1] = 0x01;
422 fflen = emlen - tlen - 3;
423 for (emptr = em + 2; emptr < em + 2 + fflen; emptr++)
424 *emptr = 0xff;
425 *emptr++ = 0x00;
426 grub_memcpy (emptr, hash->asnoid, hash->asnlen);
427 emptr += hash->asnlen;
428 grub_memcpy (emptr, hval, hash->mdlen);
429
430 ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0);
431 grub_free (em);
432 return ret;
433}
434
1a78d573
VS
435static grub_err_t
436grub_verify_signature_real (char *buf, grub_size_t size,
437 grub_file_t f, grub_file_t sig,
438 struct grub_public_key *pkey)
5e3b8dcb
VS
439{
440 grub_size_t len;
441 grub_uint8_t v;
442 grub_uint8_t h;
443 grub_uint8_t t;
444 grub_uint8_t pk;
445 const gcry_md_spec_t *hash;
446 struct signature_v4_header v4;
447 grub_err_t err;
448 grub_size_t i;
449 gcry_mpi_t mpis[10];
450 grub_uint8_t type;
451
452 err = read_packet_header (sig, &type, &len);
453 if (err)
454 return err;
455
456 if (type != 0x2)
f8e98fee 457 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
458
459 if (grub_file_read (sig, &v, sizeof (v)) != sizeof (v))
f8e98fee 460 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
461
462 if (v != 4)
f8e98fee 463 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
464
465 if (grub_file_read (sig, &v4, sizeof (v4)) != sizeof (v4))
f8e98fee 466 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
467
468 h = v4.hash;
469 t = v4.type;
470 pk = v4.pkeyalgo;
471
472 if (t != 0)
f8e98fee 473 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
474
475 if (h >= ARRAY_SIZE (hashes) || hashes[h] == NULL)
476 return grub_error (GRUB_ERR_BAD_SIGNATURE, "unknown hash");
477
478 if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL)
f8e98fee 479 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
5e3b8dcb
VS
480
481 hash = grub_crypto_lookup_md_by_name (hashes[h]);
482 if (!hash)
483 return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%s' not loaded", hashes[h]);
484
485 grub_dprintf ("crypt", "alive\n");
486
487 {
1dcb2715 488 void *context = NULL;
5e3b8dcb
VS
489 unsigned char *hval;
490 grub_ssize_t rem = grub_be_to_cpu16 (v4.hashed_sub);
491 grub_uint32_t headlen = grub_cpu_to_be32 (rem + 6);
492 grub_uint8_t s;
493 grub_uint16_t unhashed_sub;
494 grub_ssize_t r;
495 grub_uint8_t hash_start[2];
496 gcry_mpi_t hmpi;
497 grub_uint64_t keyid = 0;
498 struct grub_public_subkey *sk;
4f84ae0e 499 grub_uint8_t *readbuf = NULL;
5e3b8dcb 500
1dcb2715 501 context = grub_zalloc (hash->contextsize);
4f84ae0e
VS
502 readbuf = grub_zalloc (READBUF_SIZE);
503 if (!context || !readbuf)
504 goto fail;
1dcb2715 505
5e3b8dcb 506 hash->init (context);
1a78d573
VS
507 if (buf)
508 hash->write (context, buf, size);
509 else
510 while (1)
511 {
4f84ae0e 512 r = grub_file_read (f, readbuf, READBUF_SIZE);
1a78d573 513 if (r < 0)
1dcb2715 514 goto fail;
1a78d573
VS
515 if (r == 0)
516 break;
517 hash->write (context, readbuf, r);
518 }
5e3b8dcb
VS
519
520 hash->write (context, &v, sizeof (v));
521 hash->write (context, &v4, sizeof (v4));
522 while (rem)
523 {
4f84ae0e
VS
524 r = grub_file_read (sig, readbuf,
525 rem < READBUF_SIZE ? rem : READBUF_SIZE);
5e3b8dcb 526 if (r < 0)
1dcb2715 527 goto fail;
5e3b8dcb
VS
528 if (r == 0)
529 break;
530 hash->write (context, readbuf, r);
531 rem -= r;
532 }
533 hash->write (context, &v, sizeof (v));
534 s = 0xff;
535 hash->write (context, &s, sizeof (s));
536 hash->write (context, &headlen, sizeof (headlen));
537 r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub));
538 if (r != sizeof (unhashed_sub))
1dcb2715 539 goto fail;
5e3b8dcb 540 {
5e3b8dcb
VS
541 grub_uint8_t *ptr;
542 grub_uint32_t l;
543 rem = grub_be_to_cpu16 (unhashed_sub);
4f84ae0e 544 if (rem > READBUF_SIZE)
1dcb2715 545 goto fail;
5e3b8dcb
VS
546 r = grub_file_read (sig, readbuf, rem);
547 if (r != rem)
1dcb2715 548 goto fail;
5e3b8dcb
VS
549 for (ptr = readbuf; ptr < readbuf + rem; ptr += l)
550 {
551 if (*ptr < 192)
552 l = *ptr++;
553 else if (*ptr < 255)
554 {
555 if (ptr + 1 >= readbuf + rem)
556 break;
52eab656 557 l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192;
5e3b8dcb
VS
558 ptr += 2;
559 }
560 else
561 {
562 if (ptr + 5 >= readbuf + rem)
563 break;
564 l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1));
565 ptr += 5;
566 }
567 if (*ptr == 0x10 && l >= 8)
568 keyid = grub_get_unaligned64 (ptr + 1);
569 }
570 }
571
572 hash->final (context);
573
574 grub_dprintf ("crypt", "alive\n");
575
576 hval = hash->read (context);
577
578 if (grub_file_read (sig, hash_start, sizeof (hash_start)) != sizeof (hash_start))
1dcb2715 579 goto fail;
5e3b8dcb 580 if (grub_memcmp (hval, hash_start, sizeof (hash_start)) != 0)
1dcb2715 581 goto fail;
5e3b8dcb
VS
582
583 grub_dprintf ("crypt", "@ %x\n", (int)grub_file_tell (sig));
584
585 for (i = 0; i < pkalgos[pk].nmpisig; i++)
586 {
587 grub_uint16_t l;
588 grub_size_t lb;
5e3b8dcb
VS
589 grub_dprintf ("crypt", "alive\n");
590 if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l))
1dcb2715 591 goto fail;
5e3b8dcb
VS
592 grub_dprintf ("crypt", "alive\n");
593 lb = (grub_be_to_cpu16 (l) + 7) / 8;
594 grub_dprintf ("crypt", "l = 0x%04x\n", grub_be_to_cpu16 (l));
4f84ae0e 595 if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
1dcb2715 596 goto fail;
5e3b8dcb 597 grub_dprintf ("crypt", "alive\n");
4f84ae0e 598 if (grub_file_read (sig, readbuf + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
1dcb2715 599 goto fail;
5e3b8dcb 600 grub_dprintf ("crypt", "alive\n");
4f84ae0e 601 grub_memcpy (readbuf, &l, sizeof (l));
5e3b8dcb
VS
602 grub_dprintf ("crypt", "alive\n");
603
604 if (gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP,
4f84ae0e 605 readbuf, lb + sizeof (grub_uint16_t), 0))
1dcb2715 606 goto fail;
5e3b8dcb
VS
607 grub_dprintf ("crypt", "alive\n");
608 }
609
610 if (pkey)
611 sk = grub_crypto_pk_locate_subkey (keyid, pkey);
612 else
613 sk = grub_crypto_pk_locate_subkey_in_trustdb (keyid);
614 if (!sk)
1dcb2715
VS
615 {
616 /* TRANSLATORS: %08x is 32-bit key id. */
617 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("public key %08x not found"),
618 keyid);
619 goto fail;
620 }
5e3b8dcb 621
1106c3f0 622 if (pkalgos[pk].pad (&hmpi, hval, hash, sk))
1dcb2715
VS
623 goto fail;
624 if (!*pkalgos[pk].algo)
625 {
626 grub_dl_load (pkalgos[pk].module);
627 grub_errno = GRUB_ERR_NONE;
628 }
629
1106c3f0 630 if (!*pkalgos[pk].algo)
1dcb2715
VS
631 {
632 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("module `%s' isn't loaded"),
633 pkalgos[pk].module);
634 goto fail;
635 }
1106c3f0 636 if ((*pkalgos[pk].algo)->verify (0, hmpi, mpis, sk->mpis, 0, 0))
1dcb2715
VS
637 goto fail;
638
7bbb60cf
VS
639 grub_free (context);
640 grub_free (readbuf);
641
1dcb2715
VS
642 return GRUB_ERR_NONE;
643
644 fail:
645 grub_free (context);
4f84ae0e 646 grub_free (readbuf);
1dcb2715 647 if (!grub_errno)
f8e98fee 648 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
1dcb2715 649 return grub_errno;
5e3b8dcb 650 }
5e3b8dcb
VS
651}
652
1a78d573
VS
653grub_err_t
654grub_verify_signature (grub_file_t f, grub_file_t sig,
655 struct grub_public_key *pkey)
656{
657 return grub_verify_signature_real (0, 0, f, sig, pkey);
658}
659
5e3b8dcb 660static grub_err_t
0d711431
VS
661grub_cmd_trust (grub_extcmd_context_t ctxt,
662 int argc, char **args)
5e3b8dcb
VS
663{
664 grub_file_t pkf;
665 struct grub_public_key *pk = NULL;
666
667 if (argc < 1)
f8e98fee 668 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
5e3b8dcb 669
0d711431
VS
670 grub_file_filter_disable_compression ();
671 if (ctxt->state[OPTION_SKIP_SIG].set)
672 grub_file_filter_disable_pubkey ();
5e3b8dcb
VS
673 pkf = grub_file_open (args[0]);
674 if (!pkf)
675 return grub_errno;
676 pk = grub_load_public_key (pkf);
677 if (!pk)
678 {
679 grub_file_close (pkf);
680 return grub_errno;
681 }
682 grub_file_close (pkf);
683
684 pk->next = grub_pk_trusted;
685 grub_pk_trusted = pk;
686
687 return GRUB_ERR_NONE;
688}
689
adcc6020
VS
690static grub_err_t
691grub_cmd_list (grub_command_t cmd __attribute__ ((unused)),
692 int argc __attribute__ ((unused)),
693 char **args __attribute__ ((unused)))
694{
695 struct grub_public_key *pk = NULL;
696 struct grub_public_subkey *sk = NULL;
697
698 for (pk = grub_pk_trusted; pk; pk = pk->next)
699 for (sk = pk->subkeys; sk; sk = sk->next)
700 {
701 unsigned i;
702 for (i = 0; i < 20; i += 2)
703 grub_printf ("%02x%02x ", ((grub_uint8_t *) sk->fingerprint)[i],
704 ((grub_uint8_t *) sk->fingerprint)[i + 1]);
705 grub_printf ("\n");
706 }
707
708 return GRUB_ERR_NONE;
709}
710
5e3b8dcb
VS
711static grub_err_t
712grub_cmd_distrust (grub_command_t cmd __attribute__ ((unused)),
713 int argc, char **args)
714{
715 grub_uint32_t keyid, keyid_be;
716 struct grub_public_key **pkey;
717 struct grub_public_subkey *sk;
718
719 if (argc < 1)
f8e98fee 720 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
5e3b8dcb
VS
721 keyid = grub_strtoull (args[0], 0, 16);
722 if (grub_errno)
723 return grub_errno;
724 keyid_be = grub_cpu_to_be32 (keyid);
725
726 for (pkey = &grub_pk_trusted; *pkey; pkey = &((*pkey)->next))
727 {
728 struct grub_public_key *next;
729 for (sk = (*pkey)->subkeys; sk; sk = sk->next)
730 if (grub_memcmp (sk->fingerprint + 4, &keyid_be, 4) == 0)
731 break;
732 if (!sk)
733 continue;
734 next = (*pkey)->next;
735 free_pk (*pkey);
736 *pkey = next;
737 return GRUB_ERR_NONE;
738 }
f8e98fee
VS
739 /* TRANSLATORS: %08x is 32-bit key id. */
740 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("public key %08x not found"), keyid);
5e3b8dcb
VS
741}
742
743static grub_err_t
0d711431 744grub_cmd_verify_signature (grub_extcmd_context_t ctxt,
5e3b8dcb
VS
745 int argc, char **args)
746{
7bbb60cf
VS
747 grub_file_t f = NULL, sig = NULL;
748 grub_err_t err = GRUB_ERR_NONE;
5e3b8dcb
VS
749 struct grub_public_key *pk = NULL;
750
751 grub_dprintf ("crypt", "alive\n");
752
753 if (argc < 2)
f8e98fee 754 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
5e3b8dcb
VS
755
756 grub_dprintf ("crypt", "alive\n");
757
758 if (argc > 2)
759 {
760 grub_file_t pkf;
0d711431
VS
761 grub_file_filter_disable_compression ();
762 if (ctxt->state[OPTION_SKIP_SIG].set)
763 grub_file_filter_disable_pubkey ();
5e3b8dcb
VS
764 pkf = grub_file_open (args[2]);
765 if (!pkf)
766 return grub_errno;
767 pk = grub_load_public_key (pkf);
768 if (!pk)
769 {
770 grub_file_close (pkf);
771 return grub_errno;
772 }
773 grub_file_close (pkf);
774 }
775
776 grub_file_filter_disable_all ();
777 f = grub_file_open (args[0]);
778 if (!f)
7bbb60cf
VS
779 {
780 err = grub_errno;
781 goto fail;
782 }
5e3b8dcb
VS
783
784 grub_file_filter_disable_all ();
785 sig = grub_file_open (args[1]);
786 if (!sig)
787 {
7bbb60cf
VS
788 err = grub_errno;
789 goto fail;
5e3b8dcb
VS
790 }
791
792 err = grub_verify_signature (f, sig, pk);
7bbb60cf
VS
793 fail:
794 if (sig)
795 grub_file_close (sig);
796 if (f)
797 grub_file_close (f);
798 if (pk)
799 free_pk (pk);
5e3b8dcb
VS
800 return err;
801}
802
803static int sec = 0;
804
1a78d573
VS
805static grub_ssize_t
806verified_read (struct grub_file *file, char *buf, grub_size_t len)
807{
808 grub_memcpy (buf, (char *) file->data + file->offset, len);
809 return len;
810}
811
812static grub_err_t
813verified_close (struct grub_file *file)
814{
815 grub_free (file->data);
816 file->data = 0;
817 return GRUB_ERR_NONE;
818}
819
820struct grub_fs verified_fs =
821{
822 .name = "verified_read",
823 .read = verified_read,
824 .close = verified_close
825};
826
5e3b8dcb
VS
827static grub_file_t
828grub_pubkey_open (grub_file_t io, const char *filename)
829{
830 grub_file_t sig;
831 char *fsuf, *ptr;
832 grub_err_t err;
833 grub_file_filter_t curfilt[GRUB_FILE_FILTER_MAX];
1a78d573 834 grub_file_t ret;
5e3b8dcb
VS
835
836 if (!sec)
837 return io;
1a78d573
VS
838 if (io->device->disk && io->device->disk->id == GRUB_DISK_DEVICE_MEMDISK_ID)
839 return io;
5e3b8dcb
VS
840 fsuf = grub_malloc (grub_strlen (filename) + sizeof (".sig"));
841 if (!fsuf)
842 return NULL;
843 ptr = grub_stpcpy (fsuf, filename);
844 grub_memcpy (ptr, ".sig", sizeof (".sig"));
845
846 grub_memcpy (curfilt, grub_file_filters_enabled,
847 sizeof (curfilt));
848 grub_file_filter_disable_all ();
849 sig = grub_file_open (fsuf);
850 grub_memcpy (grub_file_filters_enabled, curfilt,
851 sizeof (curfilt));
852 grub_free (fsuf);
853 if (!sig)
854 return NULL;
855
1a78d573
VS
856 ret = grub_malloc (sizeof (*ret));
857 if (!ret)
858 return NULL;
859 *ret = *io;
860
861 ret->fs = &verified_fs;
862 ret->not_easily_seekable = 0;
863 if (ret->size >> (sizeof (grub_size_t) * GRUB_CHAR_BIT - 1))
864 {
865 grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
866 "big file signature isn't implemented yet");
867 return NULL;
868 }
869 ret->data = grub_malloc (ret->size);
870 if (!ret->data)
871 {
872 grub_free (ret);
873 return NULL;
874 }
875 if (grub_file_read (io, ret->data, ret->size) != (grub_ssize_t) ret->size)
876 {
877 if (!grub_errno)
878 grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
879 filename);
880 return NULL;
881 }
882
883 err = grub_verify_signature_real (ret->data, ret->size, 0, sig, NULL);
5e3b8dcb
VS
884 grub_file_close (sig);
885 if (err)
886 return NULL;
1a78d573
VS
887 io->device = 0;
888 grub_file_close (io);
889 return ret;
5e3b8dcb
VS
890}
891
892static char *
893grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)),
894 const char *val)
895{
896 sec = (*val == '1') || (*val == 'e');
897 return grub_strdup (sec ? "enforce" : "no");
898}
899
900static grub_ssize_t
901pseudo_read (struct grub_file *file, char *buf, grub_size_t len)
902{
903 grub_memcpy (buf, (grub_uint8_t *) file->data + file->offset, len);
904 return len;
905}
906
907
908/* Filesystem descriptor. */
909struct grub_fs pseudo_fs =
910 {
911 .name = "pseudo",
912 .read = pseudo_read
913};
914
5e3b8dcb 915
0d711431
VS
916static grub_extcmd_t cmd, cmd_trust;
917static grub_command_t cmd_distrust, cmd_list;
5e3b8dcb
VS
918
919GRUB_MOD_INIT(verify)
920{
921 const char *val;
922 struct grub_module_header *header;
923
924 val = grub_env_get ("check_signatures");
925 if (val && (val[0] == '1' || val[0] == 'e'))
926 sec = 1;
927 else
928 sec = 0;
929
930 grub_file_filter_register (GRUB_FILE_FILTER_PUBKEY, grub_pubkey_open);
931
932 grub_register_variable_hook ("check_signatures", 0, grub_env_write_sec);
933 grub_env_export ("check_signatures");
934
935 grub_pk_trusted = 0;
936 FOR_MODULES (header)
937 {
938 struct grub_file pseudo_file;
939 struct grub_public_key *pk = NULL;
940
941 grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
942
943 /* Not an ELF module, skip. */
944 if (header->type != OBJ_TYPE_PUBKEY)
945 continue;
946
947 pseudo_file.fs = &pseudo_fs;
948 pseudo_file.size = (header->size - sizeof (struct grub_module_header));
949 pseudo_file.data = (char *) header + sizeof (struct grub_module_header);
950
951 pk = grub_load_public_key (&pseudo_file);
952 if (!pk)
953 grub_fatal ("error loading initial key: %s\n", grub_errmsg);
954
955 pk->next = grub_pk_trusted;
956 grub_pk_trusted = pk;
957 }
958
959 if (!val)
960 grub_env_set ("check_signatures", grub_pk_trusted ? "enforce" : "no");
961
0d711431
VS
962 cmd = grub_register_extcmd ("verify_detached", grub_cmd_verify_signature, 0,
963 N_("[-s|--skip-sig] FILE SIGNATURE_FILE [PUBKEY_FILE]"),
964 N_("Verify detached signature."),
965 options);
966 cmd_trust = grub_register_extcmd ("trust", grub_cmd_trust, 0,
967 N_("[-s|--skip-sig] PUBKEY_FILE"),
968 N_("Add PKFILE to trusted keys."),
969 options);
adcc6020
VS
970 cmd_list = grub_register_command ("list_trusted", grub_cmd_list,
971 0,
972 N_("List trusted keys."));
5e3b8dcb 973 cmd_distrust = grub_register_command ("distrust", grub_cmd_distrust,
f8e98fee 974 N_("PUBKEY_ID"),
5e3b8dcb
VS
975 N_("Remove KEYID from trusted keys."));
976}
977
978GRUB_MOD_FINI(verify)
979{
980 grub_file_filter_unregister (GRUB_FILE_FILTER_PUBKEY);
0d711431
VS
981 grub_unregister_extcmd (cmd);
982 grub_unregister_extcmd (cmd_trust);
adcc6020 983 grub_unregister_command (cmd_list);
5e3b8dcb
VS
984 grub_unregister_command (cmd_distrust);
985}