--- autogen.sh | 1 + conf/Makefile.common | 4 +- grub-core/Makefile.core.def | 36 +- grub-core/commands/hashsum.c | 2 +- grub-core/commands/legacycfg.c | 6 +- grub-core/commands/pgp.c | 114 +--- grub-core/commands/xnu_uuid.c | 2 +- grub-core/disk/cryptodisk.c | 2 +- grub-core/io/gzio.c | 2 +- grub-core/io/lzopio.c | 2 +- grub-core/lib/adler32.c | 21 +- grub-core/lib/b64dec.c | 293 +++++++++ grub-core/lib/crc64.c | 24 +- grub-core/lib/crypto.c | 245 +++++++- grub-core/lib/libgcrypt/src/gcrypt-int.h | 51 -- grub-core/lib/libgcrypt_wrap/cipher_wrap.h | 12 +- grub-core/lib/libgcrypt_wrap/md.c | 687 +++++++++++++++++++++ grub-core/lib/libgcrypt_wrap/mem.c | 83 ++- grub-core/lib/xzembed/xz_dec_stream.c | 18 +- grub-core/tests/dsa_sexp_test.c | 107 ++++ grub-core/tests/rsa_sexp_test.c | 81 +++ include/grub/crypto.h | 261 ++++++-- include/grub/gcrypt/gpg-error.h | 9 + util/grub-fstest.c | 2 +- util/import_gcry.py | 122 ++-- util/import_gcrypt_inth.sed | 17 + util/import_gcrypth.sed | 2 - 27 files changed, 1942 insertions(+), 264 deletions(-) create mode 100644 grub-core/lib/b64dec.c create mode 100644 grub-core/lib/libgcrypt_wrap/md.c create mode 100644 grub-core/tests/dsa_sexp_test.c create mode 100644 grub-core/tests/rsa_sexp_test.c create mode 100644 util/import_gcrypt_inth.sed
diff --git a/autogen.sh b/autogen.sh index 195daa541..04779c955 100755 --- a/autogen.sh +++ b/autogen.sh @@ -35,6 +35,7 @@ ${PYTHON} util/import_unicode.py unicode/UnicodeData.txt unicode/BidiMirroring.t echo "Importing libgcrypt..." ${PYTHON} util/import_gcry.py grub-core/lib/libgcrypt/ grub-core sed -n -f util/import_gcrypth.sed < grub-core/lib/libgcrypt/src/gcrypt.h.in > include/grub/gcrypt/gcrypt.h +sed -n -f util/import_gcrypt_inth.sed < grub-core/lib/libgcrypt/src/gcrypt-int.h >> include/grub/gcrypt/gcrypt.h if [ -f include/grub/gcrypt/g10lib.h ]; then rm include/grub/gcrypt/g10lib.h fi diff --git a/conf/Makefile.common b/conf/Makefile.common index b8f216f6c..1fd3fc9da 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -81,8 +81,8 @@ CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-co CFLAGS_POSIX = -fno-builtin CPPFLAGS_POSIX = -I$(top_srcdir)/grub-core/lib/posix_wrap -CFLAGS_GCRY = -Wno-error -Wno-missing-field-initializers -Wno-redundant-decls -Wno-undef $(CFLAGS_POSIX) -CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap $(CPPFLAGS_POSIX) -D_GCRYPT_IN_LIBGCRYPT=1 -I$(top_srcdir)/include/grub/gcrypt +CFLAGS_GCRY = -Wno-error=sign-compare -Wno-error=shift-count-overflow -Wno-missing-field-initializers -Wno-redundant-decls -Wno-undef $(CFLAGS_POSIX) +CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap $(CPPFLAGS_POSIX) -D_GCRYPT_IN_LIBGCRYPT=1 -D_GCRYPT_CONFIG_H_INCLUDED=1 -DHAVE_STRTOUL=1 -I$(top_srcdir)/include/grub/gcrypt CPPFLAGS_EFIEMU = -I$(top_srcdir)/grub-core/efiemu/runtime diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 1571421d7..59270fc9a 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -971,8 +971,8 @@ module = { module = { name = pgp; common = commands/pgp.c; - cflags = '$(CFLAGS_POSIX)'; - cppflags = '-I$(srcdir)/lib/posix_wrap'; + cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare'; + cppflags = '$(CPPFLAGS_GCRY)'; }; module = { @@ -2165,6 +2165,22 @@ module = { common = tests/setjmp_test.c; }; +module = { + name = dsa_sexp_test; + common = tests/dsa_sexp_test.c; + + cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare'; + cppflags = '$(CPPFLAGS_GCRY)'; +}; + +module = { + name = rsa_sexp_test; + common = tests/rsa_sexp_test.c; + + cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare'; + cppflags = '$(CPPFLAGS_GCRY)'; +}; + module = { name = signature_test; common = tests/signature_test.c; @@ -2519,7 +2535,23 @@ module = { common = lib/libgcrypt-grub/mpi/mpicoder.c; common = lib/libgcrypt-grub/mpi/mpih-rshift.c; common = lib/libgcrypt-grub/mpi/mpi-inline.c; + common = lib/libgcrypt-grub/mpi/mpih-const-time.c; + common = lib/libgcrypt-grub/mpi/mpi-scan.c; + common = lib/libgcrypt-grub/src/const-time.c; common = lib/libgcrypt_wrap/mem.c; + common = lib/libgcrypt_wrap/md.c; + + cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare -Wno-unused-but-set-variable'; + cppflags = '$(CPPFLAGS_GCRY)'; +}; + +module = { + name = pubkey; + common = lib/libgcrypt-grub/cipher/pubkey-util.c; + common = lib/libgcrypt-grub/cipher/rsa-common.c; + common = lib/libgcrypt-grub/cipher/dsa-common.c; + common = lib/libgcrypt-grub/src/sexp.c; + common = lib/b64dec.c; cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare'; cppflags = '$(CPPFLAGS_GCRY)'; diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c index d56b5b0bb..b6f8e3d1a 100644 --- a/grub-core/commands/hashsum.c +++ b/grub-core/commands/hashsum.c @@ -73,7 +73,7 @@ hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result) if (!readbuf || !context) goto fail; - hash->init (context); + hash->init (context, 0); while (1) { grub_ssize_t r; diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index e9e9d94ef..052bb110d 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -625,7 +625,7 @@ check_password_md5_real (const char *entered, if (!ctx) return 0; - GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->init (ctx, 0); GRUB_MD_MD5->write (ctx, entered, enteredlen); GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); GRUB_MD_MD5->write (ctx, entered, enteredlen); @@ -633,7 +633,7 @@ check_password_md5_real (const char *entered, GRUB_MD_MD5->final (ctx); grub_memcpy (alt_result, digest, MD5_HASHLEN); - GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->init (ctx, 0); GRUB_MD_MD5->write (ctx, entered, enteredlen); GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */ for (i = enteredlen; i > 16; i -= 16) @@ -649,7 +649,7 @@ check_password_md5_real (const char *entered, { grub_memcpy (alt_result, digest, 16); - GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->init (ctx, 0); if ((i & 1) != 0) GRUB_MD_MD5->write (ctx, entered, enteredlen); else diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c index c6766f044..22eca97ff 100644 --- a/grub-core/commands/pgp.c +++ b/grub-core/commands/pgp.c @@ -136,41 +136,27 @@ struct signature_v4_header grub_uint16_t hashed_sub; } GRUB_PACKED; -const char *hashes[] = { - [0x01] = "md5", - [0x02] = "sha1", - [0x03] = "ripemd160", - [0x08] = "sha256", - [0x09] = "sha384", - [0x0a] = "sha512", - [0x0b] = "sha224" -}; - struct gcry_pk_spec *grub_crypto_pk_dsa; struct gcry_pk_spec *grub_crypto_pk_ecdsa; struct gcry_pk_spec *grub_crypto_pk_rsa; -static int -dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, - const gcry_md_spec_t *hash, struct grub_public_subkey *sk); -static int -rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, - const gcry_md_spec_t *hash, struct grub_public_subkey *sk); - struct { const char *name; + const char *sigsexp; grub_size_t nmpisig; + const char *pubsexp; grub_size_t nmpipub; struct gcry_pk_spec **algo; - int (*pad) (gcry_mpi_t *hmpi, grub_uint8_t *hval, - const gcry_md_spec_t *hash, struct grub_public_subkey *sk); + const char *padding; const char *module; } pkalgos[] = { - [1] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" }, - [3] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" }, - [17] = { "dsa", 2, 4, &grub_crypto_pk_dsa, dsa_pad, "gcry_dsa" }, + [1] = { "rsa", "(sig-val (rsa (s %M)))", 1, "(public-key (dsa (n %M) (e %M)))", 2, &grub_crypto_pk_rsa, "pkcs1", "gcry_rsa" }, + [3] = { "rsa", "(sig-val (rsa (s %M)))", 1, "(public-key (dsa (n %M) (e %M)))", 2, &grub_crypto_pk_rsa, "pkcs1", "gcry_rsa" }, + [17] = { "dsa", "(sig-val (dsa (r %M) (s %M)))", 2, + "(public-key (dsa (p %M) (q %M) (g %M) (y %M)))", + 4, &grub_crypto_pk_dsa, "raw", "gcry_dsa" }, }; struct grub_public_key @@ -196,7 +182,7 @@ free_pk (struct grub_public_key *pk) grub_size_t i; for (i = 0; i < ARRAY_SIZE (sk->mpis); i++) if (sk->mpis[i]) - gcry_mpi_release (sk->mpis[i]); + _gcry_mpi_release (sk->mpis[i]); nsk = sk->next; grub_free (sk); } @@ -303,7 +289,7 @@ grub_load_public_key (grub_file_t f) goto fail; grub_memset (fingerprint_context, 0, GRUB_MD_SHA1->contextsize); - GRUB_MD_SHA1->init (fingerprint_context); + GRUB_MD_SHA1->init (fingerprint_context, 0); GRUB_MD_SHA1->write (fingerprint_context, "\x99", 1); len_be = grub_cpu_to_be16 (len); GRUB_MD_SHA1->write (fingerprint_context, &len_be, sizeof (len_be)); @@ -336,7 +322,7 @@ grub_load_public_key (grub_file_t f) GRUB_MD_SHA1->write (fingerprint_context, buffer, lb + sizeof (grub_uint16_t)); - if (gcry_mpi_scan (&sk->mpis[i], GCRYMPI_FMT_PGP, + if (_gcry_mpi_scan (&sk->mpis[i], GCRYMPI_FMT_PGP, buffer, lb + sizeof (grub_uint16_t), 0)) { grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); @@ -394,51 +380,6 @@ grub_crypto_pk_locate_subkey_in_trustdb (grub_uint64_t keyid) return 0; } - -static int -dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, - const gcry_md_spec_t *hash, struct grub_public_subkey *sk) -{ - unsigned nbits = gcry_mpi_get_nbits (sk->mpis[1]); - grub_dprintf ("crypt", "must be %u bits got %d bits\n", nbits, - (int)(8 * hash->mdlen)); - return gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, hval, - nbits / 8 < (unsigned) hash->mdlen ? nbits / 8 - : (unsigned) hash->mdlen, 0); -} - -static int -rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, - const gcry_md_spec_t *hash, struct grub_public_subkey *sk) -{ - grub_size_t tlen, emlen, fflen; - grub_uint8_t *em, *emptr; - unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]); - int ret; - tlen = hash->mdlen + hash->asnlen; - emlen = (nbits + 7) / 8; - if (emlen < tlen + 11) - return 1; - - em = grub_malloc (emlen); - if (!em) - return 1; - - em[0] = 0x00; - em[1] = 0x01; - fflen = emlen - tlen - 3; - for (emptr = em + 2; emptr < em + 2 + fflen; emptr++) - *emptr = 0xff; - *emptr++ = 0x00; - grub_memcpy (emptr, hash->asnoid, hash->asnlen); - emptr += hash->asnlen; - grub_memcpy (emptr, hval, hash->mdlen); - - ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0); - grub_free (em); - return ret; -} - struct grub_pubkey_context { grub_file_t sig; @@ -483,15 +424,12 @@ grub_verify_signature_init (struct grub_pubkey_context *ctxt, grub_file_t sig) if (t != 0) return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); - if (h >= ARRAY_SIZE (hashes) || hashes[h] == NULL) - return grub_error (GRUB_ERR_BAD_SIGNATURE, "unknown hash"); - if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL) return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); - ctxt->hash = grub_crypto_lookup_md_by_name (hashes[h]); + ctxt->hash = grub_crypto_lookup_md_by_algo (h); if (!ctxt->hash) - return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%s' not loaded", hashes[h]); + return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%d' not loaded", h); grub_dprintf ("crypt", "alive\n"); @@ -499,7 +437,7 @@ grub_verify_signature_init (struct grub_pubkey_context *ctxt, grub_file_t sig) if (!ctxt->hash_context) return grub_errno; - ctxt->hash->init (ctxt->hash_context); + ctxt->hash->init (ctxt->hash_context, 0); ctxt->sig = sig; return GRUB_ERR_NONE; @@ -528,7 +466,6 @@ grub_verify_signature_real (struct grub_pubkey_context *ctxt, grub_uint16_t unhashed_sub; grub_ssize_t r; grub_uint8_t hash_start[2]; - gcry_mpi_t hmpi; grub_uint64_t keyid = 0; struct grub_public_subkey *sk; @@ -620,7 +557,7 @@ grub_verify_signature_real (struct grub_pubkey_context *ctxt, grub_memcpy (readbuf, &l, sizeof (l)); grub_dprintf ("crypt", "alive\n"); - if (gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP, + if (_gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP, readbuf, lb + sizeof (grub_uint16_t), 0)) goto fail; grub_dprintf ("crypt", "alive\n"); @@ -638,8 +575,6 @@ grub_verify_signature_real (struct grub_pubkey_context *ctxt, goto fail; } - if (pkalgos[pk].pad (&hmpi, hval, ctxt->hash, sk)) - goto fail; if (!*pkalgos[pk].algo) { grub_dl_load (pkalgos[pk].module); @@ -652,7 +587,24 @@ grub_verify_signature_real (struct grub_pubkey_context *ctxt, pkalgos[pk].module); goto fail; } - if ((*pkalgos[pk].algo)->verify (0, hmpi, mpis, sk->mpis, 0, 0)) + + gcry_sexp_t hsexp, pubkey, sig; + grub_size_t errof; + + if(_gcry_sexp_build(&hsexp, &errof, "(data (flags %s) (hash %s %b))", pkalgos[pk].padding, ctxt->hash->name, ctxt->hash->mdlen, hval)) + goto fail; + + if(_gcry_sexp_build(&pubkey, &errof, pkalgos[pk].pubsexp, sk->mpis[0], sk->mpis[1], sk->mpis[2], sk->mpis[3])) + goto fail; + + if(_gcry_sexp_build(&sig, &errof, pkalgos[pk].sigsexp, mpis[0], mpis[1])) + goto fail; + + _gcry_sexp_dump(sig); + _gcry_sexp_dump(hsexp); + _gcry_sexp_dump(pubkey); + + if ((*pkalgos[pk].algo)->verify (sig, hsexp, pubkey)) goto fail; grub_free (readbuf); diff --git a/grub-core/commands/xnu_uuid.c b/grub-core/commands/xnu_uuid.c index ae4b3a415..1406c43f5 100644 --- a/grub-core/commands/xnu_uuid.c +++ b/grub-core/commands/xnu_uuid.c @@ -68,7 +68,7 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), ctx = grub_zalloc (GRUB_MD_MD5->contextsize); if (!ctx) return grub_errno; - GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->init (ctx, 0); GRUB_MD_MD5->write (ctx, hash_prefix, sizeof (hash_prefix)); GRUB_MD_MD5->write (ctx, &serial, sizeof (serial)); GRUB_MD_MD5->final (ctx); diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 2246af51b..7ff1c5322 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -296,7 +296,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, return GPG_ERR_OUT_OF_MEMORY; tmp = grub_cpu_to_le64 (sector << log_sector_size); - dev->iv_hash->init (ctx); + dev->iv_hash->init (ctx, 0); dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof (tmp)); dev->iv_hash->final (ctx); diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c index ca9355751..30c863e5b 100644 --- a/grub-core/io/gzio.c +++ b/grub-core/io/gzio.c @@ -1184,7 +1184,7 @@ initialize_tables (grub_gzio_t gzio) gzio->td = NULL; if (gzio->hcontext) - gzio->hdesc->init(gzio->hcontext); + gzio->hdesc->init(gzio->hcontext, 0); } diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index a7d442543..cea942308 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -345,7 +345,7 @@ test_header (grub_file_t file) if (! context) return 0; - hcheck->init(context); + hcheck->init(context, 0); /* MAGIC is not included in check calculation. */ hcheck->write(context, &header.lzop_version, sizeof(header)- LZOP_MAGIC_SIZE); diff --git a/grub-core/lib/adler32.c b/grub-core/lib/adler32.c index 43b68af62..f849ccee6 100644 --- a/grub-core/lib/adler32.c +++ b/grub-core/lib/adler32.c @@ -29,10 +29,12 @@ struct adler32_context }; static void -adler32_init (void *context) +adler32_init (void *context, unsigned int flags) { struct adler32_context *ctx = context; + (void) flags; + ctx->a = 1; ctx->b = 0; } @@ -81,13 +83,22 @@ adler32_read (void *context) static gcry_md_spec_t spec_adler32 = { - "ADLER32", 0, 0, 0, 4, - adler32_init, adler32_write, adler32_final, adler32_read, - sizeof (struct adler32_context), + .algo = GCRY_MD_ADLER32, + .flags = {.disabled = 0, .fips = 0}, + .name = "ADLER32", + .asnoid = NULL, + .asnlen = 0, + .oids = NULL, + .mdlen = 4, + .init = adler32_init, + .write = adler32_write, + .final = adler32_final, + .read = adler32_read, + .contextsize = sizeof (struct adler32_context), + .blocksize = 64, #ifdef GRUB_UTIL .modname = "adler32", #endif - .blocksize = 64 }; diff --git a/grub-core/lib/b64dec.c b/grub-core/lib/b64dec.c new file mode 100644 index 000000000..8aafa9700 --- /dev/null +++ b/grub-core/lib/b64dec.c @@ -0,0 +1,293 @@ +/* b64dec.c - Simple Base64 decoder. + * Copyright (C) 2008, 2011 Free Software Foundation, Inc. + * Copyright (C) 2008, 2011, 2016 g10 Code GmbH + * + * This file is part of Libgpg-error. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This file 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This file was originally a part of GnuPG. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <grub/crypto.h> + +struct _gpgrt_b64state +{ + int idx; + int quad_count; + char *title; + unsigned char radbuf[4]; + unsigned int crc; + gpg_err_code_t lasterr; + unsigned int flags; + unsigned int stop_seen:1; + unsigned int invalid_encoding:1; + unsigned int using_decoder:1; +}; + + +/* The reverse base-64 list used for base-64 decoding. */ +static unsigned char const asctobin[128] = + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff + }; + +enum decoder_states + { + s_init, s_idle, s_lfseen, s_beginseen, s_waitheader, s_waitblank, s_begin, + s_b64_0, s_b64_1, s_b64_2, s_b64_3, + s_waitendtitle, s_waitend + }; + + + +/* Allocate and initialize the context for the base64 decoder. If + TITLE is NULL a plain base64 decoding is done. If it is the empty + string the decoder will skip everything until a "-----BEGIN " line + has been seen, decoding ends at a "----END " line. */ +gpgrt_b64state_t +gpgrt_b64dec_start (const char *title) +{ + gpgrt_b64state_t state; + char *t = NULL; + + if (title) + { + t = grub_strdup (title); + if (!t) + return NULL; + } + + state = grub_calloc (1, sizeof (struct _gpgrt_b64state)); + if (!state) + { + grub_free (t); + return NULL; + } + + if (t) + { + state->title = t; + state->idx = s_init; + } + else + state->idx = s_b64_0; + + state->using_decoder = 1; + + return state; +} + + +/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Stores the + new length of the buffer at R_NBYTES. */ +gpg_err_code_t +gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, size_t length, + size_t *r_nbytes) +{ + enum decoder_states ds = state->idx; + unsigned char val = state->radbuf[0]; + int pos = state->quad_count; + char *d, *s; + + if (state->lasterr) + return state->lasterr; + + if (state->stop_seen) + { + *r_nbytes = 0; + state->lasterr = GPG_ERR_EOF; + grub_free (state->title); + state->title = NULL; + return state->lasterr; + } + + for (s=d=buffer; length && !state->stop_seen; length--, s++) + { + again: + switch (ds) + { + case s_idle: + if (*s == '\n') + { + ds = s_lfseen; + pos = 0; + } + break; + case s_init: + ds = s_lfseen; + /* Fall through */ + case s_lfseen: + if (*s != "-----BEGIN "[pos]) + { + ds = s_idle; + goto again; + } + else if (pos == 10) + { + pos = 0; + ds = s_beginseen; + } + else + pos++; + break; + case s_beginseen: + if (*s != "PGP "[pos]) + ds = s_begin; /* Not a PGP armor. */ + else if (pos == 3) + ds = s_waitheader; + else + pos++; + break; + case s_waitheader: + if (*s == '\n') + ds = s_waitblank; + break; + case s_waitblank: + if (*s == '\n') + ds = s_b64_0; /* blank line found. */ + else if (*s == ' ' || *s == '\r' || *s == '\t') + ; /* Ignore spaces. */ + else + { + /* Armor header line. Note that we don't care that our + * FSM accepts a header prefixed with spaces. */ + ds = s_waitheader; /* Wait for next header. */ + } + break; + case s_begin: + if (*s == '\n') + ds = s_b64_0; + break; + case s_b64_0: + case s_b64_1: + case s_b64_2: + case s_b64_3: + { + int c; + + if (*s == '-' && state->title) + { + /* Not a valid Base64 character: assume end + header. */ + ds = s_waitend; + } + else if (*s == '=') + { + /* Pad character: stop */ + if (ds == s_b64_1) + *d++ = val; + ds = state->title? s_waitendtitle : s_waitend; + } + else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t') + ; /* Skip white spaces. */ + else if ( (*s & 0x80) + || (c = asctobin[*(unsigned char *)s]) == 255) + { + /* Skip invalid encodings. */ + state->invalid_encoding = 1; + } + else if (ds == s_b64_0) + { + val = c << 2; + ds = s_b64_1; + } + else if (ds == s_b64_1) + { + val |= (c>>4)&3; + *d++ = val; + val = (c<<4)&0xf0; + ds = s_b64_2; + } + else if (ds == s_b64_2) + { + val |= (c>>2)&15; + *d++ = val; + val = (c<<6)&0xc0; + ds = s_b64_3; + } + else + { + val |= c&0x3f; + *d++ = val; + ds = s_b64_0; + } + } + break; + case s_waitendtitle: + if (*s == '-') + ds = s_waitend; + break; + case s_waitend: + if ( *s == '\n') + state->stop_seen = 1; + break; + default: + grub_fatal ("invalid state"); + } + } + + + state->idx = ds; + state->radbuf[0] = val; + state->quad_count = pos; + *r_nbytes = (d -(char*) buffer); + return 0; +} + + +/* Return an error code in case an encoding error has been found + during decoding. */ +gpg_err_code_t +gpgrt_b64dec_finish (gpgrt_b64state_t state) +{ + gpg_error_t err; + + if (!state) + return 0; /* Already released. */ + + if (!state->using_decoder) + err = GPG_ERR_CONFLICT; /* State was allocated for the encoder. */ + else if (state->lasterr) + err = state->lasterr; + else + { + grub_free (state->title); + err = state->invalid_encoding? GPG_ERR_BAD_DATA : 0; + } + grub_free (state); + + return err; +} diff --git a/grub-core/lib/crc64.c b/grub-core/lib/crc64.c index 4960f3f89..c231fa97c 100644 --- a/grub-core/lib/crc64.c +++ b/grub-core/lib/crc64.c @@ -61,8 +61,10 @@ init_crc64_table (void) } static void -crc64_init (void *context) +crc64_init (void *context, unsigned int flags) { + (void) flags; + if (! crc64_table[1]) init_crc64_table (); *(grub_uint64_t *) context = 0; @@ -97,10 +99,22 @@ crc64_final (void *context __attribute__ ((unused))) gcry_md_spec_t _gcry_digest_spec_crc64 = { - "CRC64", 0, 0, 0, 8, - crc64_init, crc64_write, crc64_final, crc64_read, - sizeof (grub_uint64_t), - .blocksize = 64 + .algo = GCRY_MD_CRC64, + .flags = {.disabled = 0, .fips = 0}, + .name = "CRC64", + .asnoid = NULL, + .asnlen = 0, + .oids = NULL, + .mdlen = 8, + .init = crc64_init, + .write = crc64_write, + .final = crc64_final, + .read = crc64_read, + .contextsize = sizeof (grub_uint64_t), + .blocksize = 64, +#ifdef GRUB_UTIL + .modname = "crc64", +#endif }; GRUB_MOD_INIT(crc64) diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index 396f76410..dd60dd4ac 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -37,6 +37,8 @@ struct grub_crypto_hmac_handle static gcry_cipher_spec_t *grub_ciphers = NULL; static gcry_md_spec_t *grub_digests = NULL; +int _gcry_no_fips_mode_required = 1; + void (*grub_crypto_autoload_hook) (const char *name) = NULL; /* Based on libgcrypt-1.4.4/src/misc.c. */ @@ -56,6 +58,17 @@ _gcry_burn_stack (int size) grub_burn_stack (size); } +void +__gcry_burn_stack (unsigned int size) +{ + grub_burn_stack (size); +} + +void +__gcry_burn_stack_dummy (void) +{ +} + void __attribute__ ((noreturn)) _gcry_assert_failed (const char *expr, const char *file, int line, const char *func) @@ -64,6 +77,12 @@ _gcry_assert_failed (const char *expr, const char *file, int line, grub_fatal ("assertion %s at %s:%d (%s) failed\n", expr, file, line, func); } +void +_gcry_bug( const char *file, int line, const char *func ) +{ + grub_fatal ("... this is a bug (%s:%d:%s)\n", file, line, func); +} + void _gcry_log_error (const char *fmt, ...) { @@ -83,6 +102,36 @@ void _gcry_log_error (const char *fmt, ...) } } +void _gcry_log_info (const char *fmt, ...) +{ + va_list args; + const char *debug = grub_env_get ("debug"); + + if (! debug) + return; + + if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt")) + { + grub_printf ("gcrypt info: "); + va_start (args, fmt); + grub_vprintf (fmt, args); + va_end (args); + grub_refresh (); + } +} + +void +_gcry_fast_wipememory2 (void *ptr, int set, grub_size_t len) +{ + grub_memset(ptr, set, len); +} + +void +_gcry_fast_wipememory (void *ptr, grub_size_t len) +{ + grub_memset(ptr, 0, len); +} + void grub_cipher_register (gcry_cipher_spec_t *cipher) { @@ -129,7 +178,7 @@ grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in, if (hash->contextsize > sizeof (ctx)) grub_fatal ("Too large md context"); - hash->init (&ctx); + hash->init (&ctx, 0); hash->write (&ctx, in, inlen); hash->final (&ctx); grub_memcpy (out, hash->read (&ctx), hash->mdlen); @@ -153,6 +202,91 @@ grub_crypto_lookup_md_by_name (const char *name) } } +const gcry_md_spec_t * +grub_crypto_lookup_md_by_oid (const char *oid) +{ + const gcry_md_spec_t *md; + + if (!oid) + return NULL; + + if (grub_strncmp (oid, "oid.", 4) == 0 || grub_strncmp (oid, "OID.", 4) == 0) + oid += 4; + + + for (md = grub_digests; md; md = md->next) + { + const gcry_md_oid_spec_t *oid_specs = md->oids; + if (oid_specs) + { + for (int j = 0; oid_specs[j].oidstring; j++) + if (grub_strcasecmp (oid, oid_specs[j].oidstring) == 0) + return md; + } + } + + return NULL; +} + +static const char *md_algos[] = { + [1] = "MD5", + [2] = "SHA1", + [3] = "RIPEMD160", + [6] = "TIGER", + [8] = "SHA256", + [9] = "SHA384", + [10] = "SHA512", + [11] = "SHA224", + + [301] = "MD4", + [302] = "CRC32", + [303] = "CRC32RFC1510", + [304] = "CRC24RFC2440", + [305] = "WHIRLPOOL", + [306] = "TIGER1", + [307] = "TIGER2", + [308] = "GOSTR3411_94", + [309] = "STRIBOG256", + [310] = "STRIBOG512", + [311] = "GOSTR3411_CP", + [312] = "SHA3-224", + [313] = "SHA3-256", + [314] = "SHA3-384", + [315] = "SHA3-512", + [316] = "SHAKE128", + [317] = "SHAKE256", + [318] = "BLAKE2B_512", + [319] = "BLAKE2B_384", + [320] = "BLAKE2B_256", + [321] = "BLAKE2B_160", + [322] = "BLAKE2S_256", + [323] = "BLAKE2S_224", + [324] = "BLAKE2S_160", + [325] = "BLAKE2S_128", + [326] = "SM3", + [327] = "SHA512_256", + [328] = "SHA512_224", +}; + + +const gcry_md_spec_t * +grub_crypto_lookup_md_by_algo (int algo) +{ + const gcry_md_spec_t *md; + int first = 1; + while (1) + { + for (md = grub_digests; md; md = md->next) + if (algo == md->algo) + return md; + if (grub_crypto_autoload_hook && first && algo > 0 && algo < (int)ARRAY_SIZE(md_algos) && md_algos[algo]) { + grub_crypto_autoload_hook (md_algos[algo]); + } else + return NULL; + first = 0; + } +} + const gcry_cipher_spec_t * grub_crypto_lookup_cipher_by_name (const char *name) { @@ -196,7 +330,9 @@ 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); + /* TODO: Fix this. It's ugly as hell. */ + void *bulk_ops[100]; + return cipher->cipher->setkey (cipher->ctx, key, keylen, (void *) bulk_ops); } gcry_err_code_t @@ -343,7 +479,7 @@ grub_crypto_hmac_init (const struct gcry_md_spec *md, grub_free (helpkey); helpkey = NULL; - md->init (ctx); + md->init (ctx, 0); md->write (ctx, ipad, md->blocksize); /* inner pad */ grub_memset (ipad, 0, md->blocksize); @@ -390,7 +526,7 @@ grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out) hnd->md->read (hnd->ctx); p = hnd->md->read (hnd->ctx); - hnd->md->init (ctx2); + hnd->md->init (ctx2, 0); hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize); hnd->md->write (ctx2, p, hnd->md->mdlen); hnd->md->final (ctx2); @@ -433,19 +569,106 @@ grub_crypto_gcry_error (gcry_err_code_t in) return GRUB_ACCESS_DENIED; } + +/* + * Compare byte arrays of length LEN, return 1 if it's not same, + * 0, otherwise. + */ int -grub_crypto_memcmp (const void *a, const void *b, grub_size_t n) +grub_crypto_memcmp (const void *b1, const void *b2, grub_size_t len) { - register grub_size_t counter = 0; - const grub_uint8_t *pa, *pb; + const grub_uint8_t *a = b1; + const grub_uint8_t *b = b2; + int ab, ba; + grub_size_t i; - for (pa = a, pb = b; n; pa++, pb++, n--) + /* Constant-time compare. */ + for (i = 0, ab = 0, ba = 0; i < len; i++) { - if (*pa != *pb) - counter++; + /* If a[i] != b[i], either ab or ba will be negative. */ + ab |= a[i] - b[i]; + ba |= b[i] - a[i]; } - return !!counter; + /* 'ab | ba' is negative when buffers are not equal, extract sign bit. */ + return ((unsigned int)(ab | ba) >> (sizeof(unsigned int) * 8 - 1)) & 1; +} + + +void * +_gcry_malloc_secure (grub_size_t n) +{ + return grub_malloc(n); +} + +void * +_gcry_malloc (grub_size_t n) +{ + return grub_malloc(n); +} + +void * +_gcry_xmalloc(grub_size_t n) +{ + void *ret = grub_malloc(n); + if (ret == NULL) + grub_fatal("_gcry_xmalloc failed"); + return ret; +} + +void * +_gcry_xmalloc_secure(grub_size_t n) +{ + void *ret = grub_malloc(n); + if (ret == NULL) + grub_fatal("_gcry_xmalloc_secure failed"); + return ret; +} + +void _gcry_free (void *p) +{ + grub_free (p); +} + +void * +_gcry_xrealloc (void *a, grub_size_t n) +{ + void *ret = grub_realloc(a, n); + if (ret == NULL) + grub_fatal("_gcry_xrealloc failed"); + return ret; +} + +void * +_gcry_xcalloc (grub_size_t n, grub_size_t m) +{ + void *ret = grub_calloc(n, m); + if (ret == NULL) + grub_fatal("_gcry_xcalloc failed"); + return ret; +} + +void * +_gcry_xcalloc_secure (grub_size_t n, grub_size_t m) +{ + void *ret = grub_calloc(n, m); + if (ret == NULL) + grub_fatal("_gcry_xcalloc_secure failed"); + return ret; +} + + +int +_gcry_is_secure (const void *a) +{ + (void) a; + + return 0; +} + +void _gcry_divide_by_zero (void) +{ + grub_fatal("gcrypt division by zero"); } #ifndef GRUB_UTIL diff --git a/grub-core/lib/libgcrypt/src/gcrypt-int.h b/grub-core/lib/libgcrypt/src/gcrypt-int.h index 3071b421e..1ca4f21fe 100644 --- a/grub-core/lib/libgcrypt/src/gcrypt-int.h +++ b/grub-core/lib/libgcrypt/src/gcrypt-int.h @@ -265,57 +265,6 @@ void _gcry_set_log_handler (gcry_handler_log_t f, void *opaque); void _gcry_set_gettext_handler (const char *(*f)(const char*)); void _gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data); - -/* Return a pointer to a string containing a description of the error - code in the error value ERR. */ -static inline const char * -_gcry_strerror (gcry_error_t err) -{ - return gpg_strerror (err); -} - -/* Return a pointer to a string containing a description of the error - source in the error value ERR. */ -static inline const char * -_gcry_strsource (gcry_error_t err) -{ - return gpg_strsource (err); -} - -/* Retrieve the error code for the system error ERR. This returns - GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report - this). */ -static inline gcry_err_code_t -_gcry_err_code_from_errno (int err) -{ - return gpg_err_code_from_errno (err); -} - -/* Retrieve the system error for the error code CODE. This returns 0 - if CODE is not a system error code. */ -static inline int -_gcry_err_code_to_errno (gcry_err_code_t code) -{ - return gpg_err_code_to_errno (code); -} - -/* Return an error value with the error source SOURCE and the system - error ERR. */ -static inline gcry_error_t -_gcry_err_make_from_errno (gpg_err_source_t source, int err) -{ - return gpg_err_make_from_errno (source, err); -} - - -/* Return an error value with the system error ERR. */ -static inline gcry_error_t -_gcry_error_from_errno (int err) -{ - return gpg_error (gpg_err_code_from_errno (err)); -} - - gpg_err_code_t _gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length, diff --git a/grub-core/lib/libgcrypt_wrap/cipher_wrap.h b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h index 42835493d..225eb7919 100644 --- a/grub-core/lib/libgcrypt_wrap/cipher_wrap.h +++ b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h @@ -35,9 +35,7 @@ #undef __GNU_LIBRARY__ #define __GNU_LIBRARY__ 1 -#define U64_C(c) (c ## ULL) - -#define PUBKEY_FLAG_NO_BLINDING (1 << 0) +#define UINT64_C(c) (c ## ULL) #define CIPHER_INFO_NO_WEAK_KEY 1 @@ -74,4 +72,12 @@ _gcry_fips_mode (void) #define gcry_mpi_mod _gcry_mpi_mod +#define strtol grub_strtol +#define strtoul grub_strtoul +#define atoi(nptr) (strtol((nptr), NULL, 10)) + +#define stpcpy grub_stpcpy + +#define spec_from_algo grub_crypto_lookup_md_by_algo + #endif diff --git a/grub-core/lib/libgcrypt_wrap/md.c b/grub-core/lib/libgcrypt_wrap/md.c new file mode 100644 index 000000000..c24c74672 --- /dev/null +++ b/grub-core/lib/libgcrypt_wrap/md.c @@ -0,0 +1,687 @@ +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "g10lib.h" + +typedef struct gcry_md_list +{ + const gcry_md_spec_t *spec; + struct gcry_md_list *next; + size_t actual_struct_size; /* Allocated size of this structure. */ + PROPERLY_ALIGNED_TYPE context[1]; +} GcryDigestEntry; + +/* This structure is put right after the gcry_md_hd_t buffer, so that + * only one memory block is needed. */ +struct gcry_md_context +{ + int magic; + struct { + unsigned int secure:1; + unsigned int finalized:1; + unsigned int bugemu1:1; + unsigned int hmac:1; + } flags; + size_t actual_handle_size; /* Allocated size of this handle. */ + GcryDigestEntry *list; +}; + +#define CTX_MAGIC_NORMAL 0x11071961 +#define CTX_MAGIC_SECURE 0x16917011 + +static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo); +static void md_close (gcry_md_hd_t a); +static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen); +static byte *md_read( gcry_md_hd_t a, int algo ); +///static int md_get_algo( gcry_md_hd_t a ); +static int md_digest_length( int algo ); + +int +_gcry_md_map_name (const char *string) +{ + const gcry_md_spec_t *spec; + + if (!string) + return 0; + + /* If the string starts with a digit (optionally prefixed with + either "OID." or "oid."), we first look into our table of ASN.1 + object identifiers to figure out the algorithm */ + spec = grub_crypto_lookup_md_by_oid (string); + if (spec) + return spec->algo; + + /* Not found, search a matching digest name. */ + spec = grub_crypto_lookup_md_by_name (string); + if (spec) + return spec->algo; + + return 0; +} + +static gcry_err_code_t +check_digest_algo (int algorithm) +{ + const gcry_md_spec_t *spec; + + spec = spec_from_algo (algorithm); + if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ())) + return 0; + + return GPG_ERR_DIGEST_ALGO; + +} + +/**************** + * Open a message digest handle for use with algorithm ALGO. + * More algorithms may be added by md_enable(). The initial algorithm + * may be 0. + */ +static gcry_err_code_t +md_open (gcry_md_hd_t *h, int algo, unsigned int flags) +{ + gcry_err_code_t err = 0; + int secure = !!(flags & GCRY_MD_FLAG_SECURE); + int hmac = !!(flags & GCRY_MD_FLAG_HMAC); + int bufsize = secure ? 512 : 1024; + gcry_md_hd_t hd; + size_t n; + + /* Allocate a memory area to hold the caller visible buffer with it's + * control information and the data required by this module. Set the + * context pointer at the beginning to this area. + * We have to use this strange scheme because we want to hide the + * internal data but have a variable sized buffer. + * + * +---+------+---........------+-------------+ + * !ctx! bctl ! buffer ! private ! + * +---+------+---........------+-------------+ + * ! ^ + * !---------------------------! + * + * We have to make sure that private is well aligned. + */ + n = offsetof (struct gcry_md_handle, buf) + bufsize; + n = ((n + sizeof (PROPERLY_ALIGNED_TYPE) - 1) + / sizeof (PROPERLY_ALIGNED_TYPE)) * sizeof (PROPERLY_ALIGNED_TYPE); + + /* Allocate and set the Context pointer to the private data */ + if (secure) + hd = xtrymalloc_secure (n + sizeof (struct gcry_md_context)); + else + hd = xtrymalloc (n + sizeof (struct gcry_md_context)); + + if (! hd) + err = gpg_err_code_from_errno (errno); + + if (! err) + { + struct gcry_md_context *ctx; + + ctx = (void *) (hd->buf - offsetof (struct gcry_md_handle, buf) + n); + /* Setup the globally visible data (bctl in the diagram).*/ + hd->ctx = ctx; + hd->bufsize = n - offsetof (struct gcry_md_handle, buf); + hd->bufpos = 0; + + /* Initialize the private data. */ + wipememory2 (ctx, 0, sizeof *ctx); + ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; + ctx->actual_handle_size = n + sizeof (struct gcry_md_context); + ctx->flags.secure = secure; + ctx->flags.hmac = hmac; + ctx->flags.bugemu1 = !!(flags & GCRY_MD_FLAG_BUGEMU1); + } + + if (! err) + { + if (algo) + { + err = md_enable (hd, algo); + if (err) + md_close (hd); + } + } + + if (! err) + *h = hd; + + return err; +} + +/* Create a message digest object for algorithm ALGO. FLAGS may be + given as an bitwise OR of the gcry_md_flags values. ALGO may be + given as 0 if the algorithms to be used are later set using + gcry_md_enable. H is guaranteed to be a valid handle or NULL on + error. */ +gcry_err_code_t +_gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags) +{ + gcry_err_code_t rc; + gcry_md_hd_t hd; + + if ((flags & ~(GCRY_MD_FLAG_SECURE + | GCRY_MD_FLAG_HMAC + | GCRY_MD_FLAG_BUGEMU1))) + rc = GPG_ERR_INV_ARG; + else + rc = md_open (&hd, algo, flags); + + *h = rc? NULL : hd; + return rc; +} + +static gcry_err_code_t +md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd) +{ + gcry_err_code_t err = 0; + struct gcry_md_context *a = ahd->ctx; + struct gcry_md_context *b; + GcryDigestEntry *ar, *br; + gcry_md_hd_t bhd; + size_t n; + + if (ahd->bufpos) + md_write (ahd, NULL, 0); + + n = (char *) ahd->ctx - (char *) ahd; + if (a->flags.secure) + bhd = xtrymalloc_secure (n + sizeof (struct gcry_md_context)); + else + bhd = xtrymalloc (n + sizeof (struct gcry_md_context)); + + if (!bhd) + { + err = gpg_err_code_from_syserror (); + goto leave; + } + + bhd->ctx = b = (void *) ((char *) bhd + n); + /* No need to copy the buffer due to the write above. */ + gcry_assert (ahd->bufsize == (n - offsetof (struct gcry_md_handle, buf))); + bhd->bufsize = ahd->bufsize; + bhd->bufpos = 0; + gcry_assert (! ahd->bufpos); + memcpy (b, a, sizeof *a); + b->list = NULL; + + /* Copy the complete list of algorithms. The copied list is + reversed, but that doesn't matter. */ + for (ar = a->list; ar; ar = ar->next) + { + if (a->flags.secure) + br = xtrymalloc_secure (ar->actual_struct_size); + else + br = xtrymalloc (ar->actual_struct_size); + if (!br) + { + err = gpg_err_code_from_syserror (); + md_close (bhd); + goto leave; + } + + memcpy (br, ar, ar->actual_struct_size); + br->next = b->list; + b->list = br; + } + + *b_hd = bhd; + + leave: + return err; +} + +gcry_err_code_t +_gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd) +{ + gcry_err_code_t rc; + + rc = md_copy (hd, handle); + if (rc) + *handle = NULL; + return rc; +} + + +/* + * Reset all contexts and discard any buffered stuff. This may be used + * instead of a md_close(); md_open(). + */ +void +_gcry_md_reset (gcry_md_hd_t a) +{ + GcryDigestEntry *r; + + /* Note: We allow this even in fips non operational mode. */ + + a->bufpos = a->ctx->flags.finalized = 0; + + if (a->ctx->flags.hmac) + for (r = a->ctx->list; r; r = r->next) + { + memcpy (r->context, (char *)r->context + r->spec->contextsize, + r->spec->contextsize); + } + else + for (r = a->ctx->list; r; r = r->next) + { + memset (r->context, 0, r->spec->contextsize); + (*r->spec->init) (r->context, + a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0); + } +} + +static void +md_close (gcry_md_hd_t a) +{ + GcryDigestEntry *r, *r2; + + if (! a) + return; + for (r = a->ctx->list; r; r = r2) + { + r2 = r->next; + wipememory (r, r->actual_struct_size); + xfree (r); + } + + wipememory (a, a->ctx->actual_handle_size); + xfree(a); +} + + +void +_gcry_md_close (gcry_md_hd_t hd) +{ + /* Note: We allow this even in fips non operational mode. */ + md_close (hd); +} + +static void +md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen) +{ + GcryDigestEntry *r; + + for (r = a->ctx->list; r; r = r->next) + { + if (a->bufpos) + (*r->spec->write) (r->context, a->buf, a->bufpos); + (*r->spec->write) (r->context, inbuf, inlen); + } + a->bufpos = 0; +} + + +/* Note that this function may be used after finalize and read to keep + on writing to the transform function so to mitigate timing + attacks. */ +void +_gcry_md_write (gcry_md_hd_t hd, const void *inbuf, size_t inlen) +{ + md_write (hd, inbuf, inlen); +} + +static void +md_final (gcry_md_hd_t a) +{ + GcryDigestEntry *r; + + if (a->ctx->flags.finalized) + return; + + if (a->bufpos) + md_write (a, NULL, 0); + + for (r = a->ctx->list; r; r = r->next) + (*r->spec->final) (r->context); + + a->ctx->flags.finalized = 1; + + if (!a->ctx->flags.hmac) + return; + + for (r = a->ctx->list; r; r = r->next) + { + byte *p; + size_t dlen = r->spec->mdlen; + byte *hash; + gcry_err_code_t err; + + if (r->spec->read == NULL) + continue; + + p = r->spec->read (r->context); + + if (a->ctx->flags.secure) + hash = xtrymalloc_secure (dlen); + else + hash = xtrymalloc (dlen); + if (!hash) + { + err = gpg_err_code_from_errno (errno); + _gcry_fatal_error (err, NULL); + } + + memcpy (hash, p, dlen); + memcpy (r->context, (char *)r->context + r->spec->contextsize * 2, + r->spec->contextsize); + (*r->spec->write) (r->context, hash, dlen); + (*r->spec->final) (r->context); + xfree (hash); + } +} + +static gcry_err_code_t +md_enable (gcry_md_hd_t hd, int algorithm) +{ + struct gcry_md_context *h = hd->ctx; + const gcry_md_spec_t *spec; + GcryDigestEntry *entry; + gcry_err_code_t err = 0; + + for (entry = h->list; entry; entry = entry->next) + if (entry->spec->algo == algorithm) + return 0; /* Already enabled */ + + spec = spec_from_algo (algorithm); + if (!spec) + { + log_debug ("md_enable: algorithm %d not available\n", algorithm); + err = GPG_ERR_DIGEST_ALGO; + } + + if (!err && spec->flags.disabled) + err = GPG_ERR_DIGEST_ALGO; + + /* Any non-FIPS algorithm should go this way */ + if (!err && !spec->flags.fips && fips_mode ()) + err = GPG_ERR_DIGEST_ALGO; + + if (!err && h->flags.hmac && spec->read == NULL) + { + /* Expandable output function cannot act as part of HMAC. */ + err = GPG_ERR_DIGEST_ALGO; + } + + if (!err) + { + size_t size = (sizeof (*entry) + + spec->contextsize * (h->flags.hmac? 3 : 1) + - sizeof (entry->context)); + + /* And allocate a new list entry. */ + if (h->flags.secure) + entry = xtrymalloc_secure (size); + else + entry = xtrymalloc (size); + + if (! entry) + err = gpg_err_code_from_errno (errno); + else + { + entry->spec = spec; + entry->next = h->list; + entry->actual_struct_size = size; + h->list = entry; + + /* And init this instance. */ + entry->spec->init (entry->context, + h->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0); + } + } + + return err; +} + + +gcry_err_code_t +_gcry_md_enable (gcry_md_hd_t hd, int algorithm) +{ + return md_enable (hd, algorithm); +} + +gcry_err_code_t +_gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen) +{ + gcry_err_code_t rc = 0; + + (void)buflen; /* Currently not used. */ + (void)buffer; + + switch (cmd) + { + case GCRYCTL_FINALIZE: + md_final (hd); + break; + case GCRYCTL_START_DUMP: + break; + case GCRYCTL_STOP_DUMP: + break; + default: + rc = GPG_ERR_INV_OP; + } + return rc; +} + +/**************** + * If ALGO is null get the digest for the used algo (which should be + * only one) + */ +static byte * +md_read( gcry_md_hd_t a, int algo ) +{ + GcryDigestEntry *r = a->ctx->list; + + if (! algo) + { + /* Return the first algorithm */ + if (r) + { + if (r->next) + log_debug ("more than one algorithm in md_read(0)\n"); + if (r->spec->read) + return r->spec->read (r->context); + } + } + else + { + for (r = a->ctx->list; r; r = r->next) + if (r->spec->algo == algo) + { + if (r->spec->read) + return r->spec->read (r->context); + break; + } + } + + if (r && !r->spec->read) + _gcry_fatal_error (GPG_ERR_DIGEST_ALGO, + "requested algo has no fixed digest length"); + else + _gcry_fatal_error (GPG_ERR_DIGEST_ALGO, "requested algo not in md context"); + return NULL; +} + + +/* + * Read out the complete digest, this function implictly finalizes + * the hash. + */ +byte * +_gcry_md_read (gcry_md_hd_t hd, int algo) +{ + /* This function is expected to always return a digest, thus we + can't return an error which we actually should do in + non-operational state. */ + _gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0); + return md_read (hd, algo); +} + +/* + * Shortcut function to hash a buffer with a given algo. The only + * guaranteed supported algorithms are RIPE-MD160 and SHA-1. The + * supplied digest buffer must be large enough to store the resulting + * hash. No error is returned, the function will abort on an invalid + * algo. DISABLED_ALGOS are ignored here. */ +void +_gcry_md_hash_buffer (int algo, void *digest, + const void *buffer, size_t length) +{ + const gcry_md_spec_t *spec; + + spec = spec_from_algo (algo); + if (!spec) + { + log_debug ("md_hash_buffer: algorithm %d not available\n", algo); + return; + } + + /* if (spec->hash_buffers != NULL) + { + gcry_buffer_t iov; + + iov.size = 0; + iov.data = (void *)buffer; + iov.off = 0; + iov.len = length; + + if (spec->flags.disabled || (!spec->flags.fips && fips_mode ())) + log_bug ("gcry_md_hash_buffer failed for algo %d: %s", + algo, gpg_strerror (gcry_error (GPG_ERR_DIGEST_ALGO))); + + spec->hash_buffers (digest, spec->mdlen, &iov, 1); + } + else*/ + { + /* For the others we do not have a fast function, so we use the + normal functions. */ + gcry_md_hd_t h; + gpg_err_code_t err; + + err = md_open (&h, algo, 0); + if (err) + log_bug ("gcry_md_open failed for algo %d: %s", + algo, gpg_strerror (gcry_error(err))); + md_write (h, (byte *) buffer, length); + md_final (h); + memcpy (digest, md_read (h, algo), md_digest_length (algo)); + md_close (h); + } +} + +/**************** + * Return the length of the digest + */ +static int +md_digest_length (int algorithm) +{ + const gcry_md_spec_t *spec; + + spec = spec_from_algo (algorithm); + return spec? spec->mdlen : 0; +} + + +/**************** + * Return the length of the digest in bytes. + * This function will return 0 in case of errors. + */ +unsigned int +_gcry_md_get_algo_dlen (int algorithm) +{ + return md_digest_length (algorithm); +} + +/* Hmmm: add a mode to enumerate the OIDs + * to make g10/sig-check.c more portable */ +static const byte * +md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen) +{ + const gcry_md_spec_t *spec; + const byte *asnoid = NULL; + + spec = spec_from_algo (algorithm); + if (spec) + { + if (asnlen) + *asnlen = spec->asnlen; + if (mdlen) + *mdlen = spec->mdlen; + asnoid = spec->asnoid; + } + else + log_bug ("no ASN.1 OID for md algo %d\n", algorithm); + + return asnoid; +} + + +/**************** + * Return information about the given cipher algorithm + * WHAT select the kind of information returned: + * GCRYCTL_TEST_ALGO: + * Returns 0 when the specified algorithm is available for use. + * buffer and nbytes must be zero. + * GCRYCTL_GET_ASNOID: + * Return the ASNOID of the algorithm in buffer. if buffer is NULL, only + * the required length is returned. + * GCRYCTL_SELFTEST + * Helper for the regression tests - shall not be used by applications. + * + * Note: Because this function is in most cases used to return an + * integer value, we can make it easier for the caller to just look at + * the return value. The caller will in all cases consult the value + * and thereby detecting whether a error occurred or not (i.e. while checking + * the block size) + */ +gcry_err_code_t +_gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes) +{ + gcry_err_code_t rc; + + switch (what) + { + case GCRYCTL_TEST_ALGO: + if (buffer || nbytes) + rc = GPG_ERR_INV_ARG; + else + rc = check_digest_algo (algo); + break; + + case GCRYCTL_GET_ASNOID: + /* We need to check that the algo is available because + md_asn_oid would otherwise raise an assertion. */ + rc = check_digest_algo (algo); + if (!rc) + { + const char unsigned *asn; + size_t asnlen; + + asn = md_asn_oid (algo, &asnlen, NULL); + if (buffer && (*nbytes >= asnlen)) + { + memcpy (buffer, asn, asnlen); + *nbytes = asnlen; + } + else if (!buffer && nbytes) + *nbytes = asnlen; + else + { + if (buffer) + rc = GPG_ERR_TOO_SHORT; + else + rc = GPG_ERR_INV_ARG; + } + } + break; + + default: + rc = GPG_ERR_INV_OP; + break; + } + + return rc; +} diff --git a/grub-core/lib/libgcrypt_wrap/mem.c b/grub-core/lib/libgcrypt_wrap/mem.c index 74c6eafe5..ab0cf4ad3 100644 --- a/grub-core/lib/libgcrypt_wrap/mem.c +++ b/grub-core/lib/libgcrypt_wrap/mem.c @@ -46,6 +46,15 @@ gcry_xcalloc (size_t n, size_t m) return ret; } +void * +_gcry_calloc (size_t n, size_t m) +{ + size_t sz; + if (grub_mul (n, m, &sz)) + return NULL; + return grub_zalloc (sz); +} + void * gcry_xmalloc_secure (size_t n) { @@ -69,6 +78,15 @@ gcry_xcalloc_secure (size_t n, size_t m) return ret; } +void * +_gcry_calloc_secure (size_t n, size_t m) +{ + size_t sz; + if (grub_mul (n, m, &sz)) + return NULL; + return grub_zalloc (sz); +} + void * gcry_xmalloc (size_t n) { @@ -89,6 +107,12 @@ gcry_xrealloc (void *a, size_t n) return ret; } +void * +_gcry_realloc (void *a, size_t n) +{ + return grub_realloc (a, n); +} + void _gcry_check_heap (const void *a __attribute__ ((unused))) { @@ -113,6 +137,24 @@ void _gcry_log_printf (const char *fmt, ...) } } +void _gcry_log_debug (const char *fmt, ...) +{ + va_list args; + const char *debug = grub_env_get ("debug"); + + if (! debug) + return; + + if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt")) + { + grub_printf ("gcrypt: "); + va_start (args, fmt); + grub_vprintf (fmt, args); + va_end (args); + grub_refresh (); + } +} + void _gcry_log_bug (const char *fmt, ...) { va_list args; @@ -126,9 +168,9 @@ void _gcry_log_bug (const char *fmt, ...) } gcry_err_code_t -gpg_error_from_syserror (void) +gpg_err_code_from_errno (int err) { - switch (grub_errno) + switch (err) { case GRUB_ERR_NONE: return GPG_ERR_NO_ERROR; @@ -138,3 +180,40 @@ gpg_error_from_syserror (void) return GPG_ERR_GENERAL; } } + +gcry_err_code_t +gpg_error_from_syserror (void) +{ + return gpg_err_code_from_errno(grub_errno); +} + +gcry_err_code_t +gpg_err_code_from_syserror (void) +{ + return gpg_error_from_syserror (); +} + +void _gcry_fatal_error(int rc, const char *text ) +{ + grub_fatal("gcry fatal %d: %s", rc, text); +} + + +void _gcry_randomize (void *buffer __attribute__((unused)), size_t length __attribute__((unused)), + enum gcry_random_level level __attribute__((unused))) +{ + grub_fatal("Attempt to get secure random numbers"); +} + + +void *_gcry_random_bytes_secure (size_t nbytes __attribute__((unused)), enum gcry_random_level level __attribute__((unused))) +{ + grub_fatal("Attempt to get secure random numbers"); +} + +const char *gpg_strerror (gpg_error_t err) +{ + static char buf[256]; + grub_snprintf(buf, sizeof(buf) - 5, "gpg error %d\n", err); + return buf; +} diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c index 832d8af9a..f2dd42dc2 100644 --- a/grub-core/lib/xzembed/xz_dec_stream.c +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -425,9 +425,9 @@ static enum xz_ret hash_validate(struct xz_dec *s, struct xz_buf *b, #ifndef GRUB_EMBED_DECOMPRESSOR if (s->hash) - s->hash->init(s->hash_context); + s->hash->init(s->hash_context, 0); if (s->crc32) - s->crc32->init(s->crc32_context); + s->crc32->init(s->crc32_context, 0); #endif s->have_hash_value = 0; s->pos = 0; @@ -493,7 +493,7 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) s->crc32_context = kmalloc(s->crc32->contextsize, GFP_KERNEL); if (s->crc32_context == NULL) return XZ_MEMLIMIT_ERROR; - s->crc32->init(s->crc32_context); + s->crc32->init(s->crc32_context, 0); } #endif @@ -531,9 +531,9 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) return XZ_MEMLIMIT_ERROR; } - s->hash->init(s->hash_context); - s->hash->init(s->index.hash.hash_context); - s->hash->init(s->block.hash.hash_context); + s->hash->init(s->hash_context, 0); + s->hash->init(s->index.hash.hash_context, 0); + s->hash->init(s->block.hash.hash_context, 0); } #endif } @@ -1014,9 +1014,9 @@ void xz_dec_reset(struct xz_dec *s) #ifndef GRUB_EMBED_DECOMPRESSOR if (s->hash) { - s->hash->init(s->hash_context); - s->hash->init(s->index.hash.hash_context); - s->hash->init(s->block.hash.hash_context); + s->hash->init(s->hash_context, 0); + s->hash->init(s->index.hash.hash_context, 0); + s->hash->init(s->block.hash.hash_context, 0); } #endif s->have_hash_value = 0; diff --git a/grub-core/tests/dsa_sexp_test.c b/grub-core/tests/dsa_sexp_test.c new file mode 100644 index 000000000..ea233bf0c --- /dev/null +++ b/grub-core/tests/dsa_sexp_test.c @@ -0,0 +1,107 @@ +#include <grub/test.h> +#include <grub/crypto.h> +#include <grub/gcrypt/gcrypt.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +static char pubkey_dump[] = { + 0x28, 0x31, 0x30, 0x3a, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x28, 0x33, + 0x3a, 0x64, 0x73, 0x61, 0x28, 0x31, 0x3a, 0x70, + 0x31, 0x32, 0x39, 0x3a, 0x00, 0xc0, 0x50, 0x14, + 0x4c, 0x97, 0x10, 0x69, 0x07, 0xa7, 0xe9, 0x2b, + 0xe5, 0xc6, 0x88, 0xe1, 0x6d, 0xd8, 0x38, 0x28, + 0x09, 0x49, 0x5b, 0xe8, 0xa3, 0x04, 0xb8, 0xc4, + 0x6e, 0x98, 0xc1, 0xc2, 0xb0, 0x2a, 0xe0, 0xe2, + 0x1a, 0x30, 0xd2, 0xdb, 0x45, 0x1a, 0x88, 0x80, + 0x28, 0x24, 0xb0, 0xbf, 0xc2, 0xbd, 0xe9, 0xf6, + 0x9d, 0xa2, 0x01, 0x94, 0xe6, 0x7f, 0xa0, 0xb6, + 0xe4, 0x39, 0xfc, 0x54, 0xba, 0x99, 0xb6, 0xbe, + 0x39, 0xee, 0xa5, 0xd9, 0xa0, 0x35, 0x3c, 0x2d, + 0x3e, 0x96, 0xc3, 0x96, 0xa5, 0x0d, 0x2b, 0xbf, + 0x3b, 0xa3, 0xe2, 0xe8, 0x89, 0xed, 0x60, 0xe0, + 0x43, 0x61, 0xb6, 0x73, 0xf6, 0xa7, 0xb4, 0x56, + 0x76, 0x04, 0xf7, 0x8b, 0xf1, 0x84, 0xaa, 0x3e, + 0xe0, 0x08, 0xad, 0xdd, 0xc2, 0x36, 0xfd, 0x3d, + 0xd0, 0xad, 0xf4, 0x3a, 0x7e, 0x80, 0x8c, 0x52, + 0x2b, 0x04, 0xa8, 0x03, 0x27, 0x29, 0x28, 0x31, + 0x3a, 0x71, 0x32, 0x31, 0x3a, 0x00, 0xd5, 0x34, + 0xd2, 0xc5, 0x1c, 0x26, 0xdf, 0xb0, 0xba, 0x78, + 0x75, 0xe5, 0xe9, 0x36, 0x6b, 0x04, 0x03, 0xe2, + 0x57, 0x3f, 0x29, 0x28, 0x31, 0x3a, 0x67, 0x31, + 0x32, 0x38, 0x3a, 0x3b, 0xa0, 0xac, 0xa3, 0xa1, + 0xd1, 0x04, 0x23, 0x5f, 0x9f, 0xbc, 0x6d, 0x9e, + 0x88, 0x2a, 0x28, 0xc1, 0x48, 0xaf, 0xa5, 0x17, + 0x59, 0x3a, 0x17, 0x33, 0x56, 0xaa, 0x8d, 0x27, + 0x64, 0xfe, 0x8e, 0x8a, 0x2e, 0xba, 0xf2, 0x66, + 0xcc, 0x66, 0xbd, 0xa4, 0xfe, 0xa9, 0x07, 0x0d, + 0xae, 0x8c, 0x9f, 0x70, 0xf7, 0x87, 0xaa, 0x01, + 0x47, 0x6b, 0xf9, 0x0f, 0x09, 0x18, 0x42, 0x76, + 0xc4, 0xa3, 0xb9, 0x55, 0x11, 0x8d, 0xa3, 0xa5, + 0x69, 0x30, 0x91, 0xb7, 0x03, 0xef, 0x7f, 0x12, + 0xe6, 0xb9, 0x78, 0x73, 0xe0, 0xc0, 0x4f, 0xc6, + 0xd9, 0x43, 0x99, 0x95, 0x0b, 0x4d, 0x58, 0xd3, + 0x6b, 0x76, 0xb0, 0x6a, 0xcf, 0x68, 0x6d, 0xf0, + 0xd9, 0xc1, 0x88, 0x43, 0x9d, 0xf9, 0x04, 0xcb, + 0xc9, 0x82, 0x6c, 0xee, 0xd4, 0x9c, 0xbd, 0x1c, + 0x4d, 0x54, 0x29, 0x83, 0xa9, 0x5e, 0xaa, 0x10, + 0xa7, 0xc1, 0x04, 0x29, 0x28, 0x31, 0x3a, 0x79, + 0x31, 0x32, 0x39, 0x3a, 0x00, 0x82, 0x33, 0xf1, + 0x91, 0xe3, 0xf2, 0x12, 0x93, 0x5a, 0xed, 0x0c, + 0x9d, 0xec, 0x67, 0xaa, 0xa7, 0x97, 0x7f, 0x9f, + 0x5e, 0xef, 0x6a, 0x3e, 0xa4, 0x7f, 0x9b, 0xed, + 0x65, 0xd7, 0xba, 0x40, 0x6d, 0xe1, 0xde, 0xc1, + 0x14, 0x4c, 0x9b, 0x28, 0x5c, 0x03, 0x8e, 0x1a, + 0xd4, 0x1b, 0x80, 0x1b, 0x07, 0xd6, 0x84, 0x04, + 0x49, 0x6c, 0x1b, 0x08, 0x84, 0x15, 0x54, 0x62, + 0xca, 0xd5, 0x75, 0xff, 0xc8, 0xb3, 0x81, 0x76, + 0x82, 0x91, 0x35, 0x80, 0x20, 0x73, 0x2a, 0x21, + 0xca, 0x22, 0x06, 0xa7, 0x73, 0x99, 0x75, 0x7e, + 0x5e, 0xa6, 0x09, 0x59, 0x66, 0x2c, 0xcd, 0xb1, + 0x8d, 0x3b, 0xc0, 0x68, 0xc5, 0x41, 0xa0, 0x9d, + 0x82, 0x15, 0xc4, 0xdd, 0x47, 0x1c, 0x5b, 0xa9, + 0x74, 0x18, 0xaf, 0x72, 0x63, 0x6b, 0x0a, 0x4e, + 0x95, 0x09, 0x7a, 0xb5, 0x4b, 0x98, 0x85, 0xb9, + 0x6d, 0x9d, 0x3b, 0x73, 0x8c, 0x29, 0x29, 0x29, +}; + +static char sig_dump[] = { + 0x28, 0x37, 0x3a, 0x73, 0x69, 0x67, 0x2d, 0x76, + 0x61, 0x6c, 0x28, 0x33, 0x3a, 0x64, 0x73, 0x61, + 0x28, 0x31, 0x3a, 0x72, 0x32, 0x30, 0x3a, 0xb6, + 0x60, 0x37, 0xef, 0x02, 0x7c, 0x7c, 0x6e, 0x4f, + 0x66, 0x8c, 0x7c, 0x26, 0x77, 0xd9, 0x33, 0x90, + 0xba, 0x7c, 0xfb, 0x29, 0x28, 0x31, 0x3a, 0x73, + 0x32, 0x30, 0x3a, 0x83, 0xc0, 0x84, 0x72, 0xc6, + 0x1c, 0x85, 0x6f, 0x8b, 0x9b, 0xb0, 0x38, 0x38, + 0xb2, 0xb6, 0xdf, 0x1c, 0x52, 0x96, 0x1b, 0x29, + 0x29, 0x29, +}; + +extern gcry_pk_spec_t _gcry_pubkey_spec_dsa; + +static void +dsa_sexp_test (void) +{ + gcry_sexp_t sign_parms, sign_parms_invalid, pubkey, sig; + int rc; + grub_size_t errof; + + rc = _gcry_sexp_build (&sign_parms_invalid, &errof, + "(data (value \"hi\"))\n"); + grub_test_assert (rc == 0, "sexp build failed"); + + rc = _gcry_sexp_build (&sign_parms, &errof, + "(data (value \"hello\"))\n"); + grub_test_assert (rc == 0, "sexp build failed"); + rc = _gcry_sexp_new (&pubkey, pubkey_dump, sizeof(pubkey_dump), 0); + grub_test_assert (rc == 0, "sexp new failed"); + rc = _gcry_sexp_new (&sig, sig_dump, sizeof(sig_dump), 0); + grub_test_assert (rc == 0, "sexp new failed"); + rc = _gcry_pubkey_spec_dsa.verify (sig, sign_parms, pubkey); + grub_test_assert (rc == 0, "signature verification failed: %d", rc); + rc = _gcry_pubkey_spec_dsa.verify (sig, sign_parms_invalid, pubkey); + grub_test_assert (rc != 0, "signature verification succeded wrongly"); +} + +GRUB_FUNCTIONAL_TEST (dsa_sexp_test, dsa_sexp_test); diff --git a/grub-core/tests/rsa_sexp_test.c b/grub-core/tests/rsa_sexp_test.c new file mode 100644 index 000000000..e00befe4e --- /dev/null +++ b/grub-core/tests/rsa_sexp_test.c @@ -0,0 +1,81 @@ +#include <grub/test.h> +#include <grub/crypto.h> +#include <grub/gcrypt/gcrypt.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +static char pubkey_dump[] = { + 0x28, 0x31, 0x30, 0x3a, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x28, 0x33, + 0x3a, 0x72, 0x73, 0x61, 0x28, 0x31, 0x3a, 0x6e, + 0x31, 0x32, 0x39, 0x3a, 0x00, 0xe1, 0x35, 0xc1, + 0x97, 0x90, 0xe8, 0x54, 0xa8, 0x3b, 0x97, 0x05, + 0xaf, 0x45, 0xaf, 0x67, 0xbf, 0xec, 0x07, 0xbe, + 0x9b, 0x55, 0x9c, 0x3f, 0x47, 0xae, 0x25, 0xb6, + 0xe3, 0x23, 0x99, 0x10, 0x5e, 0x17, 0x1a, 0xda, + 0x33, 0xe6, 0x73, 0x0d, 0x96, 0x9c, 0x5c, 0x25, + 0x13, 0x5d, 0x49, 0xb9, 0x86, 0xc0, 0xb1, 0x80, + 0x29, 0x20, 0xb2, 0x91, 0x72, 0x43, 0xcc, 0x2a, + 0x67, 0xd3, 0x11, 0xe8, 0x7b, 0x21, 0x75, 0xf6, + 0x1b, 0xc0, 0xb2, 0x01, 0xc8, 0x35, 0xaa, 0xfb, + 0xa7, 0x29, 0xb4, 0xb9, 0x94, 0x4e, 0x53, 0x49, + 0x82, 0x74, 0xe9, 0x23, 0x69, 0xa4, 0xf6, 0xdf, + 0x40, 0x2a, 0x73, 0x01, 0xfa, 0xe7, 0xf8, 0x32, + 0x6b, 0x57, 0xfe, 0xb9, 0x7d, 0x02, 0xc2, 0xfb, + 0x7f, 0x99, 0x1f, 0x6e, 0x8d, 0x53, 0x01, 0x56, + 0xaf, 0x46, 0x62, 0xb3, 0xe0, 0xa8, 0xa6, 0x0a, + 0x55, 0x2c, 0x4b, 0x85, 0x5b, 0x29, 0x28, 0x31, + 0x3a, 0x65, 0x33, 0x3a, 0x01, 0x00, 0x01, 0x29, + 0x29, 0x29, +}; + +static char sig_dump[] = { + 0x28, 0x37, 0x3a, 0x73, 0x69, 0x67, 0x2d, 0x76, + 0x61, 0x6c, 0x28, 0x33, 0x3a, 0x72, 0x73, 0x61, + 0x28, 0x31, 0x3a, 0x73, 0x31, 0x32, 0x38, 0x3a, + 0x5b, 0x2d, 0xeb, 0xa5, 0x4b, 0x8b, 0xd9, 0x92, + 0x66, 0x57, 0x89, 0xd8, 0x31, 0xc0, 0x0e, 0x53, + 0xf8, 0x1c, 0x4f, 0xc8, 0x79, 0x67, 0xb9, 0x10, + 0xe5, 0x63, 0x5f, 0xef, 0xb1, 0x0b, 0x0e, 0x7f, + 0xed, 0x86, 0x06, 0xa8, 0x05, 0xbf, 0x6b, 0xd1, + 0x36, 0x41, 0x08, 0x3b, 0xd0, 0xbd, 0xef, 0xb7, + 0xc2, 0x69, 0xb8, 0xb4, 0x3e, 0x2c, 0xb5, 0x39, + 0x13, 0x03, 0xca, 0xad, 0x5f, 0xd2, 0x57, 0x23, + 0x19, 0xdd, 0x71, 0xdd, 0x93, 0xe1, 0x3e, 0x43, + 0xaf, 0xdd, 0x94, 0x07, 0xf3, 0x78, 0xb3, 0x2a, + 0x57, 0x24, 0x97, 0x04, 0x58, 0xc1, 0xaf, 0xd3, + 0xe7, 0xa7, 0x65, 0xd1, 0x23, 0xa3, 0x93, 0x18, + 0xc7, 0x52, 0x70, 0x53, 0x60, 0x8b, 0x5a, 0x5d, + 0x6e, 0xf9, 0x83, 0x52, 0x99, 0xbb, 0x0a, 0x53, + 0x0e, 0x2a, 0x7f, 0x81, 0x52, 0x02, 0x32, 0xa4, + 0xfc, 0xe0, 0x17, 0x0c, 0x0e, 0x96, 0xbd, 0x01, + 0x29, 0x29, 0x29, +}; + +extern gcry_pk_spec_t _gcry_pubkey_spec_rsa; + +static void +rsa_sexp_test (void) +{ + gcry_sexp_t sign_parms, sign_parms_invalid, pubkey, sig; + int rc; + grub_size_t errof; + + rc = _gcry_sexp_build (&sign_parms_invalid, &errof, + "(data (flags) (value \"hi\"))\n"); + grub_test_assert (rc == 0, "sexp build failed"); + + rc = _gcry_sexp_build (&sign_parms, &errof, + "(data (flags) (value \"hello\"))\n"); + grub_test_assert (rc == 0, "sexp build failed"); + rc = _gcry_sexp_new (&pubkey, pubkey_dump, sizeof(pubkey_dump), 0); + grub_test_assert (rc == 0, "sexp new failed"); + rc = _gcry_sexp_new (&sig, sig_dump, sizeof(sig_dump), 0); + grub_test_assert (rc == 0, "sexp new failed"); + rc = _gcry_pubkey_spec_rsa.verify (sig, sign_parms, pubkey); + grub_test_assert (rc == 0, "signature verification failed: %d", rc); + rc = _gcry_pubkey_spec_rsa.verify (sig, sign_parms_invalid, pubkey); + grub_test_assert (rc != 0, "signature verification succeded wrongly"); +} + +GRUB_FUNCTIONAL_TEST (rsa_sexp_test, rsa_sexp_test); diff --git a/include/grub/crypto.h b/include/grub/crypto.h index 31c87c302..01f86be71 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -65,7 +65,31 @@ typedef enum GPG_ERR_WRONG_PUBKEY_ALGO, GPG_ERR_OUT_OF_MEMORY, GPG_ERR_TOO_LARGE, - GPG_ERR_ENOMEM + GPG_ERR_ENOMEM, + GPG_ERR_CHECKSUM, + GPG_ERR_INV_LENGTH, + GPG_ERR_VALUE_NOT_FOUND, + GPG_ERR_ERANGE, + GPG_ERR_INV_DATA, + GPG_ERR_ENCODING_PROBLEM, + GPG_ERR_BUFFER_TOO_SHORT, + GPG_ERR_SYNTAX, + GPG_ERR_SEXP_INV_LEN_SPEC, + GPG_ERR_SEXP_UNMATCHED_DH, + GPG_ERR_SEXP_UNMATCHED_PAREN, + GPG_ERR_SEXP_ZERO_PREFIX, + GPG_ERR_SEXP_NESTED_DH, + GPG_ERR_SEXP_UNEXPECTED_PUNC, + GPG_ERR_SEXP_BAD_CHARACTER, + GPG_ERR_SEXP_NOT_CANONICAL, + GPG_ERR_SEXP_STRING_TOO_LONG, + GPG_ERR_SEXP_BAD_QUOTATION, + GPG_ERR_SEXP_ODD_HEX_NUMBERS, + GPG_ERR_SEXP_BAD_HEX_CHAR, + GPG_ERR_LIMIT_REACHED, + GPG_ERR_EOF, + GPG_ERR_BAD_DATA, + GPG_ERR_EINVAL, } gpg_err_code_t; typedef gpg_err_code_t gpg_error_t; typedef gpg_error_t gcry_error_t; @@ -84,37 +108,60 @@ enum gcry_cipher_modes }; #endif +/* Extra algo IDs not coming from gcrypt. */ +#define GCRY_MD_ADLER32 10301 +#define GCRY_MD_CRC64 10302 + /* Don't rely on this. Check! */ #define GRUB_CRYPTO_MAX_MDLEN 64 #define GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE 16 #define GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE 256 /* Type for the cipher_setkey function. */ +struct cipher_bulk_ops; + typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c, const unsigned char *key, - unsigned keylen); + unsigned keylen, + struct cipher_bulk_ops *bulk_ops); /* Type for the cipher_encrypt function. */ -typedef void (*gcry_cipher_encrypt_t) (void *c, - unsigned char *outbuf, - const unsigned char *inbuf); +typedef unsigned int (*gcry_cipher_encrypt_t) (void *c, + unsigned char *outbuf, + const unsigned char *inbuf); /* Type for the cipher_decrypt function. */ -typedef void (*gcry_cipher_decrypt_t) (void *c, - unsigned char *outbuf, - const unsigned char *inbuf); +typedef unsigned int (*gcry_cipher_decrypt_t) (void *c, + unsigned char *outbuf, + const unsigned char *inbuf); /* Type for the cipher_stencrypt function. */ typedef void (*gcry_cipher_stencrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf, - unsigned int n); + grub_size_t n); /* Type for the cipher_stdecrypt function. */ typedef void (*gcry_cipher_stdecrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf, - unsigned int n); + grub_size_t n); + +typedef void (*selftest_report_func_t)(const char *domain, + int algo, + const char *what, + const char *errdesc); + +/* The type used to convey additional information to a cipher. */ +typedef gpg_err_code_t (*gcry_cipher_set_extra_info_t) + (void *c, int what, const void *buffer, grub_size_t buflen); + +/* The type used to set an IV directly in the algorithm module. */ +typedef void (*gcry_cipher_setiv_func_t)(void *c, const grub_uint8_t *iv, grub_size_t ivlen); + +/* Definition of the selftest functions. */ +typedef gpg_err_code_t (*gcry_selftest_func_t) + (int algo, int extended, selftest_report_func_t report); typedef struct gcry_cipher_oid_spec { @@ -125,9 +172,14 @@ typedef struct gcry_cipher_oid_spec /* Module specification structure for ciphers. */ typedef struct gcry_cipher_spec { + int algo; + struct { + unsigned int disabled:1; + unsigned int fips:1; + } flags; const char *name; const char **aliases; - gcry_cipher_oid_spec_t *oids; + const gcry_cipher_oid_spec_t *oids; grub_size_t blocksize; grub_size_t keylen; grub_size_t contextsize; @@ -136,6 +188,10 @@ typedef struct gcry_cipher_spec gcry_cipher_decrypt_t decrypt; gcry_cipher_stencrypt_t stencrypt; gcry_cipher_stdecrypt_t stdecrypt; + gcry_selftest_func_t selftest; + gcry_cipher_set_extra_info_t set_extra_info; + gcry_cipher_setiv_func_t setiv; + #ifdef GRUB_UTIL const char *modname; #endif @@ -143,7 +199,7 @@ typedef struct gcry_cipher_spec } gcry_cipher_spec_t; /* Type for the md_init function. */ -typedef void (*gcry_md_init_t) (void *c); +typedef void (*gcry_md_init_t) (void *c, unsigned int flags); /* Type for the md_write function. */ typedef void (*gcry_md_write_t) (void *c, const void *buf, grub_size_t nbytes); @@ -162,16 +218,24 @@ typedef struct gcry_md_oid_spec /* Module specification structure for message digests. */ typedef struct gcry_md_spec { + int algo; + struct { + unsigned int disabled:1; + unsigned int fips:1; + } flags; const char *name; - unsigned char *asnoid; + const unsigned char *asnoid; int asnlen; - gcry_md_oid_spec_t *oids; + const gcry_md_oid_spec_t *oids; grub_size_t mdlen; gcry_md_init_t init; gcry_md_write_t write; gcry_md_final_t final; gcry_md_read_t read; + void *extract; + void *hash_buffers; grub_size_t contextsize; /* allocate this amount of context */ + /* Block size, needed for HMAC. */ grub_size_t blocksize; #ifdef GRUB_UTIL @@ -180,54 +244,123 @@ typedef struct gcry_md_spec struct gcry_md_spec *next; } gcry_md_spec_t; +typedef struct gcry_md_handle*gcry_md_hd_t; + struct gcry_mpi; typedef struct gcry_mpi *gcry_mpi_t; +struct gcry_sexp; +typedef struct gcry_sexp *gcry_sexp_t; + + +#define PUBKEY_FLAG_NO_BLINDING (1 << 0) +#define PUBKEY_FLAG_RFC6979 (1 << 1) +#define PUBKEY_FLAG_FIXEDLEN (1 << 2) +#define PUBKEY_FLAG_LEGACYRESULT (1 << 3) +#define PUBKEY_FLAG_RAW_FLAG (1 << 4) +#define PUBKEY_FLAG_TRANSIENT_KEY (1 << 5) +#define PUBKEY_FLAG_USE_X931 (1 << 6) +#define PUBKEY_FLAG_USE_FIPS186 (1 << 7) +#define PUBKEY_FLAG_USE_FIPS186_2 (1 << 8) +#define PUBKEY_FLAG_PARAM (1 << 9) +#define PUBKEY_FLAG_COMP (1 << 10) +#define PUBKEY_FLAG_NOCOMP (1 << 11) +#define PUBKEY_FLAG_EDDSA (1 << 12) +#define PUBKEY_FLAG_GOST (1 << 13) +#define PUBKEY_FLAG_NO_KEYTEST (1 << 14) +#define PUBKEY_FLAG_DJB_TWEAK (1 << 15) +#define PUBKEY_FLAG_SM2 (1 << 16) +#define PUBKEY_FLAG_PREHASH (1 << 17) + +enum pk_operation + { + PUBKEY_OP_ENCRYPT, + PUBKEY_OP_DECRYPT, + PUBKEY_OP_SIGN, + PUBKEY_OP_VERIFY + }; + +enum pk_encoding + { + PUBKEY_ENC_RAW, + PUBKEY_ENC_PKCS1, + PUBKEY_ENC_PKCS1_RAW, + PUBKEY_ENC_OAEP, + PUBKEY_ENC_PSS, + PUBKEY_ENC_UNKNOWN + }; + +struct pk_encoding_ctx +{ + enum pk_operation op; + unsigned int nbits; + + enum pk_encoding encoding; + int flags; + + int hash_algo; + + /* for OAEP */ + unsigned char *label; + grub_size_t labellen; + + /* for PSS */ + grub_size_t saltlen; + + int (* verify_cmp) (void *opaque, gcry_mpi_t tmp); + void *verify_arg; +}; + /* Type for the pk_generate function. */ -typedef gcry_err_code_t (*gcry_pk_generate_t) (int algo, - unsigned int nbits, - unsigned long use_e, - gcry_mpi_t *skey, - gcry_mpi_t **retfactors); +typedef gcry_err_code_t (*gcry_pk_generate_t) (gcry_sexp_t genparms, + gcry_sexp_t *r_skey); /* Type for the pk_check_secret_key function. */ -typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo, - gcry_mpi_t *skey); +typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (gcry_sexp_t keyparms); /* Type for the pk_encrypt function. */ -typedef gcry_err_code_t (*gcry_pk_encrypt_t) (int algo, - gcry_mpi_t *resarr, - gcry_mpi_t data, - gcry_mpi_t *pkey, - int flags); +typedef gcry_err_code_t (*gcry_pk_encrypt_t) (gcry_sexp_t *r_ciph, + gcry_sexp_t s_data, + gcry_sexp_t keyparms); /* Type for the pk_decrypt function. */ -typedef gcry_err_code_t (*gcry_pk_decrypt_t) (int algo, - gcry_mpi_t *result, - gcry_mpi_t *data, - gcry_mpi_t *skey, - int flags); +typedef gcry_err_code_t (*gcry_pk_decrypt_t) (gcry_sexp_t *r_plain, + gcry_sexp_t s_data, + gcry_sexp_t keyparms); /* Type for the pk_sign function. */ -typedef gcry_err_code_t (*gcry_pk_sign_t) (int algo, - gcry_mpi_t *resarr, - gcry_mpi_t data, - gcry_mpi_t *skey); +typedef gcry_err_code_t (*gcry_pk_sign_t) (gcry_sexp_t *r_sig, + gcry_sexp_t s_data, + gcry_sexp_t keyparms); /* Type for the pk_verify function. */ -typedef gcry_err_code_t (*gcry_pk_verify_t) (int algo, - gcry_mpi_t hash, - gcry_mpi_t *data, - gcry_mpi_t *pkey, - int (*cmp) (void *, gcry_mpi_t), - void *opaquev); +typedef gcry_err_code_t (*gcry_pk_verify_t) (gcry_sexp_t s_sig, + gcry_sexp_t s_data, + gcry_sexp_t keyparms); /* Type for the pk_get_nbits function. */ -typedef unsigned (*gcry_pk_get_nbits_t) (int algo, gcry_mpi_t *pkey); +typedef unsigned (*gcry_pk_get_nbits_t) (gcry_sexp_t keyparms); + +/* The type used to compute the keygrip. */ +typedef gpg_err_code_t (*pk_comp_keygrip_t) (gcry_md_hd_t md, + gcry_sexp_t keyparm); + +/* The type used to query an ECC curve name. */ +typedef const char *(*pk_get_curve_t)(gcry_sexp_t keyparms, int iterator, + unsigned int *r_nbits); + +/* The type used to query ECC curve parameters by name. */ +typedef gcry_sexp_t (*pk_get_curve_param_t)(const char *name); /* Module specification structure for message digests. */ typedef struct gcry_pk_spec { + int algo; + struct { + unsigned int disabled:1; + unsigned int fips:1; + } flags; + int use; const char *name; const char **aliases; const char *elements_pkey; @@ -235,7 +368,6 @@ typedef struct gcry_pk_spec const char *elements_enc; const char *elements_sig; const char *elements_grip; - int use; gcry_pk_generate_t generate; gcry_pk_check_secret_key_t check_secret_key; gcry_pk_encrypt_t encrypt; @@ -243,6 +375,10 @@ typedef struct gcry_pk_spec gcry_pk_sign_t sign; gcry_pk_verify_t verify; gcry_pk_get_nbits_t get_nbits; + pk_comp_keygrip_t comp_keygrip; + pk_get_curve_t get_curve; + pk_get_curve_param_t get_curve_param; + #ifdef GRUB_UTIL const char *modname; #endif @@ -345,6 +481,10 @@ grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in, grub_size_t inlen); const gcry_md_spec_t * grub_crypto_lookup_md_by_name (const char *name); +const gcry_md_spec_t * +grub_crypto_lookup_md_by_algo (int algo); +const gcry_md_spec_t * +grub_crypto_lookup_md_by_oid (const char *oid); grub_err_t grub_crypto_gcry_error (gcry_err_code_t in); @@ -408,7 +548,35 @@ void _gcry_assert_failed (const char *expr, const char *file, int line, void _gcry_burn_stack (int bytes); void _gcry_log_error( const char *fmt, ... ) __attribute__ ((format (__printf__, 1, 2))); +void _gcry_log_info (const char *fmt, ...); +void __gcry_burn_stack (unsigned int size); +void __gcry_burn_stack_dummy (void); +void _gcry_bug( const char *file, int line, const char *func ); +void +_gcry_fast_wipememory (void *ptr, grub_size_t len); +void +_gcry_fast_wipememory2 (void *ptr, int set, grub_size_t len); +unsigned int +_gcry_ct_memequal (const void *b1, const void *b2, grub_size_t len); +unsigned int +_gcry_ct_not_memequal (const void *b1, const void *b2, grub_size_t len); + + +static inline unsigned int _gcry_get_hw_features(void) +{ + return 0; +} +void *_gcry_malloc(grub_size_t n); +void *_gcry_malloc_secure(grub_size_t n); +void *_gcry_xmalloc(grub_size_t n); +void *_gcry_xmalloc_secure(grub_size_t n); +void _gcry_free (void *p); +void *_gcry_xrealloc (void *a, grub_size_t n); +int _gcry_is_secure (const void *a); +void *_gcry_xcalloc (grub_size_t n, grub_size_t m); +void *_gcry_xcalloc_secure (grub_size_t n, grub_size_t m); +void _gcry_divide_by_zero (void); #ifdef GRUB_UTIL void grub_gcry_init_all (void); @@ -419,4 +587,11 @@ grub_get_random (void *out, grub_size_t len); #endif +typedef struct _gpgrt_b64state *gpgrt_b64state_t; +gpgrt_b64state_t gpgrt_b64dec_start (const char *title); +gpg_error_t gpgrt_b64dec_proc (gpgrt_b64state_t state, + void *buffer, grub_size_t length, + grub_size_t *r_nbytes); +gpg_error_t gpgrt_b64dec_finish (gpgrt_b64state_t state); +const char *gpg_strerror (gpg_error_t err); #endif diff --git a/include/grub/gcrypt/gpg-error.h b/include/grub/gcrypt/gpg-error.h index 1e4250284..444bef221 100644 --- a/include/grub/gcrypt/gpg-error.h +++ b/include/grub/gcrypt/gpg-error.h @@ -29,4 +29,13 @@ gpg_err_source (gpg_error_t err __attribute__ ((unused))) gcry_err_code_t gpg_error_from_syserror (void); +gcry_err_code_t +gpg_err_code_from_syserror (void); + +gcry_err_code_t +gpg_error_from_errno (int err); + +gcry_err_code_t +gpg_err_code_from_errno (int err); + #endif diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 25ae52ab6..7e6706976 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -364,7 +364,7 @@ static void cmd_crc (char *pathname) { grub_uint8_t *crc32_context = xmalloc (GRUB_MD_CRC32->contextsize); - GRUB_MD_CRC32->init(crc32_context); + GRUB_MD_CRC32->init(crc32_context, 0); read_file (pathname, crc_hook, crc32_context); GRUB_MD_CRC32->final(crc32_context); diff --git a/util/import_gcry.py b/util/import_gcry.py index 2b3322d3a..5422afa11 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -62,6 +62,12 @@ confutil.write (" cflags = '$(CFLAGS_GCRY)';\n"); confutil.write (" cppflags = '$(CPPFLAGS_GCRY)';\n"); confutil.write (" extra_dist = grub-core/lib/libgcrypt-grub/cipher/ChangeLog;\n"); confutil.write ("\n"); + +for src in ['src/const-time.c']: + confutil.write (" common = grub-core/lib/libgcrypt-grub/%s;\n" % src) + +confutil.write ("\n"); + chlog = "" modules_sym_md = [] @@ -79,10 +85,23 @@ mdblocksizes = {"_gcry_digest_spec_crc32" : 64, "_gcry_digest_spec_sha256" : 64, "_gcry_digest_spec_sha384" : 128, "_gcry_digest_spec_sha512" : 128, + "_gcry_digest_spec_sha512_256": 128, + "_gcry_digest_spec_sha512_224": 128, "_gcry_digest_spec_tiger" : 64, "_gcry_digest_spec_tiger1" : 64, "_gcry_digest_spec_tiger2" : 64, - "_gcry_digest_spec_whirlpool" : 64} + "_gcry_digest_spec_whirlpool" : 64, + "_gcry_digest_spec_shake128": 64, + "_gcry_digest_spec_shake256": 64, + "_gcry_digest_spec_sm3": 64, + "_gcry_digest_spec_stribog_256": 64, + "_gcry_digest_spec_stribog_512": 64, + "_gcry_digest_spec_sha3_224": 1152 / 8, + "_gcry_digest_spec_sha3_256": 1088 / 8, + "_gcry_digest_spec_sha3_384": 832 / 8, + "_gcry_digest_spec_sha3_512": 576 / 8, + "_gcry_digest_spec_gost3411_94": 32, + "_gcry_digest_spec_gost3411_cp": 32} cryptolist = codecs.open (os.path.join (cipher_dir_out, "crypto.lst"), "w", "utf-8") @@ -99,13 +118,32 @@ cryptolist.write ("AES-256: gcry_rijndael\n"); cryptolist.write ("ADLER32: adler32\n"); cryptolist.write ("CRC64: crc64\n"); +extra_files = { + "gcry_camellia": ["camellia.c"], # Main file is camellia-glue.c + "gcry_sha512" : ["hash-common.c"], +} +extra_files_list = [x for xs in extra_files.values() for x in xs] + ["pubkey-util.c", "rsa-common.c", "dsa-common.c"] + for cipher_file in cipher_files: infile = os.path.join (cipher_dir_in, cipher_file) outfile = os.path.join (cipher_dir_out, cipher_file) if cipher_file == "ChangeLog" or cipher_file == "ChangeLog-2011": continue chlognew = " * %s" % cipher_file - if re.match ("(Manifest|Makefile\.am|ac\.c|cipher\.c|hash-common\.c|hmac-tests\.c|md\.c|pubkey\.c)$", cipher_file) or cipher_file == "kdf.c" or cipher_file == "elgamal.c" or cipher_file == "primegen.c" or cipher_file == "ecc.c" or cipher_file == "test-getrusage.c": + # Unused generic support files + if re.match ("(Makefile\.am|md\.c|cipher\.c|cipher-.*\.c|mac-.*\.c|mac\.c|pubkey\.c)$", cipher_file): + chlog = "%s%s: Removed\n" % (chlog, chlognew) + continue + # TODO: Support KDF + if re.match ("(kdf\.c|scrypt\.c)$", cipher_file): + chlog = "%s%s: Removed\n" % (chlog, chlognew) + continue + # TODO: Support chacha20 and poly1305 + if cipher_file in ["chacha20.c", "ecc.c", "elgamal.c"]: + chlog = "%s%s: Removed\n" % (chlog, chlognew) + continue + # TODO: Use optimized versions + if re.match ("(.*\.[sS]|.*-intel-shaext\.c|.*-ssse3-i386\.c|.*-ppc\.c|.*-ssse3-amd64\.c|.*-s390x\.c|rijndael-aesni\.c|crc-intel-pclmul\.c|.*-armv8-ce\.c|.*-p10le\.c|rijndael-padlock.c|rijndael-ppc9le.c|rijndael-vaes.c)$", cipher_file): chlog = "%s%s: Removed\n" % (chlog, chlognew) continue # Autogenerated files. Not even worth mentionning in ChangeLog @@ -148,14 +186,10 @@ for cipher_file in cipher_files: iscipher = False iscryptostart = False iscomma = False - isglue = False skip_statement = False + skip_comma = 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 + modname = "gcry_%s" % cipher_file.removesuffix(".c").removesuffix("-glue").replace("-", "_") for line in f: line = line if skip_statement: @@ -171,7 +205,7 @@ for cipher_file in cipher_files: skip2 = False continue if iscryptostart: - s = re.search (" *\"([A-Z0-9_a-z]*)\"", line) + 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)) @@ -212,11 +246,14 @@ for cipher_file in cipher_files: chlognew = "%s %s" % (chlognew, chmsg) nch = True continue + if (not hold) and (re.match (r"[ \t]*(run_selftests|do_tripledes_set_extra_info),?", line) is not None): + iscomma = True + line = "" if hold: hold = False # We're optimising for size and exclude anything needing good # randomness. - 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|dsa_generate_ext|test_keys|gen_k|sign|gen_x931_parm_xp|generate_x931|generate_key|dsa_generate|dsa_sign|ecc_sign|generate|generate_fips186|_gcry_register_pk_dsa_progress|_gcry_register_pk_ecc_progress|progress|scanval|ec2os|ecc_generate_ext|ecc_generate|compute_keygrip|ecc_get_param|_gcry_register_pk_dsa_progress|gen_x931_parm_xp|gen_x931_parm_xi|rsa_decrypt|rsa_sign|rsa_generate_ext|rsa_generate|secret|check_exponent|rsa_blind|rsa_unblind|extract_a_from_sexp|curve_free|curve_copy|point_set)", line) is None: + if re.match ("(_gcry_hash_selftest_check_one|bulk_selftest_setkey|run_selftests|do_tripledes_set_extra_info|selftest|sm4_selftest|_gcry_[a-z0-9_]*_hash_buffer|tripledes_set2keys|_gcry_rmd160_mixblock|serpent_test|dsa_generate_ext|test_keys|gen_k|sign|gen_x931_parm_xp|generate_x931|generate_key|dsa_generate|dsa_sign|ecc_sign|generate|generate_fips186|_gcry_register_pk_dsa_progress|_gcry_register_pk_ecc_progress|progress|scanval|ec2os|ecc_generate_ext|ecc_generate|ecc_get_param|_gcry_register_pk_dsa_progress|gen_x931_parm_xp|gen_x931_parm_xi|rsa_decrypt|rsa_sign|rsa_generate_ext|rsa_generate|secret|check_exponent|rsa_blind|rsa_unblind|extract_a_from_sexp|curve_free|curve_copy|point_set|_gcry_dsa_gen_rfc6979_k|bits2octets|int2octets)", line) is not None: skip = 1 if not re.match ("selftest", line) is None and cipher_file == "idea.c": @@ -224,6 +261,11 @@ for cipher_file in cipher_files: if not re.match ("serpent_test", line) is None: fw.write ("static const char *serpent_test (void) { return 0; }\n"); + if not re.match ("sm4_selftest", line) is None: + fw.write ("static const char *sm4_selftest (void) { return 0; }\n"); + hash_buf = re.match ("(_gcry_[a-z0-9_]*_hash_buffers)", line) + if hash_buf is not None: + fw.write ("#define %s 0" % (hash_buf.group(0))) if not re.match ("dsa_generate", line) is None: fw.write ("#define dsa_generate 0"); if not re.match ("ecc_generate", line) is None: @@ -257,37 +299,38 @@ for cipher_file in cipher_files: chlognew = "%s: %s" % (chlognew, chmsg) nch = True continue - m = re.match ("gcry_cipher_spec_t", line) + m = re.match ("(const )?gcry_cipher_spec_t", line) if isc and not m is None: assert (not ismd) assert (not ispk) assert (not iscipher) assert (not iscryptostart) - ciphername = line [len ("gcry_cipher_spec_t"):].strip () + ciphername = line.removeprefix("const ").removeprefix("gcry_cipher_spec_t").strip () ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group () ciphernames.append (ciphername) iscipher = True iscryptostart = True - m = re.match ("gcry_pk_spec_t", line) + m = re.match ("(const )?gcry_pk_spec_t", line) if isc and not m is None: assert (not ismd) assert (not ispk) assert (not iscipher) assert (not iscryptostart) - pkname = line [len ("gcry_pk_spec_t"):].strip () + pkname = line.removeprefix("const ").removeprefix("gcry_pk_spec_t").strip () pkname = re.match("[a-zA-Z0-9_]*",pkname).group () pknames.append (pkname) ispk = True iscryptostart = True - m = re.match ("gcry_md_spec_t", line) + m = re.match ("(const )?gcry_md_spec_t", line) if isc and not m is None: assert (not ismd) assert (not ispk) assert (not iscipher) assert (not iscryptostart) - mdname = line [len ("gcry_md_spec_t"):].strip () + line = line.removeprefix("const ") + mdname = line.removeprefix("const ").removeprefix("gcry_md_spec_t").strip () mdname = re.match("[a-zA-Z0-9_]*",mdname).group () mdnames.append (mdname) ismd = True @@ -350,7 +393,7 @@ for cipher_file in cipher_files: nch = True continue - m = re.match ("(static const char( |)\*|static gpg_err_code_t|void|static int|static gcry_err_code_t|static gcry_mpi_t|static void|void|static elliptic_curve_t) *$", line) + m = re.match ("((static )?const char( |)\*|(static )?gpg_err_code_t|void|static int|(static )?gcry_err_code_t|static gcry_mpi_t|static void|void|static elliptic_curve_t) *$", line) if not m is None: hold = True holdline = line @@ -421,11 +464,9 @@ for cipher_file in cipher_files: continue fw.write (line) if len (ciphernames) > 0 or len (mdnames) > 0 or len (pknames) > 0: - if isglue: - modfiles = "lib/libgcrypt-grub/cipher/%s lib/libgcrypt-grub/cipher/%s" \ - % (cipher_file, cipher_file.replace ("-glue.c", ".c")) - else: - modfiles = "lib/libgcrypt-grub/cipher/%s" % cipher_file + modfiles = [cipher_file] + if modname in extra_files.keys(): + modfiles += extra_files[modname] if len (ciphernames) > 0 or len (mdnames) > 0: modules_sym_md.append (modname) chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname @@ -447,7 +488,7 @@ for cipher_file in cipher_files: chlognew = "%s\n %s" % (chlognew, chmsg) fw.write (" grub_md_register (&%s);\n" % mdname) for pkname in pknames: - chmsg = "Register pk %s" % mdname + chmsg = "Register pk %s" % pkname chlognew = "%s\n %s" % (chlognew, chmsg) fw.write (" grub_crypto_pk_%s = &%s;\n" % (pkname.replace ("_gcry_pubkey_spec_", ""), pkname)) @@ -465,17 +506,17 @@ for cipher_file in cipher_files: chlognew = "%s\n %s" % (chlognew, chmsg) fw.write (" grub_md_unregister (&%s);\n" % mdname) for pkname in pknames: - chmsg = "Unregister pk %s" % mdname + chmsg = "Unregister pk %s" % pkname chlognew = "%s\n %s" % (chlognew, chmsg) fw.write (" grub_crypto_pk_%s = 0;\n" % (pkname.replace ("_gcry_pubkey_spec_", ""))) fw.write ("}\n") conf.write ("module = {\n") conf.write (" name = %s;\n" % modname) - for src in modfiles.split(): - conf.write (" common = %s;\n" % src) + for src in modfiles: + conf.write (" common = lib/libgcrypt-grub/cipher/%s;\n" % src) if len (ciphernames) > 0 or len (mdnames) > 0: - confutil.write (" common = grub-core/%s;\n" % src) + confutil.write (" common = grub-core/lib/libgcrypt-grub/cipher/%s;\n" % src) if modname == "gcry_ecc": conf.write (" common = lib/libgcrypt-grub/mpi/ec.c;\n") conf.write (" cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';\n") @@ -490,7 +531,7 @@ for cipher_file in cipher_files: fw.close () if nch: chlog = "%s%s\n" % (chlog, chlognew) - elif isc and cipher_file != "camellia.c": + elif isc and cipher_file not in extra_files_list: print ("WARNING: C file isn't a module: %s" % cipher_file) f.close () fw.close () @@ -512,7 +553,7 @@ for src in sorted (os.listdir (os.path.join (indir, "src"))): or src == "libgcrypt.vers" or src == "Makefile.am" \ or src == "Manifest" or src == "misc.c" \ or src == "missing-string.c" or src == "module.c" \ - or src == "secmem.c" or src == "sexp.c" \ + or src == "secmem.c" \ or src == "stdmem.c" or src == "visibility.c": continue outfile = os.path.join (basedir, "src", src) @@ -534,8 +575,17 @@ for src in sorted (os.listdir (os.path.join (indir, "src"))): fw.close () continue + if src == "cipher-proto.h": + fw.write("#include <grub/crypto.h>\n") + fw.write("typedef gcry_selftest_func_t selftest_func_t;") + f.close () + fw.close () + continue + if src == "g10lib.h": - fw.write (f.read ().replace ("(printf,f,a)", "(__printf__,f,a)")) + fw.write("#include <cipher_wrap.h>\n") + fw.write("#include <grub/crypto.h>\n") + fw.write (f.read ().replace ("(printf,f,a)", "(__printf__,f,a)").replace ("#include \"../compat/libcompat.h\"", "").replace("#define N_(a) (a)", "")) f.close () fw.close () continue @@ -546,7 +596,7 @@ for src in sorted (os.listdir (os.path.join (indir, "src"))): for src in sorted (os.listdir (os.path.join (indir, "mpi"))): if src == "config.links" or src == "ChangeLog-2011" \ - or src == "mpi-scan.c" or src == "Manifest" \ + or src == "Manifest" \ or src == "Makefile.am": continue infile = os.path.join (indir, "mpi", src) @@ -568,7 +618,7 @@ for src in sorted (os.listdir (os.path.join (indir, "mpi"))): hold = False # We're optimising for size and exclude anything needing good # randomness. - if not re.match ("(_gcry_mpi_get_hw_config|gcry_mpi_randomize)", line) is None: + if not re.match ("(_gcry_mpi_get_hw_config|gcry_mpi_randomize|_gcry_mpi_randomize)", line) is None: skip = 1 continue else: @@ -612,9 +662,6 @@ fw.write ("#include <cipher_wrap.h>\n") chlog = "%s * g10lib.h: Likewise.\n" % chlog fw.close () -infile = os.path.join (cipher_dir_in, "ChangeLog") -outfile = os.path.join (cipher_dir_out, "ChangeLog") - conf.close (); initfile = codecs.open (os.path.join (cipher_dir_out, "init.c"), "w", "utf-8") @@ -643,7 +690,7 @@ confutil.write ("};\n"); confutil.close (); -f=codecs.open (infile, "r", "utf-8") +outfile = os.path.join (cipher_dir_out, "ChangeLog") fw=codecs.open (outfile, "w", "utf-8") dt = datetime.date.today () fw.write ("%04d-%02d-%02d Automatic import tool\n" % \ @@ -653,7 +700,4 @@ fw.write (" Imported ciphers to GRUB\n") fw.write ("\n") fw.write (chlog) fw.write ("\n") -for line in f: - fw.write (line) -f.close () fw.close () diff --git a/util/import_gcrypt_inth.sed b/util/import_gcrypt_inth.sed new file mode 100644 index 000000000..ebe9371ee --- /dev/null +++ b/util/import_gcrypt_inth.sed @@ -0,0 +1,17 @@ +/^#@INSERT_SYS_SELECT_H@/ d +/^@FALLBACK_SOCKLEN_T@/ d +/^# *include <stdlib\.h>/ d +/^# *include <string\.h>/ d +/^# *include <winsock2\.h>/ d +/^# *include <ws2tcpip\.h>/ d +/^# *include <time\.h>/ d +/^# *include <sys\/socket\.h>/ d +/^# *include <sys\/time\.h>/ d +/^ typedef long ssize_t;/ d +/^ typedef int pid_t;/ d +/^# *include <gpg-error\.h>/ s,#include <gpg-error.h>,#include <grub/gcrypt/gpg-error.h>, +/^typedef gpg_error_t gcry_error_t;/ d +/^typedef gpg_err_code_t gcry_err_code_t;/ d +/^typedef struct gcry_mpi \*gcry_mpi_t;/ d +/^#error gcrypt.h already included/ d +p diff --git a/util/import_gcrypth.sed b/util/import_gcrypth.sed index fe6d1a072..503b4b547 100644 --- a/util/import_gcrypth.sed +++ b/util/import_gcrypth.sed @@ -13,6 +13,4 @@ /^typedef gpg_error_t gcry_error_t;/ d /^typedef gpg_err_code_t gcry_err_code_t;/ d /^typedef struct gcry_mpi \*gcry_mpi_t;/ d -/^struct gcry_thread_cbs/ d -s,_gcry_mpi_invm,gcry_mpi_invm,g p \ No newline at end of file -- 2.39.2 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel