2N/A#*
2N/A#* GRUB -- GRand Unified Bootloader
2N/A#* Copyright (C) 2009 Free Software Foundation, Inc.
2N/A#*
2N/A#* GRUB is free software: you can redistribute it and/or modify
2N/A#* it under the terms of the GNU General Public License as published by
2N/A#* the Free Software Foundation, either version 3 of the License, or
2N/A#* (at your option) any later version.
2N/A#*
2N/A#* GRUB is distributed in the hope that it will be useful,
2N/A#* but WITHOUT ANY WARRANTY; without even the implied warranty of
2N/A#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2N/A#* GNU General Public License for more details.
2N/A#*
2N/A#* You should have received a copy of the GNU General Public License
2N/A#* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
2N/A#*
2N/A
2N/Aimport re
2N/Aimport sys
2N/Aimport os
2N/Aimport datetime
2N/Aimport codecs
2N/A
2N/Aif len (sys.argv) < 3:
2N/A print ("Usage: %s SOURCE DESTINATION" % sys.argv[0])
2N/A exit (0)
2N/Aindir = sys.argv[1]
2N/Aoutdir = sys.argv[2]
2N/A
2N/Abasedir = os.path.join (outdir, "lib/libgcrypt-grub")
2N/Atry:
2N/A os.makedirs (basedir)
2N/Aexcept:
2N/A print ("WARNING: %s already exists" % basedir)
2N/Acipher_dir_in = os.path.join (indir, "cipher")
2N/Acipher_dir_out = os.path.join (basedir, "cipher")
2N/Atry:
2N/A os.makedirs (cipher_dir_out)
2N/Aexcept:
2N/A print ("WARNING: %s already exists" % cipher_dir_out)
2N/A
2N/Acipher_files = os.listdir (cipher_dir_in)
2N/Aconf = codecs.open (os.path.join ("grub-core", "Makefile.gcry.def"), "w", "utf-8")
2N/Aconf.write ("AutoGen definitions Makefile.tpl;\n\n")
2N/Aconfutil = codecs.open ("Makefile.utilgcry.def", "w", "utf-8")
2N/Aconfutil.write ("AutoGen definitions Makefile.tpl;\n\n")
2N/Aconfutil.write ("library = {\n");
2N/Aconfutil.write (" name = libgrubgcry.a;\n");
2N/Aconfutil.write (" cflags = '$(CFLAGS_GCRY)';\n");
2N/Aconfutil.write (" cppflags = '$(CPPFLAGS_GCRY)';\n");
2N/Aconfutil.write ("\n");
2N/Achlog = ""
2N/Amodules = []
2N/A
2N/A# Strictly speaking CRC32/CRC24 work on bytes so this value should be 1
2N/A# But libgcrypt uses 64. Let's keep the value for compatibility. Since
2N/A# noone uses CRC24/CRC32 for HMAC this is no problem
2N/Amdblocksizes = {"_gcry_digest_spec_crc32" : 64,
2N/A "_gcry_digest_spec_crc32_rfc1510" : 64,
2N/A "_gcry_digest_spec_crc24_rfc2440" : 64,
2N/A "_gcry_digest_spec_md4" : 64,
2N/A "_gcry_digest_spec_md5" : 64,
2N/A "_gcry_digest_spec_rmd160" : 64,
2N/A "_gcry_digest_spec_sha1" : 64,
2N/A "_gcry_digest_spec_sha224" : 64,
2N/A "_gcry_digest_spec_sha256" : 64,
2N/A "_gcry_digest_spec_sha384" : 128,
2N/A "_gcry_digest_spec_sha512" : 128,
2N/A "_gcry_digest_spec_tiger" : 64,
2N/A "_gcry_digest_spec_whirlpool" : 64}
2N/A
2N/Acryptolist = codecs.open (os.path.join (cipher_dir_out, "crypto.lst"), "w", "utf-8")
2N/A
2N/A# rijndael is the only cipher using aliases. So no need for mangling, just
2N/A# hardcode it
2N/Acryptolist.write ("RIJNDAEL: gcry_rijndael\n");
2N/Acryptolist.write ("RIJNDAEL192: gcry_rijndael\n");
2N/Acryptolist.write ("RIJNDAEL256: gcry_rijndael\n");
2N/Acryptolist.write ("AES128: gcry_rijndael\n");
2N/Acryptolist.write ("AES-128: gcry_rijndael\n");
2N/Acryptolist.write ("AES-192: gcry_rijndael\n");
2N/Acryptolist.write ("AES-256: gcry_rijndael\n");
2N/A
2N/Acryptolist.write ("ADLER32: adler32\n");
2N/Acryptolist.write ("CRC64: crc64\n");
2N/A
2N/Afor cipher_file in cipher_files:
2N/A infile = os.path.join (cipher_dir_in, cipher_file)
2N/A outfile = os.path.join (cipher_dir_out, cipher_file)
2N/A if cipher_file == "ChangeLog":
2N/A continue
2N/A chlognew = " * %s" % cipher_file
2N/A if re.match ("(Manifest|Makefile\.am|ac\.c|cipher\.c|hash-common\.c|hmac-tests\.c|md\.c|pubkey\.c)$", cipher_file):
2N/A chlog = "%s%s: Removed\n" % (chlog, chlognew)
2N/A continue
2N/A # Autogenerated files. Not even worth mentionning in ChangeLog
2N/A if re.match ("Makefile\.in$", cipher_file):
2N/A continue
2N/A nch = False
2N/A if re.match (".*\.[ch]$", cipher_file):
2N/A isc = re.match (".*\.c$", cipher_file)
2N/A f = codecs.open (infile, "r", "utf-8")
2N/A fw = codecs.open (outfile, "w", "utf-8")
2N/A fw.write ("/* This file was automatically imported with \n")
2N/A fw.write (" import_gcry.py. Please don't modify it */\n")
2N/A fw.write ("#include <grub/dl.h>\n")
2N/A if cipher_file == "camellia.h":
2N/A fw.write ("#include <grub/misc.h>\n")
2N/A fw.write ("void camellia_setup128(const unsigned char *key, grub_uint32_t *subkey);\n")
2N/A fw.write ("void camellia_setup192(const unsigned char *key, grub_uint32_t *subkey);\n")
2N/A fw.write ("void camellia_setup256(const unsigned char *key, grub_uint32_t *subkey);\n")
2N/A fw.write ("void camellia_encrypt128(const grub_uint32_t *subkey, grub_uint32_t *io);\n")
2N/A fw.write ("void camellia_encrypt192(const grub_uint32_t *subkey, grub_uint32_t *io);\n")
2N/A fw.write ("void camellia_encrypt256(const grub_uint32_t *subkey, grub_uint32_t *io);\n")
2N/A fw.write ("void camellia_decrypt128(const grub_uint32_t *subkey, grub_uint32_t *io);\n")
2N/A fw.write ("void camellia_decrypt192(const grub_uint32_t *subkey, grub_uint32_t *io);\n")
2N/A fw.write ("void camellia_decrypt256(const grub_uint32_t *subkey, grub_uint32_t *io);\n")
2N/A fw.write ("#define memcpy grub_memcpy\n")
2N/A # Whole libgcrypt is distributed under GPLv3+ or compatible
2N/A if isc:
2N/A fw.write ("GRUB_MOD_LICENSE (\"GPLv3+\");\n")
2N/A
2N/A ciphernames = []
2N/A mdnames = []
2N/A hold = False
2N/A skip = False
2N/A skip2 = False
2N/A ismd = False
2N/A iscipher = False
2N/A iscryptostart = False
2N/A iscomma = False
2N/A isglue = False
2N/A skip_statement = False
2N/A if isc:
2N/A modname = cipher_file [0:len(cipher_file) - 2]
2N/A if re.match (".*-glue$", modname):
2N/A modname = modname.replace ("-glue", "")
2N/A isglue = True
2N/A modname = "gcry_%s" % modname
2N/A for line in f:
2N/A line = line
2N/A if skip_statement:
2N/A if not re.search (";", line) is None:
2N/A skip_statement = False
2N/A continue
2N/A if skip:
2N/A if line[0] == "}":
2N/A skip = False
2N/A continue
2N/A if skip2:
2N/A if not re.search (" *};", line) is None:
2N/A skip2 = False
2N/A continue
2N/A if iscryptostart:
2N/A s = re.search (" *\"([A-Z0-9_a-z]*)\"", line)
2N/A if not s is None:
2N/A sg = s.groups()[0]
2N/A cryptolist.write (("%s: %s\n") % (sg, modname))
2N/A iscryptostart = False
2N/A if ismd or iscipher:
2N/A if not re.search (" *};", line) is None:
2N/A if not iscomma:
2N/A fw.write (" ,\n")
2N/A fw.write ("#ifdef GRUB_UTIL\n");
2N/A fw.write (" .modname = \"%s\",\n" % modname);
2N/A fw.write ("#endif\n");
2N/A if ismd:
2N/A if not (mdname in mdblocksizes):
2N/A print ("ERROR: Unknown digest blocksize: %s\n"
2N/A % mdname)
2N/A exit (1)
2N/A fw.write (" .blocksize = %s\n"
2N/A % mdblocksizes [mdname])
2N/A ismd = False
2N/A iscipher = False
2N/A iscomma = not re.search (",$", line) is None
2N/A # Used only for selftests.
2N/A m = re.match ("(static byte|static unsigned char) (weak_keys_chksum)\[[0-9]*\] =", line)
2N/A if not m is None:
2N/A skip = True
2N/A fname = m.groups ()[1]
2N/A chmsg = "(%s): Removed." % fname
2N/A if nch:
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A else:
2N/A chlognew = "%s %s" % (chlognew, chmsg)
2N/A nch = True
2N/A continue
2N/A if hold:
2N/A hold = False
2N/A # We're optimising for size.
2N/A if not re.match ("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer|tripledes_set2keys|do_tripledes_set_extra_info|_gcry_rmd160_mixblock|serpent_test)", line) is None:
2N/A skip = True
2N/A if not re.match ("serpent_test", line) is None:
2N/A fw.write ("static const char *serpent_test (void) { return 0; }\n");
2N/A fname = re.match ("[a-zA-Z0-9_]*", line).group ()
2N/A chmsg = "(%s): Removed." % fname
2N/A if nch:
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A else:
2N/A chlognew = "%s %s" % (chlognew, chmsg)
2N/A nch = True
2N/A continue
2N/A else:
2N/A fw.write (holdline)
2N/A m = re.match ("# *include <(.*)>", line)
2N/A if not m is None:
2N/A chmsg = "Removed including of %s" % m.groups ()[0]
2N/A if nch:
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A else:
2N/A chlognew = "%s: %s" % (chlognew, chmsg)
2N/A nch = True
2N/A continue
2N/A m = re.match ("gcry_cipher_spec_t", line)
2N/A if isc and not m is None:
2N/A assert (not iscryptostart)
2N/A assert (not iscipher)
2N/A assert (not iscryptostart)
2N/A ciphername = line [len ("gcry_cipher_spec_t"):].strip ()
2N/A ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group ()
2N/A ciphernames.append (ciphername)
2N/A iscipher = True
2N/A iscryptostart = True
2N/A m = re.match ("gcry_md_spec_t", line)
2N/A if isc and not m is None:
2N/A assert (not ismd)
2N/A assert (not iscipher)
2N/A assert (not iscryptostart)
2N/A mdname = line [len ("gcry_md_spec_t"):].strip ()
2N/A mdname = re.match("[a-zA-Z0-9_]*",mdname).group ()
2N/A mdnames.append (mdname)
2N/A ismd = True
2N/A iscryptostart = True
2N/A m = re.match ("static const char \*selftest.*;$", line)
2N/A if not m is None:
2N/A fname = line[len ("static const char \*"):]
2N/A fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
2N/A chmsg = "(%s): Removed declaration." % fname
2N/A if nch:
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A else:
2N/A chlognew = "%s %s" % (chlognew, chmsg)
2N/A nch = True
2N/A continue
2N/A m = re.match ("(static const char( |)\*|static gpg_err_code_t|void|static int|static gcry_err_code_t)$", line)
2N/A if not m is None:
2N/A hold = True
2N/A holdline = line
2N/A continue
2N/A m = re.match ("static int tripledes_set2keys \(.*\);", line)
2N/A if not m is None:
2N/A continue
2N/A m = re.match ("static int tripledes_set2keys \(", line)
2N/A if not m is None:
2N/A skip_statement = True
2N/A continue
2N/A m = re.match ("cipher_extra_spec_t", line)
2N/A if isc and not m is None:
2N/A skip2 = True
2N/A fname = line[len ("cipher_extra_spec_t "):]
2N/A fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
2N/A chmsg = "(%s): Removed." % fname
2N/A if nch:
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A else:
2N/A chlognew = "%s %s" % (chlognew, chmsg)
2N/A nch = True
2N/A continue
2N/A m = re.match ("md_extra_spec_t", line)
2N/A if isc and not m is None:
2N/A skip2 = True
2N/A fname = line[len ("md_extra_spec_t "):]
2N/A fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
2N/A chmsg = "(%s): Removed." % fname
2N/A if nch:
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A else:
2N/A chlognew = "%s %s" % (chlognew, chmsg)
2N/A nch = True
2N/A continue
2N/A fw.write (line)
2N/A if len (ciphernames) > 0 or len (mdnames) > 0:
2N/A if isglue:
2N/A modfiles = "lib/libgcrypt-grub/cipher/%s lib/libgcrypt-grub/cipher/%s" \
2N/A % (cipher_file, cipher_file.replace ("-glue.c", ".c"))
2N/A else:
2N/A modfiles = "lib/libgcrypt-grub/cipher/%s" % cipher_file
2N/A modules.append (modname)
2N/A chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname
2N/A if nch:
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A else:
2N/A chlognew = "%s%s" % (chlognew, chmsg)
2N/A nch = True
2N/A fw.write ("\n\nGRUB_MOD_INIT(%s)\n" % modname)
2N/A fw.write ("{\n")
2N/A for ciphername in ciphernames:
2N/A chmsg = "Register cipher %s" % ciphername
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A fw.write (" grub_cipher_register (&%s);\n" % ciphername)
2N/A for mdname in mdnames:
2N/A chmsg = "Register digest %s" % mdname
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A fw.write (" grub_md_register (&%s);\n" % mdname)
2N/A fw.write ("}")
2N/A chmsg = "(GRUB_MOD_FINI(%s)): New function\n" % modname
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A fw.write ("\n\nGRUB_MOD_FINI(%s)\n" % modname)
2N/A fw.write ("{\n")
2N/A for ciphername in ciphernames:
2N/A chmsg = "Unregister cipher %s" % ciphername
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A fw.write (" grub_cipher_unregister (&%s);\n" % ciphername)
2N/A for mdname in mdnames:
2N/A chmsg = "Unregister MD %s" % mdname
2N/A chlognew = "%s\n %s" % (chlognew, chmsg)
2N/A fw.write (" grub_md_unregister (&%s);\n" % mdname)
2N/A fw.write ("}\n")
2N/A conf.write ("module = {\n")
2N/A conf.write (" name = %s;\n" % modname)
2N/A for src in modfiles.split():
2N/A conf.write (" common = %s;\n" % src)
2N/A confutil.write (" common = grub-core/%s;\n" % src)
2N/A conf.write (" cflags = '$(CFLAGS_GCRY)';\n");
2N/A conf.write (" cppflags = '$(CPPFLAGS_GCRY)';\n");
2N/A conf.write ("};\n\n")
2N/A elif isc and cipher_file != "camellia.c":
2N/A print ("WARNING: C file isn't a module: %s" % cipher_file)
2N/A f.close ()
2N/A fw.close ()
2N/A if nch:
2N/A chlog = "%s%s\n" % (chlog, chlognew)
2N/A continue
2N/A chlog = "%s%sSkipped unknown file\n" % (chlog, chlognew)
2N/A print ("WARNING: unknown file %s" % cipher_file)
2N/A
2N/Acryptolist.close ()
2N/Achlog = "%s * crypto.lst: New file.\n" % chlog
2N/A
2N/Aoutfile = os.path.join (cipher_dir_out, "types.h")
2N/Afw=codecs.open (outfile, "w", "utf-8")
2N/Afw.write ("#include <grub/types.h>\n")
2N/Afw.write ("#include <cipher_wrap.h>\n")
2N/Achlog = "%s * types.h: New file.\n" % chlog
2N/Afw.close ()
2N/A
2N/Aoutfile = os.path.join (cipher_dir_out, "memory.h")
2N/Afw=codecs.open (outfile, "w", "utf-8")
2N/Afw.write ("#include <cipher_wrap.h>\n")
2N/Achlog = "%s * memory.h: New file.\n" % chlog
2N/Afw.close ()
2N/A
2N/A
2N/Aoutfile = os.path.join (cipher_dir_out, "cipher.h")
2N/Afw=codecs.open (outfile, "w", "utf-8")
2N/Afw.write ("#include <grub/crypto.h>\n")
2N/Afw.write ("#include <cipher_wrap.h>\n")
2N/Achlog = "%s * cipher.h: Likewise.\n" % chlog
2N/Afw.close ()
2N/A
2N/Aoutfile = os.path.join (cipher_dir_out, "g10lib.h")
2N/Afw=codecs.open (outfile, "w", "utf-8")
2N/Afw.write ("#include <cipher_wrap.h>\n")
2N/Achlog = "%s * g10lib.h: Likewise.\n" % chlog
2N/Afw.close ()
2N/A
2N/Ainfile = os.path.join (cipher_dir_in, "ChangeLog")
2N/Aoutfile = os.path.join (cipher_dir_out, "ChangeLog")
2N/A
2N/Aconf.close ();
2N/A
2N/Ainitfile = codecs.open (os.path.join (cipher_dir_out, "init.c"), "w", "utf-8")
2N/Afor module in modules:
2N/A initfile.write ("extern void grub_%s_init (void);\n" % module)
2N/A initfile.write ("extern void grub_%s_fini (void);\n" % module)
2N/Ainitfile.write ("\n")
2N/Ainitfile.write ("void\n")
2N/Ainitfile.write ("grub_gcry_init_all (void)\n")
2N/Ainitfile.write ("{\n")
2N/Afor module in modules:
2N/A initfile.write (" grub_%s_init ();\n" % module)
2N/Ainitfile.write ("}\n")
2N/Ainitfile.write ("\n")
2N/Ainitfile.write ("void\n")
2N/Ainitfile.write ("grub_gcry_fini_all (void)\n")
2N/Ainitfile.write ("{\n")
2N/Afor module in modules:
2N/A initfile.write (" grub_%s_fini ();\n" % module)
2N/Ainitfile.write ("}\n")
2N/Ainitfile.close ()
2N/A
2N/Aconfutil.write (" common = grub-core/lib/libgcrypt-grub/cipher/init.c;\n")
2N/Aconfutil.write ("};\n");
2N/Aconfutil.close ();
2N/A
2N/A
2N/Af=codecs.open (infile, "r", "utf-8")
2N/Afw=codecs.open (outfile, "w", "utf-8")
2N/Adt = datetime.date.today ()
2N/Afw.write ("%04d-%02d-%02d Automatic import tool\n" % \
2N/A (dt.year,dt.month, dt.day))
2N/Afw.write ("\n")
2N/Afw.write (" Imported ciphers to GRUB\n")
2N/Afw.write ("\n")
2N/Afw.write (chlog)
2N/Afw.write ("\n")
2N/Afor line in f:
2N/A fw.write (line)
2N/Af.close ()
2N/Afw.close ()