verify framework.

This commit is contained in:
Vladimir Serbinenko committed 2017-05-09 16:12:18 +02:00
1 parent aa93127ed8
commit 09bd17faaa
6 files changed
+368 -175

No files matched your search

+5
View File
@@ -899,6 +899,11 @@ module = {
cppflags = '-I$(srcdir)/lib/posix_wrap'; cppflags = '-I$(srcdir)/lib/posix_wrap';
}; };
module = {
name = verify_helper;
common = commands/verify_helper.c;
};
module = { module = {
name = hdparm; name = hdparm;
common = commands/hdparm.c; common = commands/hdparm.c;
+147 -174
View File
@@ -30,16 +30,10 @@
#include <grub/env.h> #include <grub/env.h>
#include <grub/kernel.h> #include <grub/kernel.h>
#include <grub/extcmd.h> #include <grub/extcmd.h>
#include <grub/verify.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
struct grub_verified
{
grub_file_t file;
void *buf;
};
typedef struct grub_verified *grub_verified_t;
enum enum
{ {
OPTION_SKIP_SIG = 0 OPTION_SKIP_SIG = 0
@@ -445,22 +439,26 @@ rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
return ret; return ret;
} }
struct grub_pubkey_context
{
grub_file_t sig;
struct signature_v4_header v4;
grub_uint8_t v;
const gcry_md_spec_t *hash;
void *hash_context;
};
static grub_err_t static grub_err_t
grub_verify_signature_real (char *buf, grub_size_t size, grub_verify_signature_init (struct grub_pubkey_context *ctxt, grub_file_t sig)
grub_file_t f, grub_file_t sig,
struct grub_public_key *pkey)
{ {
grub_size_t len; grub_size_t len;
grub_uint8_t v;
grub_uint8_t h; grub_uint8_t h;
grub_uint8_t t; grub_uint8_t t;
grub_uint8_t pk;
const gcry_md_spec_t *hash;
struct signature_v4_header v4;
grub_err_t err; grub_err_t err;
grub_size_t i;
gcry_mpi_t mpis[10];
grub_uint8_t type = 0; grub_uint8_t type = 0;
grub_uint8_t pk;
grub_memset (ctxt, 0, sizeof (*ctxt));
err = read_packet_header (sig, &type, &len); err = read_packet_header (sig, &type, &len);
if (err) if (err)
@@ -469,18 +467,18 @@ grub_verify_signature_real (char *buf, grub_size_t size,
if (type != 0x2) if (type != 0x2)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
if (grub_file_read (sig, &v, sizeof (v)) != sizeof (v)) if (grub_file_read (sig, &ctxt->v, sizeof (ctxt->v)) != sizeof (ctxt->v))
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
if (v != 4) if (ctxt->v != 4)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
if (grub_file_read (sig, &v4, sizeof (v4)) != sizeof (v4)) if (grub_file_read (sig, &ctxt->v4, sizeof (ctxt->v4)) != sizeof (ctxt->v4))
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
h = v4.hash; h = ctxt->v4.hash;
t = v4.type; t = ctxt->v4.type;
pk = v4.pkeyalgo; pk = ctxt->v4.pkeyalgo;
if (t != 0) if (t != 0)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
@@ -491,16 +489,41 @@ grub_verify_signature_real (char *buf, grub_size_t size,
if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL) if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
hash = grub_crypto_lookup_md_by_name (hashes[h]); ctxt->hash = grub_crypto_lookup_md_by_name (hashes[h]);
if (!hash) if (!ctxt->hash)
return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%s' not loaded", hashes[h]); return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%s' not loaded", hashes[h]);
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
{ ctxt->sig = sig;
void *context = NULL;
ctxt->hash_context = grub_zalloc (ctxt->hash->contextsize);
if (!ctxt->hash_context)
return grub_errno;
ctxt->hash->init (ctxt->hash_context);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_pubkey_write (void *ctxt_, void *buf, grub_size_t size)
{
struct grub_pubkey_context *ctxt = ctxt_;
ctxt->hash->write (ctxt->hash_context, buf, size);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_verify_signature_real (struct grub_pubkey_context *ctxt,
struct grub_public_key *pkey)
{
gcry_mpi_t mpis[10];
grub_uint8_t pk = ctxt->v4.pkeyalgo;
grub_size_t i;
grub_uint8_t *readbuf = NULL;
unsigned char *hval; unsigned char *hval;
grub_ssize_t rem = grub_be_to_cpu16 (v4.hashed_sub); grub_ssize_t rem = grub_be_to_cpu16 (ctxt->v4.hashed_sub);
grub_uint32_t headlen = grub_cpu_to_be32 (rem + 6); grub_uint32_t headlen = grub_cpu_to_be32 (rem + 6);
grub_uint8_t s; grub_uint8_t s;
grub_uint16_t unhashed_sub; grub_uint16_t unhashed_sub;
@@ -509,45 +532,29 @@ grub_verify_signature_real (char *buf, grub_size_t size,
gcry_mpi_t hmpi; gcry_mpi_t hmpi;
grub_uint64_t keyid = 0; grub_uint64_t keyid = 0;
struct grub_public_subkey *sk; struct grub_public_subkey *sk;
grub_uint8_t *readbuf = NULL;
context = grub_zalloc (hash->contextsize); readbuf = grub_malloc (READBUF_SIZE);
readbuf = grub_zalloc (READBUF_SIZE); if (!readbuf)
if (!context || !readbuf)
goto fail; goto fail;
hash->init (context); ctxt->hash->write (ctxt->hash_context, &ctxt->v, sizeof (ctxt->v));
if (buf) ctxt->hash->write (ctxt->hash_context, &ctxt->v4, sizeof (ctxt->v4));
hash->write (context, buf, size);
else
while (1)
{
r = grub_file_read (f, readbuf, READBUF_SIZE);
if (r < 0)
goto fail;
if (r == 0)
break;
hash->write (context, readbuf, r);
}
hash->write (context, &v, sizeof (v));
hash->write (context, &v4, sizeof (v4));
while (rem) while (rem)
{ {
r = grub_file_read (sig, readbuf, r = grub_file_read (ctxt->sig, readbuf,
rem < READBUF_SIZE ? rem : READBUF_SIZE); rem < READBUF_SIZE ? rem : READBUF_SIZE);
if (r < 0) if (r < 0)
goto fail; goto fail;
if (r == 0) if (r == 0)
break; break;
hash->write (context, readbuf, r); ctxt->hash->write (ctxt->hash_context, readbuf, r);
rem -= r; rem -= r;
} }
hash->write (context, &v, sizeof (v)); ctxt->hash->write (ctxt->hash_context, &ctxt->v, sizeof (ctxt->v));
s = 0xff; s = 0xff;
hash->write (context, &s, sizeof (s)); ctxt->hash->write (ctxt->hash_context, &s, sizeof (s));
hash->write (context, &headlen, sizeof (headlen)); ctxt->hash->write (ctxt->hash_context, &headlen, sizeof (headlen));
r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub)); r = grub_file_read (ctxt->sig, &unhashed_sub, sizeof (unhashed_sub));
if (r != sizeof (unhashed_sub)) if (r != sizeof (unhashed_sub))
goto fail; goto fail;
{ {
@@ -556,7 +563,7 @@ grub_verify_signature_real (char *buf, grub_size_t size,
rem = grub_be_to_cpu16 (unhashed_sub); rem = grub_be_to_cpu16 (unhashed_sub);
if (rem > READBUF_SIZE) if (rem > READBUF_SIZE)
goto fail; goto fail;
r = grub_file_read (sig, readbuf, rem); r = grub_file_read (ctxt->sig, readbuf, rem);
if (r != rem) if (r != rem)
goto fail; goto fail;
for (ptr = readbuf; ptr < readbuf + rem; ptr += l) for (ptr = readbuf; ptr < readbuf + rem; ptr += l)
@@ -582,25 +589,25 @@ grub_verify_signature_real (char *buf, grub_size_t size,
} }
} }
hash->final (context); ctxt->hash->final (ctxt->hash_context);
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
hval = hash->read (context); hval = ctxt->hash->read (ctxt->hash_context);
if (grub_file_read (sig, hash_start, sizeof (hash_start)) != sizeof (hash_start)) if (grub_file_read (ctxt->sig, hash_start, sizeof (hash_start)) != sizeof (hash_start))
goto fail; goto fail;
if (grub_memcmp (hval, hash_start, sizeof (hash_start)) != 0) if (grub_memcmp (hval, hash_start, sizeof (hash_start)) != 0)
goto fail; goto fail;
grub_dprintf ("crypt", "@ %x\n", (int)grub_file_tell (sig)); grub_dprintf ("crypt", "@ %x\n", (int)grub_file_tell (ctxt->sig));
for (i = 0; i < pkalgos[pk].nmpisig; i++) for (i = 0; i < pkalgos[pk].nmpisig; i++)
{ {
grub_uint16_t l; grub_uint16_t l;
grub_size_t lb; grub_size_t lb;
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l)) if (grub_file_read (ctxt->sig, &l, sizeof (l)) != sizeof (l))
goto fail; goto fail;
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
lb = (grub_be_to_cpu16 (l) + 7) / 8; lb = (grub_be_to_cpu16 (l) + 7) / 8;
@@ -608,7 +615,7 @@ grub_verify_signature_real (char *buf, grub_size_t size,
if (lb > READBUF_SIZE - sizeof (grub_uint16_t)) if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
goto fail; goto fail;
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
if (grub_file_read (sig, readbuf + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb) if (grub_file_read (ctxt->sig, readbuf + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
goto fail; goto fail;
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
grub_memcpy (readbuf, &l, sizeof (l)); grub_memcpy (readbuf, &l, sizeof (l));
@@ -632,7 +639,7 @@ grub_verify_signature_real (char *buf, grub_size_t size,
goto fail; goto fail;
} }
if (pkalgos[pk].pad (&hmpi, hval, hash, sk)) if (pkalgos[pk].pad (&hmpi, hval, ctxt->hash, sk))
goto fail; goto fail;
if (!*pkalgos[pk].algo) if (!*pkalgos[pk].algo)
{ {
@@ -649,25 +656,65 @@ grub_verify_signature_real (char *buf, grub_size_t size,
if ((*pkalgos[pk].algo)->verify (0, hmpi, mpis, sk->mpis, 0, 0)) if ((*pkalgos[pk].algo)->verify (0, hmpi, mpis, sk->mpis, 0, 0))
goto fail; goto fail;
grub_free (context);
grub_free (readbuf); grub_free (readbuf);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
fail: fail:
grub_free (context);
grub_free (readbuf); grub_free (readbuf);
if (!grub_errno) if (!grub_errno)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
return grub_errno; return grub_errno;
} }
static void
grub_pubkey_close_real (struct grub_pubkey_context *ctxt)
{
if (ctxt->sig)
grub_file_close (ctxt->sig);
if (ctxt->hash_context)
grub_free (ctxt->hash_context);
}
static void
grub_pubkey_close (void *ctxt)
{
grub_pubkey_close_real (ctxt);
grub_free (ctxt);
} }
grub_err_t grub_err_t
grub_verify_signature (grub_file_t f, grub_file_t sig, grub_verify_signature (grub_file_t f, grub_file_t sig,
struct grub_public_key *pkey) struct grub_public_key *pkey)
{ {
return grub_verify_signature_real (0, 0, f, sig, pkey); grub_err_t err;
struct grub_pubkey_context ctxt;
grub_uint8_t *readbuf = NULL;
err = grub_verify_signature_init (&ctxt, sig);
if (err)
return err;
readbuf = grub_zalloc (READBUF_SIZE);
if (!readbuf)
goto fail;
while (1)
{
grub_ssize_t r;
r = grub_file_read (f, readbuf, READBUF_SIZE);
if (r < 0)
goto fail;
if (r == 0)
break;
err = grub_pubkey_write (&ctxt, readbuf, r);
if (err)
return err;
}
grub_verify_signature_real (&ctxt, pkey);
fail:
grub_pubkey_close_real (&ctxt);
return grub_errno;
} }
static grub_err_t static grub_err_t
@@ -819,134 +866,52 @@ grub_cmd_verify_signature (grub_extcmd_context_t ctxt,
static int sec = 0; static int sec = 0;
static void
verified_free (grub_verified_t verified)
{
if (verified)
{
grub_free (verified->buf);
grub_free (verified);
}
}
static grub_ssize_t
verified_read (struct grub_file *file, char *buf, grub_size_t len)
{
grub_verified_t verified = file->data;
grub_memcpy (buf, (char *) verified->buf + file->offset, len);
return len;
}
static grub_err_t static grub_err_t
verified_close (struct grub_file *file) grub_pubkey_init (grub_file_t io, enum grub_file_type type __attribute__ ((unused)),
{ void **context, enum grub_verify_flags *flags)
grub_verified_t verified = file->data;
grub_file_close (verified->file);
verified_free (verified);
file->data = 0;
/* device and name are freed by parent */
file->device = 0;
file->name = 0;
return grub_errno;
}
struct grub_fs verified_fs =
{
.name = "verified_read",
.read = verified_read,
.close = verified_close
};
static grub_file_t
grub_pubkey_open (grub_file_t io, enum grub_file_type type)
{ {
grub_file_t sig; grub_file_t sig;
char *fsuf, *ptr; char *fsuf, *ptr;
grub_err_t err; grub_err_t err;
grub_file_t ret;
grub_verified_t verified;
if ((type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_SIGNATURE
|| (type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_VERIFY_SIGNATURE
|| (type & GRUB_FILE_TYPE_SKIP_SIGNATURE))
return io;
if (!sec) if (!sec)
return io; {
if (io->device->disk && *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
(io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID return GRUB_ERR_NONE;
|| io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID)) }
return io;
fsuf = grub_malloc (grub_strlen (io->name) + sizeof (".sig")); fsuf = grub_malloc (grub_strlen (io->name) + sizeof (".sig"));
if (!fsuf) if (!fsuf)
return NULL; return grub_errno;
ptr = grub_stpcpy (fsuf, io->name); ptr = grub_stpcpy (fsuf, io->name);
grub_memcpy (ptr, ".sig", sizeof (".sig")); grub_memcpy (ptr, ".sig", sizeof (".sig"));
sig = grub_file_open (fsuf, GRUB_FILE_TYPE_SIGNATURE); sig = grub_file_open (fsuf, GRUB_FILE_TYPE_SIGNATURE);
grub_free (fsuf); grub_free (fsuf);
if (!sig) if (!sig)
return NULL; return grub_errno;
ret = grub_malloc (sizeof (*ret));
if (!ret)
{
grub_free (fsuf);
return NULL;
}
*ret = *io;
ret->fs = &verified_fs; struct grub_pubkey_context *ctxt = grub_malloc (sizeof (*ctxt));
ret->not_easily_seekable = 0; if (!ctxt)
if (ret->size >> (sizeof (grub_size_t) * GRUB_CHAR_BIT - 1))
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"big file signature isn't implemented yet");
grub_file_close (sig);
grub_free (ret);
return NULL;
}
verified = grub_malloc (sizeof (*verified));
if (!verified)
{ {
grub_file_close (sig); grub_file_close (sig);
grub_free (ret); return grub_errno;
return NULL;
} }
verified->buf = grub_malloc (ret->size); err = grub_verify_signature_init (ctxt, sig);
if (!verified->buf)
{
grub_file_close (sig);
verified_free (verified);
grub_free (ret);
return NULL;
}
if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size)
{
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
io->name);
grub_file_close (sig);
verified_free (verified);
grub_free (ret);
return NULL;
}
err = grub_verify_signature_real (verified->buf, ret->size, 0, sig, NULL);
grub_file_close (sig);
if (err) if (err)
{ {
verified_free (verified); grub_pubkey_close (ctxt);
grub_free (ret); return err;
return NULL;
} }
verified->file = io; *context = ctxt;
ret->data = verified; return GRUB_ERR_NONE;
return ret; }
static grub_err_t
grub_pubkey_fini (void *ctxt)
{
return grub_verify_signature_real (ctxt, NULL);
} }
static char * static char *
@@ -970,8 +935,16 @@ struct grub_fs pseudo_fs =
{ {
.name = "pseudo", .name = "pseudo",
.read = pseudo_read .read = pseudo_read
}; };
struct grub_file_verifier grub_pubkey_verifier =
{
.name = "pgp",
.init = grub_pubkey_init,
.fini = grub_pubkey_fini,
.write = grub_pubkey_write,
.close = grub_pubkey_close,
};
static grub_extcmd_t cmd, cmd_trust; static grub_extcmd_t cmd, cmd_trust;
static grub_command_t cmd_distrust, cmd_list; static grub_command_t cmd_distrust, cmd_list;
@@ -987,8 +960,6 @@ GRUB_MOD_INIT(verify)
else else
sec = 0; sec = 0;
grub_file_filter_register (GRUB_FILE_FILTER_PUBKEY, grub_pubkey_open);
grub_register_variable_hook ("check_signatures", 0, grub_env_write_sec); grub_register_variable_hook ("check_signatures", 0, grub_env_write_sec);
grub_env_export ("check_signatures"); grub_env_export ("check_signatures");
@@ -1033,11 +1004,13 @@ GRUB_MOD_INIT(verify)
cmd_distrust = grub_register_command ("distrust", grub_cmd_distrust, cmd_distrust = grub_register_command ("distrust", grub_cmd_distrust,
N_("PUBKEY_ID"), N_("PUBKEY_ID"),
N_("Remove PUBKEY_ID from trusted keys.")); N_("Remove PUBKEY_ID from trusted keys."));
grub_verifier_register (&grub_pubkey_verifier);
} }
GRUB_MOD_FINI(verify) GRUB_MOD_FINI(verify)
{ {
grub_file_filter_unregister (GRUB_FILE_FILTER_PUBKEY); grub_verifier_unregister (&grub_pubkey_verifier);
grub_unregister_extcmd (cmd); grub_unregister_extcmd (cmd);
grub_unregister_extcmd (cmd_trust); grub_unregister_extcmd (cmd_trust);
grub_unregister_command (cmd_list); grub_unregister_command (cmd_list);
+172
View File
@@ -0,0 +1,172 @@
#include <grub/file.h>
#include <grub/verify.h>
#include <grub/dl.h>
GRUB_MOD_LICENSE ("GPLv3+");
struct grub_file_verifier *grub_file_verifiers;
struct grub_verified
{
grub_file_t file;
void *buf;
};
typedef struct grub_verified *grub_verified_t;
static void
verified_free (grub_verified_t verified)
{
if (verified)
{
grub_free (verified->buf);
grub_free (verified);
}
}
static grub_ssize_t
verified_read (struct grub_file *file, char *buf, grub_size_t len)
{
grub_verified_t verified = file->data;
grub_memcpy (buf, (char *) verified->buf + file->offset, len);
return len;
}
static grub_err_t
verified_close (struct grub_file *file)
{
grub_verified_t verified = file->data;
grub_file_close (verified->file);
verified_free (verified);
file->data = 0;
/* device and name are freed by parent */
file->device = 0;
file->name = 0;
return grub_errno;
}
struct grub_fs verified_fs =
{
.name = "verified_read",
.read = verified_read,
.close = verified_close
};
static grub_file_t
grub_verify_helper_open (grub_file_t io, enum grub_file_type type)
{
grub_verified_t verified = 0;
struct grub_file_verifier *ver;
void *context;
grub_file_t ret = 0;
grub_err_t err;
if ((type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_SIGNATURE
|| (type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_VERIFY_SIGNATURE
|| (type & GRUB_FILE_TYPE_SKIP_SIGNATURE))
return io;
if (io->device->disk &&
(io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID
|| io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID))
return io;
FOR_LIST_ELEMENTS(ver, grub_file_verifiers)
{
enum grub_verify_flags flags = 0;
err = ver->init (io, type, &context, &flags);
if (err)
goto fail_noclose;
if (!(flags & GRUB_VERIFY_FLAGS_SKIP_VERIFICATION))
break;
}
if (!ver)
/* No verifiers wanted to verify. Just return underlying file. */
return io;
ret = grub_malloc (sizeof (*ret));
if (!ret)
{
goto fail;
}
*ret = *io;
ret->fs = &verified_fs;
ret->not_easily_seekable = 0;
if (ret->size >> (sizeof (grub_size_t) * GRUB_CHAR_BIT - 1))
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"big file signature isn't implemented yet");
goto fail;
}
verified = grub_malloc (sizeof (*verified));
if (!verified)
{
goto fail;
}
verified->buf = grub_malloc (ret->size);
if (!verified->buf)
{
goto fail;
}
if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size)
{
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
io->name);
goto fail;
}
err = ver->write (context, verified->buf, ret->size);
if (err)
goto fail;
err = ver->fini (context);
if (err)
goto fail;
ver->close (context);
FOR_LIST_ELEMENTS_NEXT(ver, grub_file_verifiers)
{
enum grub_verify_flags flags = 0;
err = ver->init (io, type, &context, &flags);
if (err)
goto fail_noclose;
if (flags & GRUB_VERIFY_FLAGS_SKIP_VERIFICATION)
continue;
err = ver->write (context, verified->buf, ret->size);
if (err)
goto fail;
err = ver->fini (context);
if (err)
goto fail;
ver->close (context);
}
verified->file = io;
ret->data = verified;
return ret;
fail:
ver->close (context);
fail_noclose:
verified_free (verified);
grub_free (ret);
return NULL;
}
GRUB_MOD_INIT(verify_helper)
{
grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verify_helper_open);
}
GRUB_MOD_FINI(verify_helper)
{
grub_file_filter_unregister (GRUB_FILE_FILTER_VERIFY);
}
+1 -1
View File
@@ -170,7 +170,7 @@ extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
/* Filters with lower ID are executed first. */ /* Filters with lower ID are executed first. */
typedef enum grub_file_filter_id typedef enum grub_file_filter_id
{ {
GRUB_FILE_FILTER_PUBKEY, GRUB_FILE_FILTER_VERIFY,
GRUB_FILE_FILTER_GZIO, GRUB_FILE_FILTER_GZIO,
GRUB_FILE_FILTER_XZIO, GRUB_FILE_FILTER_XZIO,
GRUB_FILE_FILTER_LZOPIO, GRUB_FILE_FILTER_LZOPIO,
+1
View File
@@ -35,6 +35,7 @@ void EXPORT_FUNC(grub_list_push) (grub_list_t *head, grub_list_t item);
void EXPORT_FUNC(grub_list_remove) (grub_list_t item); void EXPORT_FUNC(grub_list_remove) (grub_list_t item);
#define FOR_LIST_ELEMENTS(var, list) for ((var) = (list); (var); (var) = (var)->next) #define FOR_LIST_ELEMENTS(var, list) for ((var) = (list); (var); (var) = (var)->next)
#define FOR_LIST_ELEMENTS_NEXT(var, list) for ((var) = (var)->next; (var); (var) = (var)->next)
#define FOR_LIST_ELEMENTS_SAFE(var, nxt, list) for ((var) = (list), (nxt) = ((var) ? (var)->next : 0); (var); (var) = (nxt), ((nxt) = (var) ? (var)->next : 0)) #define FOR_LIST_ELEMENTS_SAFE(var, nxt, list) for ((var) = (list), (nxt) = ((var) ? (var)->next : 0); (var); (var) = (nxt), ((nxt) = (var) ? (var)->next : 0))
static inline void * static inline void *
+42
View File
@@ -0,0 +1,42 @@
#include <grub/file.h>
#include <grub/list.h>
enum grub_verify_flags
{
GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1,
GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2,
};
struct grub_file_verifier
{
struct grub_file_verifier *next;
struct grub_file_verifier **prev;
const char *name;
/* Check if file needs to be verified and set up context. */
/* init/read/fini is structured in the same way as hash interface. */
grub_err_t (*init) (grub_file_t io, enum grub_file_type type,
void **context, enum grub_verify_flags *verify_flags);
/* Right now we pass the whole file in one call but it
will change in the future. If you insist on single buffer we can
you need to set GRUB_VERIFY_FLAGS_SINGLE_CHUNK in verify_flags.
*/
grub_err_t (*write) (void *context, void *buf, grub_size_t sz);
grub_err_t (*fini) (void *context);
void (*close) (void *context);
};
extern struct grub_file_verifier *grub_file_verifiers;
static inline void
grub_verifier_register (struct grub_file_verifier *ver)
{
grub_list_push (GRUB_AS_LIST_P (&grub_file_verifiers), GRUB_AS_LIST (ver));
}
static inline void
grub_verifier_unregister (struct grub_file_verifier *ver)
{
grub_list_remove (GRUB_AS_LIST (ver));
}