### General targets.
CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA) po/*.mo
-pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst
+pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst
moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk
cat $(DEFSYMFILES) /dev/null \
| $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \
video.lst: $(VIDEOFILES)
cat $^ /dev/null | sort | uniq > $@
+crypto.lst: lib/libgcrypt-grub/cipher/crypto.lst
+ cp $^ $@
+
ifneq (true, $(MAKEINFO))
info_INFOS += docs/grub.info
endif
normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c \
normal/completion.c normal/main.c normal/color.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
- normal/menu_text.c \
+ normal/menu_text.c normal/crypto.c \
script/main.c script/execute.c script/function.c \
script/lexer.c script/script.c grub_script.tab.c \
partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \
normal/auth.c normal/autofs.c normal/handler.c \
normal/color.c normal/completion.c normal/datetime.c normal/menu.c \
normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \
- normal/misc.c
+ normal/misc.c normal/crypto.c
normal_mod_CFLAGS = $(COMMON_CFLAGS)
normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
/* For indistinguishibility. */
#define GRUB_ACCESS_DENIED grub_error (GRUB_ERR_ACCESS_DENIED, "Access denied.")
+extern void (*grub_crypto_autoload_hook) (const char *name);
+
#endif
/* Defined in `autofs.c'. */
void read_fs_list (void);
+void read_crypto_list (void);
+
#ifdef GRUB_UTIL
void grub_normal_init (void);
static gcry_cipher_spec_t *grub_ciphers = NULL;
static gcry_md_spec_t *grub_digests = NULL;
+void (*grub_crypto_autoload_hook) (const char *name) = NULL;
+
/* Based on libgcrypt-1.4.4/src/misc.c. */
void
grub_burn_stack (grub_size_t size)
grub_crypto_lookup_md_by_name (const char *name)
{
const gcry_md_spec_t *md;
- for (md = grub_digests; md; md = md->next)
- if (grub_strcasecmp (name, md->name) == 0)
- return md;
- return NULL;
+ int first = 1;
+ while (1)
+ {
+ for (md = grub_digests; md; md = md->next)
+ if (grub_strcasecmp (name, md->name) == 0)
+ return md;
+ if (grub_crypto_autoload_hook && first)
+ grub_crypto_autoload_hook (name);
+ else
+ return NULL;
+ first = 0;
+ }
}
const gcry_cipher_spec_t *
grub_crypto_lookup_cipher_by_name (const char *name)
{
const gcry_cipher_spec_t *ciph;
- for (ciph = grub_ciphers; ciph; ciph = ciph->next)
+ int first = 1;
+ while (1)
{
- const char **alias;
- if (grub_strcasecmp (name, ciph->name) == 0)
- return ciph;
- if (!ciph->aliases)
- continue;
- for (alias = ciph->aliases; *alias; alias++)
- if (grub_strcasecmp (name, *alias) == 0)
- return ciph;
+ for (ciph = grub_ciphers; ciph; ciph = ciph->next)
+ {
+ const char **alias;
+ if (grub_strcasecmp (name, ciph->name) == 0)
+ return ciph;
+ if (!ciph->aliases)
+ continue;
+ for (alias = ciph->aliases; *alias; alias++)
+ if (grub_strcasecmp (name, *alias) == 0)
+ return ciph;
+ }
+ if (grub_crypto_autoload_hook && first)
+ grub_crypto_autoload_hook (name);
+ else
+ return NULL;
+ first = 0;
}
- return NULL;
}
--- /dev/null
+/* crypto.c - support crypto autoload */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/crypto.h>
+#include <grub/normal.h>
+
+struct load_spec
+{
+ struct load_spec *next;
+ char *name;
+ char *modname;
+};
+
+struct load_spec *crypto_specs = NULL;
+
+static void
+grub_crypto_autoload (const char *name)
+{
+ struct load_spec *cur;
+ grub_dl_t mod;
+
+ for (cur = crypto_specs; cur; cur = cur->next)
+ if (grub_strcasecmp (name, cur->name) == 0)
+ {
+ mod = grub_dl_load (cur->modname);
+ if (mod)
+ grub_dl_ref (mod);
+ grub_errno = GRUB_ERR_NONE;
+ }
+}
+
+static void
+grub_crypto_spec_free (void)
+{
+ struct load_spec *cur, *next;
+ for (cur = crypto_specs; cur; cur = next)
+ {
+ next = cur->next;
+ grub_free (cur->name);
+ grub_free (cur->modname);
+ grub_free (cur);
+ }
+ crypto_specs = NULL;
+}
+
+
+/* Read the file crypto.lst for auto-loading. */
+void
+read_crypto_list (void)
+{
+ const char *prefix;
+ char *filename;
+ grub_file_t file;
+ char *buf = NULL;
+
+ prefix = grub_env_get ("prefix");
+ if (!prefix)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return;
+ }
+
+ filename = grub_malloc (grub_strlen (prefix) + sizeof ("/crypto.lst"));
+ if (!filename)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return;
+ }
+
+ grub_sprintf (filename, "%s/crypto.lst", prefix);
+ file = grub_file_open (filename);
+ if (!file)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return;
+ }
+
+ /* Override previous commands.lst. */
+ grub_crypto_spec_free ();
+
+ for (;; grub_free (buf))
+ {
+ char *p, *name;
+ struct load_spec *cur;
+
+ buf = grub_file_getline (file);
+
+ if (! buf)
+ break;
+
+ name = buf;
+
+ p = grub_strchr (name, ':');
+ if (! p)
+ continue;
+
+ *p = '\0';
+ while (*++p == ' ')
+ ;
+
+ cur = grub_malloc (sizeof (*cur));
+ if (!cur)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+
+ cur->name = grub_strdup (name);
+ if (! name)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ grub_free (cur);
+ continue;
+ }
+
+ cur->modname = grub_strdup (p);
+ if (! cur->modname)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ grub_free (cur);
+ grub_free (cur->name);
+ continue;
+ }
+ cur->next = crypto_specs;
+ crypto_specs = cur;
+ }
+
+ grub_file_close (file);
+
+ grub_errno = GRUB_ERR_NONE;
+
+ grub_crypto_autoload_hook = grub_crypto_autoload;
+}
read_command_list ();
read_fs_list ();
read_handler_list ();
+ read_crypto_list ();
grub_command_execute ("parser.grub", 0, 0);
reader_nested = nested;
"_gcry_digest_spec_tiger" : 64,
"_gcry_digest_spec_whirlpool" : 64}
+cryptolist = open (os.path.join (cipher_dir_out, "crypto.lst"), "w")
+
+# rijndael is the only cipher using aliases. So no need for mangling, just
+# hardcode it
+cryptolist.write ("RIJNDAEL: gcry_rijndael\n");
+cryptolist.write ("RIJNDAEL192: gcry_rijndael\n");
+cryptolist.write ("RIJNDAEL256: gcry_rijndael\n");
+cryptolist.write ("AES128: gcry_rijndael\n");
+cryptolist.write ("AES-128: gcry_rijndael\n");
+cryptolist.write ("AES-192: gcry_rijndael\n");
+cryptolist.write ("AES-256: gcry_rijndael\n");
+
for cipher_file in cipher_files:
infile = os.path.join (cipher_dir_in, cipher_file)
outfile = os.path.join (cipher_dir_out, cipher_file)
skip = False
skip2 = False
ismd = False
+ iscryptostart = False
iscomma = False
+ isglue = False
+ if isc:
+ modname = cipher_file [0:len(cipher_file) - 2]
+ if re.match (".*-glue$", modname):
+ modname = modname.replace ("-glue", "")
+ isglue = True
+ modname = "gcry_%s" % modname
for line in f:
if skip:
if line[0] == "}":
if not re.search (" *};", line) is None:
skip2 = False
continue
+ if iscryptostart:
+ s = re.search (" *\"([A-Z0-9_a-z]*)\"", line)
+ if not s is None:
+ sg = s.groups()[0]
+ cryptolist.write (("%s: %s\n") % (sg, modname))
+ iscryptostart = False
if ismd:
if not re.search (" *};", line) is None:
if not mdblocksizes.has_key (mdname):
continue
m = re.match ("gcry_cipher_spec_t", line)
if isc and not m is None:
+ assert (not iscryptostart)
ciphername = line [len ("gcry_cipher_spec_t"):].strip ()
ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group ()
ciphernames.append (ciphername)
+ iscryptostart = True
m = re.match ("gcry_md_spec_t", line)
if isc and not m is None:
assert (not ismd)
+ assert (not iscryptostart)
mdname = line [len ("gcry_md_spec_t"):].strip ()
mdname = re.match("[a-zA-Z0-9_]*",mdname).group ()
mdnames.append (mdname)
ismd = True
+ iscryptostart = True
m = re.match ("static const char \*selftest.*;$", line)
if not m is None:
fname = line[len ("static const char \*"):]
continue
fw.write (line)
if len (ciphernames) > 0 or len (mdnames) > 0:
- modname = cipher_file [0:len(cipher_file) - 2]
- if re.match (".*-glue$", modname):
+ if isglue:
modfiles = "lib/libgcrypt-grub/cipher/%s lib/libgcrypt-grub/cipher/%s" \
% (cipher_file, cipher_file.replace ("-glue.c", ".c"))
- modname = modname.replace ("-glue", "")
else:
modfiles = "lib/libgcrypt-grub/cipher/%s" % cipher_file
- modname = "gcry_%s" % modname
chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname
if nch:
chlognew = "%s\n %s" % (chlognew, chmsg)
chlog = "%s%sSkipped unknown file\n" % (chlog, chlognew)
print ("WARNING: unknown file %s" % cipher_file)
+cryptolist.close ()
+chlog = "%s * crypto.lst: New file.\n" % chlog
+
outfile = os.path.join (cipher_dir_out, "types.h")
fw=open (outfile, "w")
fw.write ("#include <grub/types.h>\n")