Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / commands / verify.c
blob6569391898cac10d91bd3b5e060de510baaa0360
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2013 Free Software Foundation, Inc.
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.
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.
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/>.
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>
32 #include <grub/extcmd.h>
34 GRUB_MOD_LICENSE ("GPLv3+");
36 struct grub_verified
38 grub_file_t file;
39 void *buf;
41 typedef struct grub_verified *grub_verified_t;
43 enum
45 OPTION_SKIP_SIG = 0
48 static const struct grub_arg_option options[] =
50 {"skip-sig", 's', 0,
51 N_("Skip signature-checking of the public key file."), 0, ARG_TYPE_NONE},
52 {0, 0, 0, 0, 0, 0}
55 static grub_err_t
56 read_packet_header (grub_file_t sig, grub_uint8_t *out_type, grub_size_t *len)
58 grub_uint8_t type;
59 grub_uint8_t l;
60 grub_uint16_t l16;
61 grub_uint32_t l32;
63 /* New format. */
64 switch (grub_file_read (sig, &type, sizeof (type)))
66 case 1:
67 break;
68 case 0:
70 *out_type = 0xff;
71 return 0;
73 default:
74 if (grub_errno)
75 return grub_errno;
76 /* TRANSLATORS: it's about GNUPG signatures. */
77 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
80 if (type == 0)
82 *out_type = 0xfe;
83 return 0;
86 if (!(type & 0x80))
87 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
88 if (type & 0x40)
90 *out_type = (type & 0x3f);
91 if (grub_file_read (sig, &l, sizeof (l)) != 1)
92 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
93 if (l < 192)
95 *len = l;
96 return 0;
98 if (l < 224)
100 *len = (l - 192) << GRUB_CHAR_BIT;
101 if (grub_file_read (sig, &l, sizeof (l)) != 1)
102 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
103 *len |= l;
104 return 0;
106 if (l == 255)
108 if (grub_file_read (sig, &l32, sizeof (l32)) != sizeof (l32))
109 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
110 *len = grub_be_to_cpu32 (l32);
111 return 0;
113 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
115 *out_type = ((type >> 2) & 0xf);
116 switch (type & 0x3)
118 case 0:
119 if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l))
120 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
121 *len = l;
122 return 0;
123 case 1:
124 if (grub_file_read (sig, &l16, sizeof (l16)) != sizeof (l16))
125 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
126 *len = grub_be_to_cpu16 (l16);
127 return 0;
128 case 2:
129 if (grub_file_read (sig, &l32, sizeof (l32)) != sizeof (l32))
130 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
131 *len = grub_be_to_cpu32 (l32);
132 return 0;
134 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
137 struct signature_v4_header
139 grub_uint8_t type;
140 grub_uint8_t pkeyalgo;
141 grub_uint8_t hash;
142 grub_uint16_t hashed_sub;
143 } GRUB_PACKED;
145 const char *hashes[] = {
146 [0x01] = "md5",
147 [0x02] = "sha1",
148 [0x03] = "ripemd160",
149 [0x08] = "sha256",
150 [0x09] = "sha384",
151 [0x0a] = "sha512",
152 [0x0b] = "sha224"
155 struct gcry_pk_spec *grub_crypto_pk_dsa;
156 struct gcry_pk_spec *grub_crypto_pk_ecdsa;
157 struct gcry_pk_spec *grub_crypto_pk_rsa;
159 static int
160 dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
161 const gcry_md_spec_t *hash, struct grub_public_subkey *sk);
162 static int
163 rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
164 const gcry_md_spec_t *hash, struct grub_public_subkey *sk);
166 struct
168 const char *name;
169 grub_size_t nmpisig;
170 grub_size_t nmpipub;
171 struct gcry_pk_spec **algo;
172 int (*pad) (gcry_mpi_t *hmpi, grub_uint8_t *hval,
173 const gcry_md_spec_t *hash, struct grub_public_subkey *sk);
174 const char *module;
175 } pkalgos[] =
177 [1] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" },
178 [3] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" },
179 [17] = { "dsa", 2, 4, &grub_crypto_pk_dsa, dsa_pad, "gcry_dsa" },
182 struct grub_public_key
184 struct grub_public_key *next;
185 struct grub_public_subkey *subkeys;
188 struct grub_public_subkey
190 struct grub_public_subkey *next;
191 grub_uint8_t type;
192 grub_uint32_t fingerprint[5];
193 gcry_mpi_t mpis[10];
196 static void
197 free_pk (struct grub_public_key *pk)
199 struct grub_public_subkey *nsk, *sk;
200 for (sk = pk->subkeys; sk; sk = nsk)
202 grub_size_t i;
203 for (i = 0; i < ARRAY_SIZE (sk->mpis); i++)
204 if (sk->mpis[i])
205 gcry_mpi_release (sk->mpis[i]);
206 nsk = sk->next;
207 grub_free (sk);
209 grub_free (pk);
212 #define READBUF_SIZE 4096
214 struct grub_public_key *
215 grub_load_public_key (grub_file_t f)
217 grub_err_t err;
218 struct grub_public_key *ret;
219 struct grub_public_subkey **last = 0;
220 void *fingerprint_context = NULL;
221 grub_uint8_t *buffer = NULL;
223 ret = grub_zalloc (sizeof (*ret));
224 if (!ret)
226 grub_free (fingerprint_context);
227 return NULL;
230 buffer = grub_zalloc (READBUF_SIZE);
231 fingerprint_context = grub_zalloc (GRUB_MD_SHA1->contextsize);
233 if (!buffer || !fingerprint_context)
234 goto fail;
236 last = &ret->subkeys;
238 while (1)
240 grub_uint8_t type;
241 grub_size_t len;
242 grub_uint8_t v, pk;
243 grub_uint32_t creation_time;
244 grub_off_t pend;
245 struct grub_public_subkey *sk;
246 grub_size_t i;
247 grub_uint16_t len_be;
249 err = read_packet_header (f, &type, &len);
251 if (err)
252 goto fail;
253 if (type == 0xfe)
254 continue;
255 if (type == 0xff)
257 grub_free (fingerprint_context);
258 grub_free (buffer);
259 return ret;
262 grub_dprintf ("crypt", "len = %x\n", (int) len);
264 pend = grub_file_tell (f) + len;
265 if (type != 6 && type != 14
266 && type != 5 && type != 7)
268 grub_file_seek (f, pend);
269 continue;
272 if (grub_file_read (f, &v, sizeof (v)) != sizeof (v))
274 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
275 goto fail;
278 grub_dprintf ("crypt", "v = %x\n", v);
280 if (v != 4)
282 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
283 goto fail;
285 if (grub_file_read (f, &creation_time, sizeof (creation_time)) != sizeof (creation_time))
287 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
288 goto fail;
291 grub_dprintf ("crypt", "time = %x\n", creation_time);
293 if (grub_file_read (f, &pk, sizeof (pk)) != sizeof (pk))
295 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
296 goto fail;
299 grub_dprintf ("crypt", "pk = %x\n", pk);
301 if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL)
303 grub_file_seek (f, pend);
304 continue;
307 sk = grub_zalloc (sizeof (struct grub_public_subkey));
308 if (!sk)
309 goto fail;
311 grub_memset (fingerprint_context, 0, GRUB_MD_SHA1->contextsize);
312 GRUB_MD_SHA1->init (fingerprint_context);
313 GRUB_MD_SHA1->write (fingerprint_context, "\x99", 1);
314 len_be = grub_cpu_to_be16 (len);
315 GRUB_MD_SHA1->write (fingerprint_context, &len_be, sizeof (len_be));
316 GRUB_MD_SHA1->write (fingerprint_context, &v, sizeof (v));
317 GRUB_MD_SHA1->write (fingerprint_context, &creation_time, sizeof (creation_time));
318 GRUB_MD_SHA1->write (fingerprint_context, &pk, sizeof (pk));
320 for (i = 0; i < pkalgos[pk].nmpipub; i++)
322 grub_uint16_t l;
323 grub_size_t lb;
324 if (grub_file_read (f, &l, sizeof (l)) != sizeof (l))
326 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
327 goto fail;
330 lb = (grub_be_to_cpu16 (l) + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT;
331 if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
333 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
334 goto fail;
336 if (grub_file_read (f, buffer + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
338 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
339 goto fail;
341 grub_memcpy (buffer, &l, sizeof (l));
343 GRUB_MD_SHA1->write (fingerprint_context, buffer, lb + sizeof (grub_uint16_t));
345 if (gcry_mpi_scan (&sk->mpis[i], GCRYMPI_FMT_PGP,
346 buffer, lb + sizeof (grub_uint16_t), 0))
348 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
349 goto fail;
353 GRUB_MD_SHA1->final (fingerprint_context);
355 grub_memcpy (sk->fingerprint, GRUB_MD_SHA1->read (fingerprint_context), 20);
357 *last = sk;
358 last = &sk->next;
360 grub_dprintf ("crypt", "actual pos: %x, expected: %x\n", (int)grub_file_tell (f), (int)pend);
362 grub_file_seek (f, pend);
364 fail:
365 free_pk (ret);
366 grub_free (fingerprint_context);
367 grub_free (buffer);
368 return NULL;
371 struct grub_public_key *grub_pk_trusted;
373 struct grub_public_subkey *
374 grub_crypto_pk_locate_subkey (grub_uint64_t keyid, struct grub_public_key *pkey)
376 struct grub_public_subkey *sk;
377 for (sk = pkey->subkeys; sk; sk = sk->next)
378 if (grub_memcmp (sk->fingerprint + 3, &keyid, 8) == 0)
379 return sk;
380 return 0;
383 struct grub_public_subkey *
384 grub_crypto_pk_locate_subkey_in_trustdb (grub_uint64_t keyid)
386 struct grub_public_key *pkey;
387 struct grub_public_subkey *sk;
388 for (pkey = grub_pk_trusted; pkey; pkey = pkey->next)
390 sk = grub_crypto_pk_locate_subkey (keyid, pkey);
391 if (sk)
392 return sk;
394 return 0;
398 static int
399 dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
400 const gcry_md_spec_t *hash, struct grub_public_subkey *sk)
402 unsigned nbits = gcry_mpi_get_nbits (sk->mpis[1]);
403 grub_dprintf ("crypt", "must be %u bits got %d bits\n", nbits,
404 (int)(8 * hash->mdlen));
405 return gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, hval,
406 nbits / 8 < (unsigned) hash->mdlen ? nbits / 8
407 : (unsigned) hash->mdlen, 0);
410 static int
411 rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
412 const gcry_md_spec_t *hash, struct grub_public_subkey *sk)
414 grub_size_t tlen, emlen, fflen;
415 grub_uint8_t *em, *emptr;
416 unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]);
417 int ret;
418 tlen = hash->mdlen + hash->asnlen;
419 emlen = (nbits + 7) / 8;
420 if (emlen < tlen + 11)
421 return 1;
423 em = grub_malloc (emlen);
424 if (!em)
425 return 1;
427 em[0] = 0x00;
428 em[1] = 0x01;
429 fflen = emlen - tlen - 3;
430 for (emptr = em + 2; emptr < em + 2 + fflen; emptr++)
431 *emptr = 0xff;
432 *emptr++ = 0x00;
433 grub_memcpy (emptr, hash->asnoid, hash->asnlen);
434 emptr += hash->asnlen;
435 grub_memcpy (emptr, hval, hash->mdlen);
437 ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0);
438 grub_free (em);
439 return ret;
442 static grub_err_t
443 grub_verify_signature_real (char *buf, grub_size_t size,
444 grub_file_t f, grub_file_t sig,
445 struct grub_public_key *pkey)
447 grub_size_t len;
448 grub_uint8_t v;
449 grub_uint8_t h;
450 grub_uint8_t t;
451 grub_uint8_t pk;
452 const gcry_md_spec_t *hash;
453 struct signature_v4_header v4;
454 grub_err_t err;
455 grub_size_t i;
456 gcry_mpi_t mpis[10];
457 grub_uint8_t type;
459 err = read_packet_header (sig, &type, &len);
460 if (err)
461 return err;
463 if (type != 0x2)
464 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
466 if (grub_file_read (sig, &v, sizeof (v)) != sizeof (v))
467 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
469 if (v != 4)
470 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
472 if (grub_file_read (sig, &v4, sizeof (v4)) != sizeof (v4))
473 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
475 h = v4.hash;
476 t = v4.type;
477 pk = v4.pkeyalgo;
479 if (t != 0)
480 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
482 if (h >= ARRAY_SIZE (hashes) || hashes[h] == NULL)
483 return grub_error (GRUB_ERR_BAD_SIGNATURE, "unknown hash");
485 if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL)
486 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
488 hash = grub_crypto_lookup_md_by_name (hashes[h]);
489 if (!hash)
490 return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%s' not loaded", hashes[h]);
492 grub_dprintf ("crypt", "alive\n");
495 void *context = NULL;
496 unsigned char *hval;
497 grub_ssize_t rem = grub_be_to_cpu16 (v4.hashed_sub);
498 grub_uint32_t headlen = grub_cpu_to_be32 (rem + 6);
499 grub_uint8_t s;
500 grub_uint16_t unhashed_sub;
501 grub_ssize_t r;
502 grub_uint8_t hash_start[2];
503 gcry_mpi_t hmpi;
504 grub_uint64_t keyid = 0;
505 struct grub_public_subkey *sk;
506 grub_uint8_t *readbuf = NULL;
508 context = grub_zalloc (hash->contextsize);
509 readbuf = grub_zalloc (READBUF_SIZE);
510 if (!context || !readbuf)
511 goto fail;
513 hash->init (context);
514 if (buf)
515 hash->write (context, buf, size);
516 else
517 while (1)
519 r = grub_file_read (f, readbuf, READBUF_SIZE);
520 if (r < 0)
521 goto fail;
522 if (r == 0)
523 break;
524 hash->write (context, readbuf, r);
527 hash->write (context, &v, sizeof (v));
528 hash->write (context, &v4, sizeof (v4));
529 while (rem)
531 r = grub_file_read (sig, readbuf,
532 rem < READBUF_SIZE ? rem : READBUF_SIZE);
533 if (r < 0)
534 goto fail;
535 if (r == 0)
536 break;
537 hash->write (context, readbuf, r);
538 rem -= r;
540 hash->write (context, &v, sizeof (v));
541 s = 0xff;
542 hash->write (context, &s, sizeof (s));
543 hash->write (context, &headlen, sizeof (headlen));
544 r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub));
545 if (r != sizeof (unhashed_sub))
546 goto fail;
548 grub_uint8_t *ptr;
549 grub_uint32_t l;
550 rem = grub_be_to_cpu16 (unhashed_sub);
551 if (rem > READBUF_SIZE)
552 goto fail;
553 r = grub_file_read (sig, readbuf, rem);
554 if (r != rem)
555 goto fail;
556 for (ptr = readbuf; ptr < readbuf + rem; ptr += l)
558 if (*ptr < 192)
559 l = *ptr++;
560 else if (*ptr < 255)
562 if (ptr + 1 >= readbuf + rem)
563 break;
564 l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192;
565 ptr += 2;
567 else
569 if (ptr + 5 >= readbuf + rem)
570 break;
571 l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1));
572 ptr += 5;
574 if (*ptr == 0x10 && l >= 8)
575 keyid = grub_get_unaligned64 (ptr + 1);
579 hash->final (context);
581 grub_dprintf ("crypt", "alive\n");
583 hval = hash->read (context);
585 if (grub_file_read (sig, hash_start, sizeof (hash_start)) != sizeof (hash_start))
586 goto fail;
587 if (grub_memcmp (hval, hash_start, sizeof (hash_start)) != 0)
588 goto fail;
590 grub_dprintf ("crypt", "@ %x\n", (int)grub_file_tell (sig));
592 for (i = 0; i < pkalgos[pk].nmpisig; i++)
594 grub_uint16_t l;
595 grub_size_t lb;
596 grub_dprintf ("crypt", "alive\n");
597 if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l))
598 goto fail;
599 grub_dprintf ("crypt", "alive\n");
600 lb = (grub_be_to_cpu16 (l) + 7) / 8;
601 grub_dprintf ("crypt", "l = 0x%04x\n", grub_be_to_cpu16 (l));
602 if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
603 goto fail;
604 grub_dprintf ("crypt", "alive\n");
605 if (grub_file_read (sig, readbuf + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
606 goto fail;
607 grub_dprintf ("crypt", "alive\n");
608 grub_memcpy (readbuf, &l, sizeof (l));
609 grub_dprintf ("crypt", "alive\n");
611 if (gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP,
612 readbuf, lb + sizeof (grub_uint16_t), 0))
613 goto fail;
614 grub_dprintf ("crypt", "alive\n");
617 if (pkey)
618 sk = grub_crypto_pk_locate_subkey (keyid, pkey);
619 else
620 sk = grub_crypto_pk_locate_subkey_in_trustdb (keyid);
621 if (!sk)
623 /* TRANSLATORS: %08x is 32-bit key id. */
624 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("public key %08x not found"),
625 keyid);
626 goto fail;
629 if (pkalgos[pk].pad (&hmpi, hval, hash, sk))
630 goto fail;
631 if (!*pkalgos[pk].algo)
633 grub_dl_load (pkalgos[pk].module);
634 grub_errno = GRUB_ERR_NONE;
637 if (!*pkalgos[pk].algo)
639 grub_error (GRUB_ERR_BAD_SIGNATURE, N_("module `%s' isn't loaded"),
640 pkalgos[pk].module);
641 goto fail;
643 if ((*pkalgos[pk].algo)->verify (0, hmpi, mpis, sk->mpis, 0, 0))
644 goto fail;
646 grub_free (context);
647 grub_free (readbuf);
649 return GRUB_ERR_NONE;
651 fail:
652 grub_free (context);
653 grub_free (readbuf);
654 if (!grub_errno)
655 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
656 return grub_errno;
660 grub_err_t
661 grub_verify_signature (grub_file_t f, grub_file_t sig,
662 struct grub_public_key *pkey)
664 return grub_verify_signature_real (0, 0, f, sig, pkey);
667 static grub_err_t
668 grub_cmd_trust (grub_extcmd_context_t ctxt,
669 int argc, char **args)
671 grub_file_t pkf;
672 struct grub_public_key *pk = NULL;
674 if (argc < 1)
675 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
677 grub_file_filter_disable_compression ();
678 if (ctxt->state[OPTION_SKIP_SIG].set)
679 grub_file_filter_disable_pubkey ();
680 pkf = grub_file_open (args[0]);
681 if (!pkf)
682 return grub_errno;
683 pk = grub_load_public_key (pkf);
684 if (!pk)
686 grub_file_close (pkf);
687 return grub_errno;
689 grub_file_close (pkf);
691 pk->next = grub_pk_trusted;
692 grub_pk_trusted = pk;
694 return GRUB_ERR_NONE;
697 static grub_err_t
698 grub_cmd_list (grub_command_t cmd __attribute__ ((unused)),
699 int argc __attribute__ ((unused)),
700 char **args __attribute__ ((unused)))
702 struct grub_public_key *pk = NULL;
703 struct grub_public_subkey *sk = NULL;
705 for (pk = grub_pk_trusted; pk; pk = pk->next)
706 for (sk = pk->subkeys; sk; sk = sk->next)
708 unsigned i;
709 for (i = 0; i < 20; i += 2)
710 grub_printf ("%02x%02x ", ((grub_uint8_t *) sk->fingerprint)[i],
711 ((grub_uint8_t *) sk->fingerprint)[i + 1]);
712 grub_printf ("\n");
715 return GRUB_ERR_NONE;
718 static grub_err_t
719 grub_cmd_distrust (grub_command_t cmd __attribute__ ((unused)),
720 int argc, char **args)
722 grub_uint32_t keyid, keyid_be;
723 struct grub_public_key **pkey;
724 struct grub_public_subkey *sk;
726 if (argc < 1)
727 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
728 keyid = grub_strtoull (args[0], 0, 16);
729 if (grub_errno)
730 return grub_errno;
731 keyid_be = grub_cpu_to_be32 (keyid);
733 for (pkey = &grub_pk_trusted; *pkey; pkey = &((*pkey)->next))
735 struct grub_public_key *next;
736 for (sk = (*pkey)->subkeys; sk; sk = sk->next)
737 if (grub_memcmp (sk->fingerprint + 4, &keyid_be, 4) == 0)
738 break;
739 if (!sk)
740 continue;
741 next = (*pkey)->next;
742 free_pk (*pkey);
743 *pkey = next;
744 return GRUB_ERR_NONE;
746 /* TRANSLATORS: %08x is 32-bit key id. */
747 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("public key %08x not found"), keyid);
750 static grub_err_t
751 grub_cmd_verify_signature (grub_extcmd_context_t ctxt,
752 int argc, char **args)
754 grub_file_t f = NULL, sig = NULL;
755 grub_err_t err = GRUB_ERR_NONE;
756 struct grub_public_key *pk = NULL;
758 grub_dprintf ("crypt", "alive\n");
760 if (argc < 2)
761 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
763 grub_dprintf ("crypt", "alive\n");
765 if (argc > 2)
767 grub_file_t pkf;
768 grub_file_filter_disable_compression ();
769 if (ctxt->state[OPTION_SKIP_SIG].set)
770 grub_file_filter_disable_pubkey ();
771 pkf = grub_file_open (args[2]);
772 if (!pkf)
773 return grub_errno;
774 pk = grub_load_public_key (pkf);
775 if (!pk)
777 grub_file_close (pkf);
778 return grub_errno;
780 grub_file_close (pkf);
783 grub_file_filter_disable_all ();
784 f = grub_file_open (args[0]);
785 if (!f)
787 err = grub_errno;
788 goto fail;
791 grub_file_filter_disable_all ();
792 sig = grub_file_open (args[1]);
793 if (!sig)
795 err = grub_errno;
796 goto fail;
799 err = grub_verify_signature (f, sig, pk);
800 fail:
801 if (sig)
802 grub_file_close (sig);
803 if (f)
804 grub_file_close (f);
805 if (pk)
806 free_pk (pk);
807 return err;
810 static int sec = 0;
812 static void
813 verified_free (grub_verified_t verified)
815 if (verified)
817 grub_free (verified->buf);
818 grub_free (verified);
822 static grub_ssize_t
823 verified_read (struct grub_file *file, char *buf, grub_size_t len)
825 grub_verified_t verified = file->data;
827 grub_memcpy (buf, (char *) verified->buf + file->offset, len);
828 return len;
831 static grub_err_t
832 verified_close (struct grub_file *file)
834 grub_verified_t verified = file->data;
836 grub_file_close (verified->file);
837 verified_free (verified);
838 file->data = 0;
840 /* device and name are freed by parent */
841 file->device = 0;
842 file->name = 0;
844 return grub_errno;
847 struct grub_fs verified_fs =
849 .name = "verified_read",
850 .read = verified_read,
851 .close = verified_close
854 static grub_file_t
855 grub_pubkey_open (grub_file_t io, const char *filename)
857 grub_file_t sig;
858 char *fsuf, *ptr;
859 grub_err_t err;
860 grub_file_filter_t curfilt[GRUB_FILE_FILTER_MAX];
861 grub_file_t ret;
862 grub_verified_t verified;
864 if (!sec)
865 return io;
866 if (io->device->disk &&
867 (io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID
868 || io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID))
869 return io;
870 fsuf = grub_malloc (grub_strlen (filename) + sizeof (".sig"));
871 if (!fsuf)
872 return NULL;
873 ptr = grub_stpcpy (fsuf, filename);
874 grub_memcpy (ptr, ".sig", sizeof (".sig"));
876 grub_memcpy (curfilt, grub_file_filters_enabled,
877 sizeof (curfilt));
878 grub_file_filter_disable_all ();
879 sig = grub_file_open (fsuf);
880 grub_memcpy (grub_file_filters_enabled, curfilt,
881 sizeof (curfilt));
882 grub_free (fsuf);
883 if (!sig)
884 return NULL;
886 ret = grub_malloc (sizeof (*ret));
887 if (!ret)
889 grub_file_close (sig);
890 return NULL;
892 *ret = *io;
894 ret->fs = &verified_fs;
895 ret->not_easily_seekable = 0;
896 if (ret->size >> (sizeof (grub_size_t) * GRUB_CHAR_BIT - 1))
898 grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
899 "big file signature isn't implemented yet");
900 grub_file_close (sig);
901 grub_free (ret);
902 return NULL;
904 verified = grub_malloc (sizeof (*verified));
905 if (!verified)
907 grub_file_close (sig);
908 grub_free (ret);
909 return NULL;
911 verified->buf = grub_malloc (ret->size);
912 if (!verified->buf)
914 grub_file_close (sig);
915 grub_free (verified);
916 grub_free (ret);
917 return NULL;
919 if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size)
921 if (!grub_errno)
922 grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
923 filename);
924 grub_file_close (sig);
925 verified_free (verified);
926 grub_free (ret);
927 return NULL;
930 err = grub_verify_signature_real (verified->buf, ret->size, 0, sig, NULL);
931 grub_file_close (sig);
932 if (err)
934 verified_free (verified);
935 grub_free (ret);
936 return NULL;
938 verified->file = io;
939 ret->data = verified;
940 return ret;
943 static char *
944 grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)),
945 const char *val)
947 sec = (*val == '1') || (*val == 'e');
948 return grub_strdup (sec ? "enforce" : "no");
951 static grub_ssize_t
952 pseudo_read (struct grub_file *file, char *buf, grub_size_t len)
954 grub_memcpy (buf, (grub_uint8_t *) file->data + file->offset, len);
955 return len;
959 /* Filesystem descriptor. */
960 struct grub_fs pseudo_fs =
962 .name = "pseudo",
963 .read = pseudo_read
967 static grub_extcmd_t cmd, cmd_trust;
968 static grub_command_t cmd_distrust, cmd_list;
970 GRUB_MOD_INIT(verify)
972 const char *val;
973 struct grub_module_header *header;
975 val = grub_env_get ("check_signatures");
976 if (val && (val[0] == '1' || val[0] == 'e'))
977 sec = 1;
978 else
979 sec = 0;
981 grub_file_filter_register (GRUB_FILE_FILTER_PUBKEY, grub_pubkey_open);
983 grub_register_variable_hook ("check_signatures", 0, grub_env_write_sec);
984 grub_env_export ("check_signatures");
986 grub_pk_trusted = 0;
987 FOR_MODULES (header)
989 struct grub_file pseudo_file;
990 struct grub_public_key *pk = NULL;
992 grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
994 /* Not an ELF module, skip. */
995 if (header->type != OBJ_TYPE_PUBKEY)
996 continue;
998 pseudo_file.fs = &pseudo_fs;
999 pseudo_file.size = (header->size - sizeof (struct grub_module_header));
1000 pseudo_file.data = (char *) header + sizeof (struct grub_module_header);
1002 pk = grub_load_public_key (&pseudo_file);
1003 if (!pk)
1004 grub_fatal ("error loading initial key: %s\n", grub_errmsg);
1006 pk->next = grub_pk_trusted;
1007 grub_pk_trusted = pk;
1010 if (!val)
1011 grub_env_set ("check_signatures", grub_pk_trusted ? "enforce" : "no");
1013 cmd = grub_register_extcmd ("verify_detached", grub_cmd_verify_signature, 0,
1014 N_("[-s|--skip-sig] FILE SIGNATURE_FILE [PUBKEY_FILE]"),
1015 N_("Verify detached signature."),
1016 options);
1017 cmd_trust = grub_register_extcmd ("trust", grub_cmd_trust, 0,
1018 N_("[-s|--skip-sig] PUBKEY_FILE"),
1019 N_("Add PUBKEY_FILE to trusted keys."),
1020 options);
1021 cmd_list = grub_register_command ("list_trusted", grub_cmd_list,
1023 N_("Show the list of trusted keys."));
1024 cmd_distrust = grub_register_command ("distrust", grub_cmd_distrust,
1025 N_("PUBKEY_ID"),
1026 N_("Remove PUBKEY_ID from trusted keys."));
1029 GRUB_MOD_FINI(verify)
1031 grub_file_filter_unregister (GRUB_FILE_FILTER_PUBKEY);
1032 grub_unregister_extcmd (cmd);
1033 grub_unregister_extcmd (cmd_trust);
1034 grub_unregister_command (cmd_list);
1035 grub_unregister_command (cmd_distrust);