]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Crypto module autoloading
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 23 Dec 2009 16:33:35 +0000 (17:33 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 23 Dec 2009 16:33:35 +0000 (17:33 +0100)
Makefile.in
conf/any-emu.rmk
conf/common.rmk
include/grub/crypto.h
include/grub/normal.h
lib/crypto.c
normal/crypto.c [new file with mode: 0644]
normal/main.c
util/import_gcry.py

index 46b380cd5f0de83fb504f045017f94d3ade8cf7e..b28b660da59a1b815b8c810baa4e8942c6e06161 100644 (file)
@@ -169,7 +169,7 @@ endif
 ### 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) > $@ \
@@ -193,6 +193,9 @@ parttool.lst: $(PARTTOOLFILES)
 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
index 451ab3393a2634fcf39f4a50cbf4b995fd186c83..a3b3c84d965aea6d2b149f40af5964d102a63bdf 100644 (file)
@@ -27,7 +27,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c   \
        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   \
index 81372d20c63df27bfdfc9e2d2ddccd1888fad874..64be988b9ff6185d73dba5c031735bdcebbceda7 100644 (file)
@@ -543,7 +543,7 @@ normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.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)
 
index 3129131cbd5944e401bfe356ead8af2d25f3446d..48b52ee6519d3c312d12314fa9d8422efde97b8d 100644 (file)
@@ -270,4 +270,6 @@ grub_password_get (char buf[], unsigned buf_size);
 /* For indistinguishibility.  */
 #define GRUB_ACCESS_DENIED grub_error (GRUB_ERR_ACCESS_DENIED, "Access denied.")
 
+extern void (*grub_crypto_autoload_hook) (const char *name);
+
 #endif
index e55553de54fc7c2941917ab0a146ce1bd67eb013..66b427bcbbcfc2600f4833e6186b1ba800853a7a 100644 (file)
@@ -95,6 +95,8 @@ void read_command_list (void);
 /* Defined in `autofs.c'.  */
 void read_fs_list (void);
 
+void read_crypto_list (void);
+
 
 #ifdef GRUB_UTIL
 void grub_normal_init (void);
index 06104bd4d00909b7d9501204cf328c636d562a0c..021560d6cf9d67d1002458814eda709524f7da13 100644 (file)
@@ -32,6 +32,8 @@ struct grub_crypto_hmac_handle
 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)
@@ -91,28 +93,44 @@ const gcry_md_spec_t *
 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;
 }
 
 
diff --git a/normal/crypto.c b/normal/crypto.c
new file mode 100644 (file)
index 0000000..6733027
--- /dev/null
@@ -0,0 +1,153 @@
+/* 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;
+}
index 3166ea1467ae4d285257bad1a30de5d702e02c1e..189244aa008215773bba4c18dd7644f502e3ba2c 100644 (file)
@@ -428,6 +428,7 @@ grub_normal_execute (const char *config, int nested, int batch)
   read_command_list ();
   read_fs_list ();
   read_handler_list ();
+  read_crypto_list ();
   grub_command_execute ("parser.grub", 0, 0);
 
   reader_nested = nested;
index fe68c85a4ba636554c2b3a98e7daadab5569ee03..93bf5982fc990ffbca7e320c59be064b3e40dd75 100644 (file)
@@ -61,6 +61,18 @@ mdblocksizes = {"_gcry_digest_spec_crc32" : 64,
                 "_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)
@@ -86,7 +98,15 @@ for cipher_file in cipher_files:
         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] == "}":
@@ -96,6 +116,12 @@ for cipher_file in cipher_files:
                 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):
@@ -133,16 +159,20 @@ for cipher_file in cipher_files:
                 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 \*"):]
@@ -185,14 +215,11 @@ for cipher_file in cipher_files:
                 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)
@@ -238,6 +265,9 @@ for cipher_file in cipher_files:
     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")