diff --git a/conf/common.rmk b/conf/common.rmk
index 0d19344a7..35b4620f4 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -619,4 +619,9 @@ setjmp_mod_SOURCES = lib/$(target_cpu)/setjmp.S
setjmp_mod_ASFLAGS = $(COMMON_ASFLAGS)
setjmp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+pkglib_MODULES += crypto.mod
+crypto_mod_SOURCES = lib/crypto.c
+crypto_mod_CFLAGS = $(COMMON_CFLAGS)
+crypto_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/gcry.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 45e1ccf91..ac9337e41 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -58,15 +58,13 @@ kernel_img_SOURCES = kern/i386/pc/startup.S \
kern/generic/millisleep.c \
kern/env.c \
term/i386/pc/console.c term/i386/vga_common.c \
- kern/crypto.c \
symlist.c
kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \
machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \
- machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h \
- crypto.h
+ machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h
kernel_img_CFLAGS = $(COMMON_CFLAGS) $(TARGET_IMG_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_KERNEL_MACHINE_LINK_ADDR) $(COMMON_CFLAGS)
diff --git a/include/grub/crypto.h b/include/grub/crypto.h
index 239b46666..5cd7f02b4 100644
--- a/include/grub/crypto.h
+++ b/include/grub/crypto.h
@@ -164,205 +164,58 @@ typedef struct gcry_md_spec
struct gcry_md_spec *next;
} gcry_md_spec_t;
-extern gcry_cipher_spec_t *EXPORT_VAR (grub_ciphers);
-extern gcry_md_spec_t *EXPORT_VAR (grub_digests);
-
-static inline void
-grub_cipher_register (gcry_cipher_spec_t *cipher)
-{
- cipher->next = grub_ciphers;
- grub_ciphers = cipher;
-}
-
-static inline void
-grub_cipher_unregister (gcry_cipher_spec_t *cipher)
-{
- gcry_cipher_spec_t **ciph;
- for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next))
- if (*ciph == cipher)
- *ciph = (*ciph)->next;
-}
-
-static inline void
-grub_md_register (gcry_md_spec_t *digest)
-{
- digest->next = grub_digests;
- grub_digests = digest;
-}
-
-static inline void
-grub_md_unregister (gcry_md_spec_t *cipher)
-{
- gcry_md_spec_t **ciph;
- for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next))
- if (*ciph == cipher)
- *ciph = (*ciph)->next;
-}
-
-static inline void
-grub_crypto_hash (const gcry_md_spec_t *hash, void *out, void *in,
- grub_size_t inlen)
-{
- grub_uint8_t ctx[hash->contextsize];
- hash->init (&ctx);
- hash->write (&ctx, in, inlen);
- hash->final (&ctx);
- grub_memcpy (out, hash->read (&ctx), hash->mdlen);
-}
-
-static inline 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;
-}
-
typedef struct grub_crypto_cipher_handle
{
const struct gcry_cipher_spec *cipher;
char ctx[0];
} *grub_crypto_cipher_handle_t;
-static inline 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)
- {
- 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;
- }
- return NULL;
-}
+const gcry_cipher_spec_t *
+grub_crypto_lookup_cipher_by_name (const char *name);
+grub_crypto_cipher_handle_t
+grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher);
-static inline grub_crypto_cipher_handle_t
-grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher)
-{
- grub_crypto_cipher_handle_t ret;
- ret = grub_malloc (sizeof (*ret) + cipher->contextsize);
- if (!ret)
- return NULL;
- ret->cipher = cipher;
- return ret;
-}
-
-static inline gcry_err_code_t
+gcry_err_code_t
grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
const unsigned char *key,
- unsigned keylen)
-{
- return cipher->cipher->setkey (cipher->ctx, key, keylen);
-}
+ unsigned keylen);
+void
+grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher);
-static inline void
-grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher)
-{
- grub_free (cipher);
-}
-
-
-static inline void
-grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size)
-{
- const grub_uint8_t *in1ptr = in1, *in2ptr = in2;
- grub_uint8_t *outptr = out;
- while (size--)
- {
- *outptr = *in1ptr ^ *in2ptr;
- in1ptr++;
- in2ptr++;
- outptr++;
- }
-}
-
-static inline grub_err_t
+void
+grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size);
+grub_err_t
grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
- void *out, void *in, grub_size_t size)
-{
- grub_uint8_t *inptr, *outptr, *end;
- if (size % cipher->cipher->blocksize != 0)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- "This encryption can't decrypt partial blocks");
- end = (grub_uint8_t *) in + size;
- for (inptr = in, outptr = out; inptr < end;
- inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
- cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
- return GRUB_ERR_NONE;
-}
+ void *out, void *in, grub_size_t size);
-static inline grub_err_t
+grub_err_t
grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
- void *out, void *in, grub_size_t size)
-{
- grub_uint8_t *inptr, *outptr, *end;
- if (size % cipher->cipher->blocksize != 0)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- "This encryption can't decrypt partial blocks");
- end = (grub_uint8_t *) in + size;
- for (inptr = in, outptr = out; inptr < end;
- inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
- cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
- return GRUB_ERR_NONE;
-}
-
-static inline grub_err_t
+ void *out, void *in, grub_size_t size);
+grub_err_t
grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size,
- void *iv_in)
-{
- grub_uint8_t *inptr, *outptr, *end;
- void *iv;
- if (size % cipher->cipher->blocksize != 0)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- "This encryption can't decrypt partial blocks");
- end = (grub_uint8_t *) in + size;
- iv = iv_in;
- for (inptr = in, outptr = out; inptr < end;
- inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
- {
- grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize);
- cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
- iv = outptr;
- }
- grub_memcpy (iv_in, iv, cipher->cipher->blocksize);
- return GRUB_ERR_NONE;
-}
-
-static inline grub_err_t
+ void *iv_in);
+grub_err_t
grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size,
- void *iv)
-{
- grub_uint8_t *inptr, *outptr, *end;
- grub_uint8_t ivt[cipher->cipher->blocksize];
- if (size % cipher->cipher->blocksize != 0)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- "This encryption can't decrypt partial blocks");
- end = (grub_uint8_t *) in + size;
- for (inptr = in, outptr = out; inptr < end;
- inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
- {
- grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
- cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
- grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
- grub_memcpy (iv, ivt, cipher->cipher->blocksize);
- }
- return GRUB_ERR_NONE;
-}
+ void *iv);
+void
+grub_cipher_register (gcry_cipher_spec_t *cipher);
+void
+grub_cipher_unregister (gcry_cipher_spec_t *cipher);
+void
+grub_md_register (gcry_md_spec_t *digest);
+void
+grub_md_unregister (gcry_md_spec_t *cipher);
+void
+grub_crypto_hash (const gcry_md_spec_t *hash, void *out, void *in,
+ grub_size_t inlen);
+const gcry_md_spec_t *
+grub_crypto_lookup_md_by_name (const char *name);
-
-void EXPORT_FUNC(grub_burn_stack) (grub_size_t size);
+void grub_burn_stack (grub_size_t size);
extern gcry_md_spec_t _gcry_digest_spec_md5;
#define GRUB_MD_MD5 ((const gcry_md_spec_t *) &_gcry_digest_spec_md5)
diff --git a/lib/crypto.c b/lib/crypto.c
new file mode 100644
index 000000000..64c386dae
--- /dev/null
+++ b/lib/crypto.c
@@ -0,0 +1,225 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
+ * 2007, 2008, 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 .
+ */
+
+#include
+#include
+#include
+
+static gcry_cipher_spec_t *grub_ciphers = NULL;
+static gcry_md_spec_t *grub_digests = NULL;
+
+/* Based on libgcrypt-1.4.4/src/misc.c. */
+void
+grub_burn_stack (grub_size_t size)
+{
+ char buf[64];
+
+ grub_memset (buf, 0, sizeof (buf));
+ if (size > sizeof (buf))
+ grub_burn_stack (size - sizeof (buf));
+}
+
+
+void
+grub_cipher_register (gcry_cipher_spec_t *cipher)
+{
+ cipher->next = grub_ciphers;
+ grub_ciphers = cipher;
+}
+
+void
+grub_cipher_unregister (gcry_cipher_spec_t *cipher)
+{
+ gcry_cipher_spec_t **ciph;
+ for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next))
+ if (*ciph == cipher)
+ *ciph = (*ciph)->next;
+}
+
+void
+grub_md_register (gcry_md_spec_t *digest)
+{
+ digest->next = grub_digests;
+ grub_digests = digest;
+}
+
+void
+grub_md_unregister (gcry_md_spec_t *cipher)
+{
+ gcry_md_spec_t **ciph;
+ for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next))
+ if (*ciph == cipher)
+ *ciph = (*ciph)->next;
+}
+
+void
+grub_crypto_hash (const gcry_md_spec_t *hash, void *out, void *in,
+ grub_size_t inlen)
+{
+ grub_uint8_t ctx[hash->contextsize];
+ hash->init (&ctx);
+ hash->write (&ctx, in, inlen);
+ hash->final (&ctx);
+ grub_memcpy (out, hash->read (&ctx), hash->mdlen);
+}
+
+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;
+}
+
+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)
+ {
+ 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;
+ }
+ return NULL;
+}
+
+
+grub_crypto_cipher_handle_t
+grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher)
+{
+ grub_crypto_cipher_handle_t ret;
+ ret = grub_malloc (sizeof (*ret) + cipher->contextsize);
+ if (!ret)
+ return NULL;
+ ret->cipher = cipher;
+ return ret;
+}
+
+gcry_err_code_t
+grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
+ const unsigned char *key,
+ unsigned keylen)
+{
+ return cipher->cipher->setkey (cipher->ctx, key, keylen);
+}
+
+
+void
+grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher)
+{
+ grub_free (cipher);
+}
+
+
+void
+grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size)
+{
+ const grub_uint8_t *in1ptr = in1, *in2ptr = in2;
+ grub_uint8_t *outptr = out;
+ while (size--)
+ {
+ *outptr = *in1ptr ^ *in2ptr;
+ in1ptr++;
+ in2ptr++;
+ outptr++;
+ }
+}
+
+grub_err_t
+grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
+ void *out, void *in, grub_size_t size)
+{
+ grub_uint8_t *inptr, *outptr, *end;
+ if (size % cipher->cipher->blocksize != 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "This encryption can't decrypt partial blocks");
+ end = (grub_uint8_t *) in + size;
+ for (inptr = in, outptr = out; inptr < end;
+ inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+ cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
+ void *out, void *in, grub_size_t size)
+{
+ grub_uint8_t *inptr, *outptr, *end;
+ if (size % cipher->cipher->blocksize != 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "This encryption can't decrypt partial blocks");
+ end = (grub_uint8_t *) in + size;
+ for (inptr = in, outptr = out; inptr < end;
+ inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+ cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
+ void *out, void *in, grub_size_t size,
+ void *iv_in)
+{
+ grub_uint8_t *inptr, *outptr, *end;
+ void *iv;
+ if (size % cipher->cipher->blocksize != 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "This encryption can't decrypt partial blocks");
+ end = (grub_uint8_t *) in + size;
+ iv = iv_in;
+ for (inptr = in, outptr = out; inptr < end;
+ inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+ {
+ grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize);
+ cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
+ iv = outptr;
+ }
+ grub_memcpy (iv_in, iv, cipher->cipher->blocksize);
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
+ void *out, void *in, grub_size_t size,
+ void *iv)
+{
+ grub_uint8_t *inptr, *outptr, *end;
+ grub_uint8_t ivt[cipher->cipher->blocksize];
+ if (size % cipher->cipher->blocksize != 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "This encryption can't decrypt partial blocks");
+ end = (grub_uint8_t *) in + size;
+ for (inptr = in, outptr = out; inptr < end;
+ inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+ {
+ grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
+ cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
+ grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
+ grub_memcpy (iv, ivt, cipher->cipher->blocksize);
+ }
+ return GRUB_ERR_NONE;
+}