diff options
author | Axelen123 | 2022-01-02 14:53:06 +0100 |
---|---|---|
committer | Axelen123 | 2022-01-02 15:06:09 +0100 |
commit | abac075026037834721776323539bd55a64c45e3 (patch) | |
tree | 7c39ca4b162237320fc491b325c1ef4c097ecb05 | |
download | aur-abac075026037834721776323539bd55a64c45e3.tar.gz |
Initial commit
-rw-r--r-- | .SRCINFO | 69 | ||||
-rw-r--r-- | PKGBUILD | 190 | ||||
-rw-r--r-- | add-GRUB_COLOR_variables.patch | 41 | ||||
-rw-r--r-- | argon_1.patch | 56 | ||||
-rw-r--r-- | argon_2.patch | 52 | ||||
-rw-r--r-- | argon_3.patch | 2624 | ||||
-rw-r--r-- | argon_4.patch | 71 | ||||
-rw-r--r-- | argon_5.patch | 96 | ||||
-rw-r--r-- | detect-archlinux-initramfs.patch | 49 | ||||
-rw-r--r-- | grub-improved-luks2-git.install | 17 | ||||
-rw-r--r-- | grub-install_luks2.patch | 263 | ||||
-rw-r--r-- | grub.default | 57 | ||||
-rw-r--r-- | mm_1.patch | 87 | ||||
-rw-r--r-- | mm_2.patch | 89 | ||||
-rw-r--r-- | mm_3.patch | 99 | ||||
-rw-r--r-- | mm_4.patch | 101 | ||||
-rw-r--r-- | mm_5.patch | 85 | ||||
-rw-r--r-- | mm_6.patch | 81 |
18 files changed, 4127 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..cc822f16793a --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,69 @@ +pkgbase = grub-improved-luks2-git + pkgdesc = GNU GRand Unified Bootloader (2) with Argon2 and better LUKS2 support + pkgver = 2.06.r92.g246d69b7e + pkgrel = 1 + url = https://www.gnu.org/software/grub/ + install = grub-improved-luks2-git.install + arch = x86_64 + license = GPL3 + makedepends = autogen + makedepends = bdf-unifont + makedepends = git + makedepends = help2man + makedepends = python + makedepends = rsync + makedepends = texinfo + makedepends = ttf-dejavu + depends = device-mapper + depends = freetype2 + depends = fuse2 + depends = gettext + optdepends = dosfstools: For grub-mkrescue FAT FS and EFI support + optdepends = efibootmgr: For grub-install EFI support + optdepends = libisoburn: Provides xorriso for generating grub rescue iso using grub-mkrescue + optdepends = mtools: For grub-mkrescue FAT FS support + optdepends = os-prober: To detect other OSes when generating grub.cfg in BIOS systems + provides = grub + conflicts = grub + backup = etc/default/grub + backup = etc/grub.d/40_custom + source = grub::git+https://git.savannah.gnu.org/git/grub.git + source = grub-extras::git+https://git.savannah.gnu.org/git/grub-extras.git + source = gnulib::git+https://git.savannah.gnu.org/git/gnulib.git + source = argon_1.patch + source = argon_2.patch + source = argon_2.patch + source = argon_3.patch + source = argon_4.patch + source = argon_5.patch + source = mm_1.patch + source = mm_2.patch + source = mm_3.patch + source = mm_4.patch + source = mm_5.patch + source = mm_6.patch + source = grub-install_luks2.patch + source = add-GRUB_COLOR_variables.patch + source = detect-archlinux-initramfs.patch + source = grub.default + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = SKIP + sha256sums = 5dee6628c48eef79812bb9e86ee772068d85e7fcebbd2b2b8d1e19d24eda9dab + sha256sums = 580a81b00088773d554832b0d74c85bf16fec37728802973c45993bcb97cd7d5 + sha256sums = 791fadf182edf8d5bee4b45c008b08adce9689a9624971136527891a8f67d206 + +pkgname = grub-improved-luks2-git diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..dbadffbae0d8 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,190 @@ +# Maintainer: Ax333l +# Contributor: Llewelyn Trahaearn <WoefulDerelict [at] GMail [dot] com> +# Contributor: Tobias Powalowski <tpowa [at] archlinux [dot] org> +# Contributor: Ronald van Haren <ronald [at] archlinux [dot] org> +# Contributor: Keshav Amburay <(the ddoott ridikulus ddoott rat) (aatt) (gemmaeiil) (ddoott) (ccoomm)> + +## "1" to enable IA32-EFI build in Arch x86_64, "0" to disable +_ia32_efi_in_arch_x64="1" + +## "1" to enable EMU build, "0" to disable +_grub_emu_build="0" + +[[ "${CARCH}" == "x86_64" ]] && _target_arch="x86_64" +[[ "${CARCH}" == "i686" ]] && _target_arch="i386" + +_build_platforms="i386-pc ${_target_arch}-efi" +[[ "${CARCH}" == "x86_64" ]] && [[ "${_ia32_efi_in_arch_x64}" == "1" ]] && _build_platforms+=" i386-efi" +[[ "${_grub_emu_build}" == "1" ]] && _build_platforms+=" ${_target_arch}-emu" + +pkgname="grub-improved-luks2-git" +pkgver=2.06.r92.g246d69b7e +pkgrel=1 +pkgdesc="GNU GRand Unified Bootloader (2) with Argon2 and better LUKS2 support" +arch=('x86_64') +url="https://www.gnu.org/software/grub/" +license=('GPL3') +depends=('device-mapper' 'freetype2' 'fuse2' 'gettext') +makedepends=('autogen' 'bdf-unifont' 'git' 'help2man' + 'python' 'rsync' 'texinfo' 'ttf-dejavu') +optdepends=('dosfstools: For grub-mkrescue FAT FS and EFI support' + 'efibootmgr: For grub-install EFI support' + 'libisoburn: Provides xorriso for generating grub rescue iso using grub-mkrescue' + 'mtools: For grub-mkrescue FAT FS support' + 'os-prober: To detect other OSes when generating grub.cfg in BIOS systems') + +if [[ "${_grub_emu_build}" == "1" ]]; then + depends+=('sdl') + makedepends+=('libusb') + optdepends+=('libusb: For grub-emu USB support') +fi + +provides=("grub") +conflicts=("grub") +backup=('etc/default/grub' + 'etc/grub.d/40_custom') +install="${pkgname}.install" +source=("grub::git+https://git.savannah.gnu.org/git/grub.git" + "grub-extras::git+https://git.savannah.gnu.org/git/grub-extras.git" + "gnulib::git+https://git.savannah.gnu.org/git/gnulib.git" + 'argon_1.patch' + 'argon_2.patch' + 'argon_2.patch' + 'argon_3.patch' + 'argon_4.patch' + 'argon_5.patch' + 'mm_1.patch' + 'mm_2.patch' + 'mm_3.patch' + 'mm_4.patch' + 'mm_5.patch' + 'mm_6.patch' + 'grub-install_luks2.patch' + 'add-GRUB_COLOR_variables.patch' + 'detect-archlinux-initramfs.patch' + 'grub.default') +sha256sums=('SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP' + '5dee6628c48eef79812bb9e86ee772068d85e7fcebbd2b2b8d1e19d24eda9dab' + '580a81b00088773d554832b0d74c85bf16fec37728802973c45993bcb97cd7d5' + '791fadf182edf8d5bee4b45c008b08adce9689a9624971136527891a8f67d206') + +prepare() { + cd grub + + # Patch to enable GRUB_COLOR_* variables in grub-mkconfig. + # Based on http://lists.gnu.org/archive/html/grub-devel/2012-02/msg00021.html + patch -Np1 -i "$srcdir"/add-GRUB_COLOR_variables.patch + + # Patch grub-mkconfig to detect Arch Linux initramfs images. + patch -Np1 -i "$srcdir"/detect-archlinux-initramfs.patch + + # mm + patch -Np1 -i "$srcdir"/mm_1.patch + patch -Np1 -i "$srcdir"/mm_2.patch + patch -Np1 -i "$srcdir"/mm_3.patch + patch -Np1 -i "$srcdir"/mm_4.patch + patch -Np1 -i "$srcdir"/mm_5.patch + patch -Np1 -i "$srcdir"/mm_6.patch + + # argon2 + patch -Np1 -i "$srcdir"/argon_1.patch + patch -Np1 -i "$srcdir"/argon_2.patch + patch -Np1 -i "$srcdir"/argon_3.patch + patch -Np1 -i "$srcdir"/argon_4.patch + patch -Np1 -i "$srcdir"/argon_5.patch + + # make grub-install work with luks2 + patch -Np1 -i "$srcdir"/grub-install_luks2.patch + + # Fix DejaVuSans.ttf location so that grub-mkfont can create *.pf2 files for starfield theme. + sed 's|/usr/share/fonts/dejavu|/usr/share/fonts/dejavu /usr/share/fonts/TTF|g' -i "configure.ac" + + # Modify grub-mkconfig behaviour to silence warnings FS#36275 + sed 's| ro | rw |g' -i "util/grub.d/10_linux.in" + + # Modify grub-mkconfig behaviour so automatically generated entries read 'Arch Linux' FS#33393 + sed 's|GNU/Linux|Linux|' -i "util/grub.d/10_linux.in" + + # Pull in latest language files + ./linguas.sh + + # Remove lua module from grub-extras as it is incompatible with changes to grub_file_open + # http://git.savannah.gnu.org/cgit/grub.git/commit/?id=ca0a4f689a02c2c5a5e385f874aaaa38e151564e + rm -rf "$srcdir"/grub-extras/lua +} + +pkgver() { + cd grub + git describe --long --tags | sed 's/^grub.//;s/\([^-]*-g\)/r\1/;s/-/./g' +} + +build() { + cd grub + export GRUB_CONTRIB="$srcdir"/grub-extras + export GNULIB_SRCDIR="$srcdir"/gnulib + + # Undefined references to _GLOBAL_OFFSET_TABLE_ + CFLAGS=${CFLAGS/-fno-plt} + + ./bootstrap + + for _arch in $_build_platforms; do + mkdir "$srcdir"/grub/build_"$_arch" + cd "$srcdir"/grub/build_"$_arch" + + # * _FORTIFY_SOURCE requires compiling with optimization warnings + # become errors due to a -Werror added during ./configure tests. + # This results in an incorrect configuration and only by adding -O2 + # to CPPFLAGS does this problem seem to be worked around. + ../configure --with-platform="${_arch##*-}" \ + --target="${_arch%%-*}" \ + --prefix="/usr" \ + --sbindir="/usr/bin" \ + --sysconfdir="/etc" \ + --enable-boot-time \ + --enable-cache-stats \ + --enable-device-mapper \ + --enable-grub-mkfont \ + --enable-grub-mount \ + --enable-mm-debug \ + --enable-nls \ + --disable-silent-rules \ + --disable-werror \ + CPPFLAGS="$CPPFLAGS -O2" + make + done +} + +package() { + cd grub + + for _arch in $_build_platforms; do + cd "$srcdir"/grub/build_"$_arch" + make DESTDIR="$pkgdir" bashcompletiondir=/usr/share/bash-completion/completions install + done + + # Install /etc/default/grub (used by grub-mkconfig) + install -D -m0644 "$srcdir"/grub.default "$pkgdir"/etc/default/grub + + # Tidy up + find "$pkgdir"/usr/lib/grub \( -name '*.module' -o \ + -name '*.image' -o \ + -name 'kernel.exec' -o \ + -name 'gdb_grub' -o \ + -name 'gmodule.pl' \) -delete +} diff --git a/add-GRUB_COLOR_variables.patch b/add-GRUB_COLOR_variables.patch new file mode 100644 index 000000000000..867e8feeb7b9 --- /dev/null +++ b/add-GRUB_COLOR_variables.patch @@ -0,0 +1,41 @@ +From 21e5bcf22ab1a9f08c63e2a0212219d7482f77c1 Mon Sep 17 00:00:00 2001 +From: Christian Hesse <mail@eworm.de> +Date: Wed, 10 Mar 2021 18:42:25 +0100 +Subject: [PATCH] 00_header: add GRUB_COLOR_* variables +--- + util/grub-mkconfig.in | 2 ++ + util/grub.d/00_header.in | 8 ++++++++ + 2 files changed, 10 insertions(+) + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index f8cbb8d7a..1189d95f9 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -246,6 +246,8 @@ export GRUB_DEFAULT \ + GRUB_BACKGROUND \ + GRUB_THEME \ + GRUB_GFXPAYLOAD_LINUX \ ++ GRUB_COLOR_NORMAL \ ++ GRUB_COLOR_HIGHLIGHT \ + GRUB_INIT_TUNE \ + GRUB_SAVEDEFAULT \ + GRUB_ENABLE_CRYPTODISK \ +diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in +index 93a90233e..c5955df00 100644 +--- a/util/grub.d/00_header.in ++++ b/util/grub.d/00_header.in +@@ -125,6 +125,14 @@ cat <<EOF + + EOF + ++if [ x$GRUB_COLOR_NORMAL != x ] && [ x$GRUB_COLOR_HIGHLIGHT != x ] ; then ++ cat << EOF ++set menu_color_normal=$GRUB_COLOR_NORMAL ++set menu_color_highlight=$GRUB_COLOR_HIGHLIGHT ++ ++EOF ++fi ++ + serial=0; + gfxterm=0; + for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do diff --git a/argon_1.patch b/argon_1.patch new file mode 100644 index 000000000000..fe19861f800e --- /dev/null +++ b/argon_1.patch @@ -0,0 +1,56 @@ +--- + grub-core/kern/dl.c | 3 ++- + util/grub-module-verifierXX.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index 48f8a7907..7d395096f 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -467,7 +467,8 @@ grub_dl_check_license (grub_dl_t mod, El + + if (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0 +- || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0) ++ || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0 ++ || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=CC0") == 0) + return GRUB_ERR_NONE; + + return grub_error (GRUB_ERR_BAD_MODULE, +diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c +index ceb24309a..284f9026e 100644 +--- a/util/grub-module-verifierXX.c ++++ b/util/grub-module-verifierXX.c +@@ -157,7 +157,8 @@ check_license (const char * const filena + Elf_Shdr *s = find_section (arch, e, ".module_license"); + if (s && (strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3") == 0 + || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3+") == 0 +- || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv2+") == 0)) ++ || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv2+") == 0 ++ || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=CC0") == 0)) + return; + grub_util_error ("%s: incompatible license", filename); + } +-- +2.32.0 + + +The original PGP Signature. I had to modify the patch to apply it to the latest grub source code. +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEP4xMACgkQVbJhu7ck +PpRSTxAAo3leEk7U47GFerE4CBrrC3CZpkpXjoNdcYuEbvy8rhhZrFzt4+g+8s5w +z9BvXArf1G85XY4bvk61oeaLO7A52WOg5qpK3dKfcv6wZheq/MbjrE/JjcDNiLLc +yOW/dipv23hXDNRU4xWHchWw792lBcTfO5QqTDhQczTfaze4LLYFt0W7ySuV39ir +Q6FIZSLQPJFpH/lAjRJf5CjmDGzkuc6xg+km5NBQIKh695jKUv+H3oBGzmUfcd36 +Smv9cM7R7HuyU0y+Uc3nV6IU77H2+gGelvdodHpMPABiKrcsqiU3e347itmjTFRT +7Yy9iThh3biPO6dxzdVGw9BwKeM9fH0Dvja6rQxx1+NkeuM7YGBAlYIe6JV8kYRo +TtdjOUtixlfNuqwdYjFMwkAdQWaq0wCebQ9MvF9r0BuiH009u1dmGHHwen3yhzyO +xxvk1bsC0B4yjy+Wq5I2r3DZSfr10RensKYxuKyWMDKRSbI2mUk/5/JJDiZlfW+r +EIV73GAjURBM/kSS7Bo1MZmjuNcH5oXSJk4PfEOypK7xFbgPX0GM1hilJB1MZQC7 +T6EJwe1+WyHkAB5nVFqiPbUM7/xWw4LwQctjLBtJ9JW/+5n/rCAtkUIGOrQIedZg +r/lckIxn6ujrKwIu5Rh03eqTIrG5PZ7Uy8LdMut0IOALp25zO7o= +=w8r3 +-----END PGP SIGNATURE----- + + diff --git a/argon_2.patch b/argon_2.patch new file mode 100644 index 000000000000..40a4981f0c61 --- /dev/null +++ b/argon_2.patch @@ -0,0 +1,52 @@ +--- + include/grub/types.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/include/grub/types.h b/include/grub/types.h +index 0a3ff1591..13b0c46b3 100644 +--- a/include/grub/types.h ++++ b/include/grub/types.h +@@ -153,6 +153,7 @@ typedef grub_int32_t grub_ssize_t; + #define GRUB_SHRT_MAX 0x7fff + #define GRUB_SHRT_MIN (-GRUB_SHRT_MAX - 1) + #define GRUB_UINT_MAX 4294967295U ++#define GRUB_UINT32_MAX 4294967295U + #define GRUB_INT_MAX 0x7fffffff + #define GRUB_INT_MIN (-GRUB_INT_MAX - 1) + #define GRUB_INT32_MAX 2147483647 +@@ -174,6 +175,13 @@ typedef grub_int32_t grub_ssize_t; + #define GRUB_TYPE_U_MAX(type) ((unsigned long long)((typeof (type))(~0))) + #define GRUB_TYPE_U_MIN(type) 0ULL + ++# define GRUB_UINT32_C(x) x ## U ++# if GRUB_ULONG_MAX >> 31 >> 31 >> 1 == 1 ++# define GRUB_UINT64_C(x) x##UL ++# elif 1 ++# define GRUB_UINT64_C(x) x##ULL ++# endif ++ + typedef grub_uint64_t grub_properly_aligned_t; + + #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)] +-- +2.32.0 + + +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEP4xcACgkQVbJhu7ck +PpTcrA/+PqtqzLX54L1VYNehv8ilsLbLPLLJp6ov/sjDbKzFt/50Y1LGguTG81hF +DMjqk2NtF6FGZS494GzZyZDpNMzfEFTxEZdOsSzoq9EbuDILUZ/2UMCwmTbYX9Bd +2pZaI+ZeI+H7hI78CKAIAYRRz4dUuH0f7xnlpNzjk4XqE/2kkNwzbiwK+zhAb4Xw +zD9BfPnPqSF1YoOMGJ5nNYwEKaqRg9XRq+zim1ADQDIydt/qS3GFudlLddC2x5UR +umbP6EltWqn7jthHyK8aD924PvkiuVWlHa9kbn6ePkrkWpiXMYQyrfzlBjcoVRfw +wHE2X7LzBKTf0vgB8uCNY9rxpy44dBFXxEqknwLn1heLx7NbaRaylzdRmeDCSsDR +VlR8mF45BvLZwv4LrIT9Ok4cR3vGbYQjWs3eqCklH5R/GwDnlZnc6SwN1tdxZLk2 +om2cdTS/cfz/5qodKKQGjk9rZqOV4dHAi9SwxzpafmXFRUPEJOHuDoIGIeuAofLz +4RsiSDBVAYCq+qWdkye38Ei37WlzFBJvz3DHMDUAqsjw+IWorFJBeWAerL1viCNj +SDFBAT+QuLYJS0F2h3IIzCgVJAnXMKrCLEuruhoSw4duYjOQw0fMlXgrYX30VCx6 +xkdfrzE5Bh9jqr+igqqglaTD8OpF+dFMSWHTU9Ew+CtpbiLzN5c= +=YqYY +-----END PGP SIGNATURE----- + + diff --git a/argon_3.patch b/argon_3.patch new file mode 100644 index 000000000000..bc39630ffe82 --- /dev/null +++ b/argon_3.patch @@ -0,0 +1,2624 @@ +--- + docs/grub-dev.texi | 64 +++ + grub-core/Makefile.core.def | 8 + + grub-core/lib/argon2/LICENSE | 314 +++++++++++ + grub-core/lib/argon2/argon2.c | 232 ++++++++ + grub-core/lib/argon2/argon2.h | 264 +++++++++ + grub-core/lib/argon2/blake2/blake2-impl.h | 151 ++++++ + grub-core/lib/argon2/blake2/blake2.h | 89 +++ + grub-core/lib/argon2/blake2/blake2b.c | 388 ++++++++++++++ + .../lib/argon2/blake2/blamka-round-ref.h | 56 ++ + grub-core/lib/argon2/core.c | 506 ++++++++++++++++++ + grub-core/lib/argon2/core.h | 228 ++++++++ + grub-core/lib/argon2/ref.c | 190 +++++++ + 12 files changed, 2490 insertions(+) + create mode 100644 grub-core/lib/argon2/LICENSE + create mode 100644 grub-core/lib/argon2/argon2.c + create mode 100644 grub-core/lib/argon2/argon2.h + create mode 100644 grub-core/lib/argon2/blake2/blake2-impl.h + create mode 100644 grub-core/lib/argon2/blake2/blake2.h + create mode 100644 grub-core/lib/argon2/blake2/blake2b.c + create mode 100644 grub-core/lib/argon2/blake2/blamka-round-ref.h + create mode 100644 grub-core/lib/argon2/core.c + create mode 100644 grub-core/lib/argon2/core.h + create mode 100644 grub-core/lib/argon2/ref.c + +diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi +index 6c629a23e..ead2a8259 100644 +--- a/docs/grub-dev.texi ++++ b/docs/grub-dev.texi +@@ -490,11 +490,75 @@ GRUB includes some code from other projects, and it is sometimes necessary + to update it. + + @menu ++* Argon2:: + * Gnulib:: + * jsmn:: + * minilzo:: + @end menu + ++@node Argon2 ++@section Argon2 ++ ++Argon2 is a key derivation function used by LUKS2 in order to derive encryption ++keys from a user-provided password. GRUB imports the official reference ++implementation of Argon2 from @url{https://github.com/P-H-C/phc-winner-argon2}. ++In order to make the library usable for GRUB, we need to perform various ++conversions. This is mainly due to the fact that the imported code makes use of ++types and functions defined in the C standard library, which isn't available. ++Furthermore, using the POSIX wrapper library is not possible as the code needs ++to be part of the kernel. ++ ++Updating the code can thus be performed like following: ++ ++@example ++$ git clone https://github.com/P-H-C/phc-winner-argon2 argon2 ++$ cp argon2/include/argon2.h argon2/src/@{argon2.c,core.c,core.h,ref.c@} \ ++ grub-core/lib/argon2/ ++$ cp argon2/src/blake2/@{blake2-impl.h,blake2.h,blake2b.c,blamka-round-ref.h@} \ ++ grub-core/lib/argon2/blake2/ ++$ sed -e 's/UINT32_C/GRUB_UINT32_C/g' \ ++ -e 's/UINT64_C/GRUB_UINT64_C/g' \ ++ -e 's/UINT32_MAX/GRUB_UINT32_MAX/g' \ ++ -e 's/CHAR_BIT/GRUB_CHAR_BIT/g' \ ++ -e 's/UINT_MAX/GRUB_UINT_MAX/g' \ ++ -e 's/uintptr_t/grub_addr_t/g' \ ++ -e 's/size_t/grub_size_t/g' \ ++ -e 's/uint32_t/grub_uint32_t/g' \ ++ -e 's/uint64_t/grub_uint64_t/g' \ ++ -e 's/uint8_t/grub_uint8_t/g' \ ++ -e 's/memset/grub_memset/g' \ ++ -e 's/memcpy/grub_memcpy/g' \ ++ -e 's/malloc/grub_malloc/g' \ ++ -e 's/free/grub_free/g' \ ++ -e 's/#elif _MSC_VER/#elif defined(_MSC_VER)/' \ ++ grub-core/lib/argon2/@{*,blake2/*@}.@{c,h@} -i ++@end example ++ ++Afterwards, you need to perform the following manual steps: ++ ++@enumerate ++@item Remove all includes of standard library headers, "encoding.h" and ++ "thread.h". ++@item Add includes <grub/mm.h> and <grub/misc.h> to "argon2.h". ++@item Add include <grub/dl.h> and module license declaration to "argon2.c". ++@item Remove the following declarations and functions from "argon2.h" and ++ "argon2.c": argon2_type2string, argon2i_hash_encoded, argon2i_hash_raw, ++ argon2d_hash_encoded, argon2d_hash_raw, argon2id_hash_encoded, ++ argon2id_hash_raw, argon2_compare, argon2_verify, argon2i_verify, ++ argon2d_verify, argon2id_verify, argon2d_ctx, argon2i_ctx, argon2id_ctx, ++ argon2_verify_ctx, argon2d_verify_ctx, argon2i_verify_ctx, ++ argon2id_verify_ctx, argon2_encodedlen. ++@item Move the declaration of `clear_internal_memory()` in "blake2-impl.h" to ++ "blake2b.c". ++@item Remove code guarded by the ARGON2_NO_THREADS macro. ++@item Remove parameters `encoded` and `encodedlen` from `argon2_hash` and remove ++ the encoding block in that function. ++@item Remove parameter verifications in `validate_inputs()` for ++ ARGON2_MIN_PWD_LENGTH, ARGON2_MIN_SECRET, ARGON2_MIN_AD_LENGTH and ++ ARGON2_MAX_MEMORY to fix compiler warnings. ++@item Mark the function argon2_ctx as static. ++@end enumerate ++ + @node Gnulib + @section Gnulib + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 8022e1c0a..3a004e88c 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1174,6 +1174,14 @@ module = { + common = lib/json/json.c; + }; + ++module = { ++ name = argon2; ++ common = lib/argon2/argon2.c; ++ common = lib/argon2/core.c; ++ common = lib/argon2/ref.c; ++ common = lib/argon2/blake2/blake2b.c; ++}; ++ + module = { + name = afsplitter; + common = disk/AFSplitter.c; +diff --git a/grub-core/lib/argon2/LICENSE b/grub-core/lib/argon2/LICENSE +new file mode 100644 +index 000000000..fa611f7ac +--- /dev/null ++++ b/grub-core/lib/argon2/LICENSE +@@ -0,0 +1,314 @@ ++Argon2 reference source code package - reference C implementations ++ ++Copyright 2015 ++Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves ++ ++You may use this work under the terms of a Creative Commons CC0 1.0 ++License/Waiver or the Apache Public License 2.0, at your option. The terms of ++these licenses can be found at: ++ ++- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 ++- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 ++ ++The terms of the licenses are reproduced below. ++ ++-------------------------------------------------------------------------------- ++ ++Creative Commons Legal Code ++ ++CC0 1.0 Universal ++ ++ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE ++ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ++ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS ++ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES ++ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS ++ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ++ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED ++ HEREUNDER. ++ ++Statement of Purpose ++ ++The laws of most jurisdictions throughout the world automatically confer ++exclusive Copyright and Related Rights (defined below) upon the creator ++and subsequent owner(s) (each and all, an "owner") of an original work of ++authorship and/or a database (each, a "Work"). ++ ++Certain owners wish to permanently relinquish those rights to a Work for ++the purpose of contributing to a commons of creative, cultural and ++scientific works ("Commons") that the public can reliably and without fear ++of later claims of infringement build upon, modify, incorporate in other ++works, reuse and redistribute as freely as possible in any form whatsoever ++and for any purposes, including without limitation commercial purposes. ++These owners may contribute to the Commons to promote the ideal of a free ++culture and the further production of creative, cultural and scientific ++works, or to gain reputation or greater distribution for their Work in ++part through the use and efforts of others. ++ ++For these and/or other purposes and motivations, and without any ++expectation of additional consideration or compensation, the person ++associating CC0 with a Work (the "Affirmer"), to the extent that he or she ++is an owner of Copyright and Related Rights in the Work, voluntarily ++elects to apply CC0 to the Work and publicly distribute the Work under its ++terms, with knowledge of his or her Copyright and Related Rights in the ++Work and the meaning and intended legal effect of CC0 on those rights. ++ ++1. Copyright and Related Rights. A Work made available under CC0 may be ++protected by copyright and related or neighboring rights ("Copyright and ++Related Rights"). Copyright and Related Rights include, but are not ++limited to, the following: ++ ++ i. the right to reproduce, adapt, distribute, perform, display, ++ communicate, and translate a Work; ++ ii. moral rights retained by the original author(s) and/or performer(s); ++iii. publicity and privacy rights pertaining to a person's image or ++ likeness depicted in a Work; ++ iv. rights protecting against unfair competition in regards to a Work, ++ subject to the limitations in paragraph 4(a), below; ++ v. rights protecting the extraction, dissemination, use and reuse of data ++ in a Work; ++ vi. database rights (such as those arising under Directive 96/9/EC of the ++ European Parliament and of the Council of 11 March 1996 on the legal ++ protection of databases, and under any national implementation ++ thereof, including any amended or successor version of such ++ directive); and ++vii. other similar, equivalent or corresponding rights throughout the ++ world based on applicable law or treaty, and any national ++ implementations thereof. ++ ++2. Waiver. To the greatest extent permitted by, but not in contravention ++of, applicable law, Affirmer hereby overtly, fully, permanently, ++irrevocably and unconditionally waives, abandons, and surrenders all of ++Affirmer's Copyright and Related Rights and associated claims and causes ++of action, whether now known or unknown (including existing as well as ++future claims and causes of action), in the Work (i) in all territories ++worldwide, (ii) for the maximum duration provided by applicable law or ++treaty (including future time extensions), (iii) in any current or future ++medium and for any number of copies, and (iv) for any purpose whatsoever, ++including without limitation commercial, advertising or promotional ++purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each ++member of the public at large and to the detriment of Affirmer's heirs and ++successors, fully intending that such Waiver shall not be subject to ++revocation, rescission, cancellation, termination, or any other legal or ++equitable action to disrupt the quiet enjoyment of the Work by the public ++as contemplated by Affirmer's express Statement of Purpose. ++ ++3. Public License Fallback. Should any part of the Waiver for any reason ++be judged legally invalid or ineffective under applicable law, then the ++Waiver shall be preserved to the maximum extent permitted taking into ++account Affirmer's express Statement of Purpose. In addition, to the ++extent the Waiver is so judged Affirmer hereby grants to each affected ++person a royalty-free, non transferable, non sublicensable, non exclusive, ++irrevocable and unconditional license to exercise Affirmer's Copyright and ++Related Rights in the Work (i) in all territories worldwide, (ii) for the ++maximum duration provided by applicable law or treaty (including future ++time extensions), (iii) in any current or future medium and for any number ++of copies, and (iv) for any purpose whatsoever, including without ++limitation commercial, advertising or promotional purposes (the ++"License"). The License shall be deemed effective as of the date CC0 was ++applied by Affirmer to the Work. Should any part of the License for any ++reason be judged legally invalid or ineffective under applicable law, such ++partial invalidity or ineffectiveness shall not invalidate the remainder ++of the License, and in such case Affirmer hereby affirms that he or she ++will not (i) exercise any of his or her remaining Copyright and Related ++Rights in the Work or (ii) assert any associated claims and causes of ++action with respect to the Work, in either case contrary to Affirmer's ++express Statement of Purpose. ++ ++4. Limitations and Disclaimers. ++ ++ a. No trademark or patent rights held by Affirmer are waived, abandoned, ++ surrendered, licensed or otherwise affected by this document. ++ b. Affirmer offers the Work as-is and makes no representations or ++ warranties of any kind concerning the Work, express, implied, ++ statutory or otherwise, including without limitation warranties of ++ title, merchantability, fitness for a particular purpose, non ++ infringement, or the absence of latent or other defects, accuracy, or ++ the present or absence of errors, whether or not discoverable, all to ++ the greatest extent permissible under applicable law. ++ c. Affirmer disclaims responsibility for clearing rights of other persons ++ that may apply to the Work or any use thereof, including without ++ limitation any person's Copyright and Related Rights in the Work. ++ Further, Affirmer disclaims responsibility for obtaining any necessary ++ consents, permissions or other rights required for any use of the ++ Work. ++ d. Affirmer understands and acknowledges that Creative Commons is not a ++ party to this document and has no duty or obligation with respect to ++ this CC0 or use of the Work. ++ ++-------------------------------------------------------------------------------- ++ ++ Apache License ++ Version 2.0, January 2004 ++ http://www.apache.org/licenses/ ++ ++ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION ++ ++ 1. Definitions. ++ ++ "License" shall mean the terms and conditions for use, reproduction, ++ and distribution as defined by Sections 1 through 9 of this document. ++ ++ "Licensor" shall mean the copyright owner or entity authorized by ++ the copyright owner that is granting the License. ++ ++ "Legal Entity" shall mean the union of the acting entity and all ++ other entities that control, are controlled by, or are under common ++ control with that entity. For the purposes of this definition, ++ "control" means (i) the power, direct or indirect, to cause the ++ direction or management of such entity, whether by contract or ++ otherwise, or (ii) ownership of fifty percent (50%) or more of the ++ outstanding shares, or (iii) beneficial ownership of such entity. ++ ++ "You" (or "Your") shall mean an individual or Legal Entity ++ exercising permissions granted by this License. ++ ++ "Source" form shall mean the preferred form for making modifications, ++ including but not limited to software source code, documentation ++ source, and configuration files. ++ ++ "Object" form shall mean any form resulting from mechanical ++ transformation or translation of a Source form, including but ++ not limited to compiled object code, generated documentation, ++ and conversions to other media types. ++ ++ "Work" shall mean the work of authorship, whether in Source or ++ Object form, made available under the License, as indicated by a ++ copyright notice that is included in or attached to the work ++ (an example is provided in the Appendix below). ++ ++ "Derivative Works" shall mean any work, whether in Source or Object ++ form, that is based on (or derived from) the Work and for which the ++ editorial revisions, annotations, elaborations, or other modifications ++ represent, as a whole, an original work of authorship. For the purposes ++ of this License, Derivative Works shall not include works that remain ++ separable from, or merely link (or bind by name) to the interfaces of, ++ the Work and Derivative Works thereof. ++ ++ "Contribution" shall mean any work of authorship, including ++ the original version of the Work and any modifications or additions ++ to that Work or Derivative Works thereof, that is intentionally ++ submitted to Licensor for inclusion in the Work by the copyright owner ++ or by an individual or Legal Entity authorized to submit on behalf of ++ the copyright owner. For the purposes of this definition, "submitted" ++ means any form of electronic, verbal, or written communication sent ++ to the Licensor or its representatives, including but not limited to ++ communication on electronic mailing lists, source code control systems, ++ and issue tracking systems that are managed by, or on behalf of, the ++ Licensor for the purpose of discussing and improving the Work, but ++ excluding communication that is conspicuously marked or otherwise ++ designated in writing by the copyright owner as "Not a Contribution." ++ ++ "Contributor" shall mean Licensor and any individual or Legal Entity ++ on behalf of whom a Contribution has been received by Licensor and ++ subsequently incorporated within the Work. ++ ++ 2. Grant of Copyright License. Subject to the terms and conditions of ++ this License, each Contributor hereby grants to You a perpetual, ++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable ++ copyright license to reproduce, prepare Derivative Works of, ++ publicly display, publicly perform, sublicense, and distribute the ++ Work and such Derivative Works in Source or Object form. ++ ++ 3. Grant of Patent License. Subject to the terms and conditions of ++ this License, each Contributor hereby grants to You a perpetual, ++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable ++ (except as stated in this section) patent license to make, have made, ++ use, offer to sell, sell, import, and otherwise transfer the Work, ++ where such license applies only to those patent claims licensable ++ by such Contributor that are necessarily infringed by their ++ Contribution(s) alone or by combination of their Contribution(s) ++ with the Work to which such Contribution(s) was submitted. If You ++ institute patent litigation against any entity (including a ++ cross-claim or counterclaim in a lawsuit) alleging that the Work ++ or a Contribution incorporated within the Work constitutes direct ++ or contributory patent infringement, then any patent licenses ++ granted to You under this License for that Work shall terminate ++ as of the date such litigation is filed. ++ ++ 4. Redistribution. You may reproduce and distribute copies of the ++ Work or Derivative Works thereof in any medium, with or without ++ modifications, and in Source or Object form, provided that You ++ meet the following conditions: ++ ++ (a) You must give any other recipients of the Work or ++ Derivative Works a copy of this License; and ++ ++ (b) You must cause any modified files to carry prominent notices ++ stating that You changed the files; and ++ ++ (c) You must retain, in the Source form of any Derivative Works ++ that You distribute, all copyright, patent, trademark, and ++ attribution notices from the Source form of the Work, ++ excluding those notices that do not pertain to any part of ++ the Derivative Works; and ++ ++ (d) If the Work includes a "NOTICE" text file as part of its ++ distribution, then any Derivative Works that You distribute must ++ include a readable copy of the attribution notices contained ++ within such NOTICE file, excluding those notices that do not ++ pertain to any part of the Derivative Works, in at least one ++ of the following places: within a NOTICE text file distributed ++ as part of the Derivative Works; within the Source form or ++ documentation, if provided along with the Derivative Works; or, ++ within a display generated by the Derivative Works, if and ++ wherever such third-party notices normally appear. The contents ++ of the NOTICE file are for informational purposes only and ++ do not modify the License. You may add Your own attribution ++ notices within Derivative Works that You distribute, alongside ++ or as an addendum to the NOTICE text from the Work, provided ++ that such additional attribution notices cannot be construed ++ as modifying the License. ++ ++ You may add Your own copyright statement to Your modifications and ++ may provide additional or different license terms and conditions ++ for use, reproduction, or distribution of Your modifications, or ++ for any such Derivative Works as a whole, provided Your use, ++ reproduction, and distribution of the Work otherwise complies with ++ the conditions stated in this License. ++ ++ 5. Submission of Contributions. Unless You explicitly state otherwise, ++ any Contribution intentionally submitted for inclusion in the Work ++ by You to the Licensor shall be under the terms and conditions of ++ this License, without any additional terms or conditions. ++ Notwithstanding the above, nothing herein shall supersede or modify ++ the terms of any separate license agreement you may have executed ++ with Licensor regarding such Contributions. ++ ++ 6. Trademarks. This License does not grant permission to use the trade ++ names, trademarks, service marks, or product names of the Licensor, ++ except as required for reasonable and customary use in describing the ++ origin of the Work and reproducing the content of the NOTICE file. ++ ++ 7. Disclaimer of Warranty. Unless required by applicable law or ++ agreed to in writing, Licensor provides the Work (and each ++ Contributor provides its Contributions) on an "AS IS" BASIS, ++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ++ implied, including, without limitation, any warranties or conditions ++ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A ++ PARTICULAR PURPOSE. You are solely responsible for determining the ++ appropriateness of using or redistributing the Work and assume any ++ risks associated with Your exercise of permissions under this License. ++ ++ 8. Limitation of Liability. In no event and under no legal theory, ++ whether in tort (including negligence), contract, or otherwise, ++ unless required by applicable law (such as deliberate and grossly ++ negligent acts) or agreed to in writing, shall any Contributor be ++ liable to You for damages, including any direct, indirect, special, ++ incidental, or consequential damages of any character arising as a ++ result of this License or out of the use or inability to use the ++ Work (including but not limited to damages for loss of goodwill, ++ work stoppage, computer failure or malfunction, or any and all ++ other commercial damages or losses), even if such Contributor ++ has been advised of the possibility of such damages. ++ ++ 9. Accepting Warranty or Additional Liability. While redistributing ++ the Work or Derivative Works thereof, You may choose to offer, ++ and charge a fee for, acceptance of support, warranty, indemnity, ++ or other liability obligations and/or rights consistent with this ++ License. However, in accepting such obligations, You may act only ++ on Your own behalf and on Your sole responsibility, not on behalf ++ of any other Contributor, and only if You agree to indemnify, ++ defend, and hold each Contributor harmless for any liability ++ incurred by, or claims asserted against, such Contributor by reason ++ of your accepting any such warranty or additional liability. +diff --git a/grub-core/lib/argon2/argon2.c b/grub-core/lib/argon2/argon2.c +new file mode 100644 +index 000000000..49532fe80 +--- /dev/null ++++ b/grub-core/lib/argon2/argon2.c +@@ -0,0 +1,232 @@ ++/* ++ * Argon2 reference source code package - reference C implementations ++ * ++ * Copyright 2015 ++ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves ++ * ++ * You may use this work under the terms of a Creative Commons CC0 1.0 ++ * License/Waiver or the Apache Public License 2.0, at your option. The terms of ++ * these licenses can be found at: ++ * ++ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 ++ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * You should have received a copy of both of these licenses along with this ++ * software. If not, they may be obtained at the above URLs. ++ */ ++ ++#include <grub/dl.h> ++ ++#include "argon2.h" ++#include "core.h" ++ ++GRUB_MOD_LICENSE ("CC0"); ++ ++static int argon2_ctx(argon2_context *context, argon2_type type) { ++ /* 1. Validate all inputs */ ++ int result = validate_inputs(context); ++ grub_uint32_t memory_blocks, segment_length; ++ argon2_instance_t instance; ++ ++ if (ARGON2_OK != result) { ++ return result; ++ } ++ ++ if (Argon2_d != type && Argon2_i != type && Argon2_id != type) { ++ return ARGON2_INCORRECT_TYPE; ++ } ++ ++ /* 2. Align memory size */ ++ /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */ ++ memory_blocks = context->m_cost; ++ ++ if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) { ++ memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes; ++ } ++ ++ segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS); ++ /* Ensure that all segments have equal length */ ++ memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS); ++ ++ instance.version = context->version; ++ instance.memory = NULL; ++ instance.passes = context->t_cost; ++ instance.memory_blocks = memory_blocks; ++ instance.segment_length = segment_length; ++ instance.lane_length = segment_length * ARGON2_SYNC_POINTS; ++ instance.lanes = context->lanes; ++ instance.threads = context->threads; ++ instance.type = type; ++ ++ if (instance.threads > instance.lanes) { ++ instance.threads = instance.lanes; ++ } ++ ++ /* 3. Initialization: Hashing inputs, allocating memory, filling first ++ * blocks ++ */ ++ result = initialize(&instance, context); ++ ++ if (ARGON2_OK != result) { ++ return result; ++ } ++ ++ /* 4. Filling memory */ ++ result = fill_memory_blocks(&instance); ++ ++ if (ARGON2_OK != result) { ++ return result; ++ } ++ /* 5. Finalization */ ++ finalize(context, &instance); ++ ++ return ARGON2_OK; ++} ++ ++int argon2_hash(const grub_uint32_t t_cost, const grub_uint32_t m_cost, ++ const grub_uint32_t parallelism, const void *pwd, ++ const grub_size_t pwdlen, const void *salt, const grub_size_t saltlen, ++ void *hash, const grub_size_t hashlen, argon2_type type, ++ const grub_uint32_t version){ ++ ++ argon2_context context; ++ int result; ++ grub_uint8_t *out; ++ ++ if (pwdlen > ARGON2_MAX_PWD_LENGTH) { ++ return ARGON2_PWD_TOO_LONG; ++ } ++ ++ if (saltlen > ARGON2_MAX_SALT_LENGTH) { ++ return ARGON2_SALT_TOO_LONG; ++ } ++ ++ if (hashlen > ARGON2_MAX_OUTLEN) { ++ return ARGON2_OUTPUT_TOO_LONG; ++ } ++ ++ if (hashlen < ARGON2_MIN_OUTLEN) { ++ return ARGON2_OUTPUT_TOO_SHORT; ++ } ++ ++ out = grub_malloc(hashlen); ++ if (!out) { ++ return ARGON2_MEMORY_ALLOCATION_ERROR; ++ } ++ ++ context.out = (grub_uint8_t *)out; ++ context.outlen = (grub_uint32_t)hashlen; ++ context.pwd = CONST_CAST(grub_uint8_t *)pwd; ++ context.pwdlen = (grub_uint32_t)pwdlen; ++ context.salt = CONST_CAST(grub_uint8_t *)salt; ++ context.saltlen = (grub_uint32_t)saltlen; ++ context.secret = NULL; ++ context.secretlen = 0; ++ context.ad = NULL; ++ context.adlen = 0; ++ context.t_cost = t_cost; ++ context.m_cost = m_cost; ++ context.lanes = parallelism; ++ context.threads = parallelism; ++ context.allocate_cbk = NULL; ++ context.grub_free_cbk = NULL; ++ context.flags = ARGON2_DEFAULT_FLAGS; ++ context.version = version; ++ ++ result = argon2_ctx(&context, type); ++ ++ if (result != ARGON2_OK) { ++ clear_internal_memory(out, hashlen); ++ grub_free(out); ++ return result; ++ } ++ ++ /* if raw hash requested, write it */ ++ if (hash) { ++ grub_memcpy(hash, out, hashlen); ++ } ++ ++ clear_internal_memory(out, hashlen); ++ grub_free(out); ++ ++ return ARGON2_OK; ++} ++ ++const char *argon2_error_message(int error_code) { ++ switch (error_code) { ++ case ARGON2_OK: ++ return "OK"; ++ case ARGON2_OUTPUT_PTR_NULL: ++ return "Output pointer is NULL"; ++ case ARGON2_OUTPUT_TOO_SHORT: ++ return "Output is too short"; ++ case ARGON2_OUTPUT_TOO_LONG: ++ return "Output is too long"; ++ case ARGON2_PWD_TOO_SHORT: ++ return "Password is too short"; ++ case ARGON2_PWD_TOO_LONG: ++ return "Password is too long"; ++ case ARGON2_SALT_TOO_SHORT: ++ return "Salt is too short"; ++ case ARGON2_SALT_TOO_LONG: ++ return "Salt is too long"; ++ case ARGON2_AD_TOO_SHORT: ++ return "Associated data is too short"; ++ case ARGON2_AD_TOO_LONG: ++ return "Associated data is too long"; ++ case ARGON2_SECRET_TOO_SHORT: ++ return "Secret is too short"; ++ case ARGON2_SECRET_TOO_LONG: ++ return "Secret is too long"; ++ case ARGON2_TIME_TOO_SMALL: ++ return "Time cost is too small"; ++ case ARGON2_TIME_TOO_LARGE: ++ return "Time cost is too large"; ++ case ARGON2_MEMORY_TOO_LITTLE: ++ return "Memory cost is too small"; ++ case ARGON2_MEMORY_TOO_MUCH: ++ return "Memory cost is too large"; ++ case ARGON2_LANES_TOO_FEW: ++ return "Too few lanes"; ++ case ARGON2_LANES_TOO_MANY: ++ return "Too many lanes"; ++ case ARGON2_PWD_PTR_MISMATCH: ++ return "Password pointer is NULL, but password length is not 0"; ++ case ARGON2_SALT_PTR_MISMATCH: ++ return "Salt pointer is NULL, but salt length is not 0"; ++ case ARGON2_SECRET_PTR_MISMATCH: ++ return "Secret pointer is NULL, but secret length is not 0"; ++ case ARGON2_AD_PTR_MISMATCH: ++ return "Associated data pointer is NULL, but ad length is not 0"; ++ case ARGON2_MEMORY_ALLOCATION_ERROR: ++ return "Memory allocation error"; ++ case ARGON2_FREE_MEMORY_CBK_NULL: ++ return "The grub_free memory callback is NULL"; ++ case ARGON2_ALLOCATE_MEMORY_CBK_NULL: ++ return "The allocate memory callback is NULL"; ++ case ARGON2_INCORRECT_PARAMETER: ++ return "Argon2_Context context is NULL"; ++ case ARGON2_INCORRECT_TYPE: ++ return "There is no such version of Argon2"; ++ case ARGON2_OUT_PTR_MISMATCH: ++ return "Output pointer mismatch"; ++ case ARGON2_THREADS_TOO_FEW: ++ return "Not enough threads"; ++ case ARGON2_THREADS_TOO_MANY: ++ return "Too many threads"; ++ case ARGON2_MISSING_ARGS: ++ return "Missing arguments"; ++ case ARGON2_ENCODING_FAIL: ++ return "Encoding failed"; ++ case ARGON2_DECODING_FAIL: ++ return "Decoding failed"; ++ case ARGON2_THREAD_FAIL: ++ return "Threading failure"; ++ case ARGON2_DECODING_LENGTH_FAIL: ++ return "Some of encoded parameters are too long or too short"; ++ case ARGON2_VERIFY_MISMATCH: ++ return "The password does not match the supplied hash"; ++ default: ++ return "Unknown error code"; ++ } ++} +diff --git a/grub-core/lib/argon2/argon2.h b/grub-core/lib/argon2/argon2.h +new file mode 100644 +index 000000000..129f7efbd +--- /dev/null ++++ b/grub-core/lib/argon2/argon2.h +@@ -0,0 +1,264 @@ ++/* ++ * Argon2 reference source code package - reference C implementations ++ * ++ * Copyright 2015 ++ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves ++ * ++ * You may use this work under the terms of a Creative Commons CC0 1.0 ++ * License/Waiver or the Apache Public License 2.0, at your option. The terms of ++ * these licenses can be found at: ++ * ++ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 ++ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * You should have received a copy of both of these licenses along with this ++ * software. If not, they may be obtained at the above URLs. ++ */ ++ ++#ifndef ARGON2_H ++#define ARGON2_H ++ ++#include <grub/misc.h> ++#include <grub/mm.h> ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++/* Symbols visibility control */ ++#ifdef A2_VISCTL ++#define ARGON2_PUBLIC __attribute__((visibility("default"))) ++#define ARGON2_LOCAL __attribute__ ((visibility ("hidden"))) ++#elif defined(_MSC_VER) ++#define ARGON2_PUBLIC __declspec(dllexport) ++#define ARGON2_LOCAL ++#else ++#define ARGON2_PUBLIC ++#define ARGON2_LOCAL ++#endif ++ ++/* ++ * Argon2 input parameter restrictions ++ */ ++ ++/* Minimum and maximum number of lanes (degree of parallelism) */ ++#define ARGON2_MIN_LANES GRUB_UINT32_C(1) ++#define ARGON2_MAX_LANES GRUB_UINT32_C(0xFFFFFF) ++ ++/* Minimum and maximum number of threads */ ++#define ARGON2_MIN_THREADS GRUB_UINT32_C(1) ++#define ARGON2_MAX_THREADS GRUB_UINT32_C(0xFFFFFF) ++ ++/* Number of synchronization points between lanes per pass */ ++#define ARGON2_SYNC_POINTS GRUB_UINT32_C(4) ++ ++/* Minimum and maximum digest size in bytes */ ++#define ARGON2_MIN_OUTLEN GRUB_UINT32_C(4) ++#define ARGON2_MAX_OUTLEN GRUB_UINT32_C(0xFFFFFFFF) ++ ++/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */ ++#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */ ++ ++#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b)) ++/* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */ ++#define ARGON2_MAX_MEMORY_BITS \ ++ ARGON2_MIN(GRUB_UINT32_C(32), (sizeof(void *) * GRUB_CHAR_BIT - 10 - 1)) ++#define ARGON2_MAX_MEMORY \ ++ ARGON2_MIN(GRUB_UINT32_C(0xFFFFFFFF), GRUB_UINT64_C(1) << ARGON2_MAX_MEMORY_BITS) ++ ++/* Minimum and maximum number of passes */ ++#define ARGON2_MIN_TIME GRUB_UINT32_C(1) ++#define ARGON2_MAX_TIME GRUB_UINT32_C(0xFFFFFFFF) ++ ++/* Minimum and maximum password length in bytes */ ++#define ARGON2_MIN_PWD_LENGTH GRUB_UINT32_C(0) ++#define ARGON2_MAX_PWD_LENGTH GRUB_UINT32_C(0xFFFFFFFF) ++ ++/* Minimum and maximum associated data length in bytes */ ++#define ARGON2_MIN_AD_LENGTH GRUB_UINT32_C(0) ++#define ARGON2_MAX_AD_LENGTH GRUB_UINT32_C(0xFFFFFFFF) ++ ++/* Minimum and maximum salt length in bytes */ ++#define ARGON2_MIN_SALT_LENGTH GRUB_UINT32_C(8) ++#define ARGON2_MAX_SALT_LENGTH GRUB_UINT32_C(0xFFFFFFFF) ++ ++/* Minimum and maximum key length in bytes */ ++#define ARGON2_MIN_SECRET GRUB_UINT32_C(0) ++#define ARGON2_MAX_SECRET GRUB_UINT32_C(0xFFFFFFFF) ++ ++/* Flags to determine which fields are securely wiped (default = no wipe). */ ++#define ARGON2_DEFAULT_FLAGS GRUB_UINT32_C(0) ++#define ARGON2_FLAG_CLEAR_PASSWORD (GRUB_UINT32_C(1) << 0) ++#define ARGON2_FLAG_CLEAR_SECRET (GRUB_UINT32_C(1) << 1) ++ ++/* Global flag to determine if we are wiping internal memory buffers. This flag ++ * is defined in core.c and defaults to 1 (wipe internal memory). */ ++extern int FLAG_clear_internal_memory; ++ ++/* Error codes */ ++typedef enum Argon2_ErrorCodes { ++ ARGON2_OK = 0, ++ ++ ARGON2_OUTPUT_PTR_NULL = -1, ++ ++ ARGON2_OUTPUT_TOO_SHORT = -2, ++ ARGON2_OUTPUT_TOO_LONG = -3, ++ ++ ARGON2_PWD_TOO_SHORT = -4, ++ ARGON2_PWD_TOO_LONG = -5, ++ ++ ARGON2_SALT_TOO_SHORT = -6, ++ ARGON2_SALT_TOO_LONG = -7, ++ ++ ARGON2_AD_TOO_SHORT = -8, ++ ARGON2_AD_TOO_LONG = -9, ++ ++ ARGON2_SECRET_TOO_SHORT = -10, ++ ARGON2_SECRET_TOO_LONG = -11, ++ ++ ARGON2_TIME_TOO_SMALL = -12, ++ ARGON2_TIME_TOO_LARGE = -13, ++ ++ ARGON2_MEMORY_TOO_LITTLE = -14, ++ ARGON2_MEMORY_TOO_MUCH = -15, ++ ++ ARGON2_LANES_TOO_FEW = -16, ++ ARGON2_LANES_TOO_MANY = -17, ++ ++ ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */ ++ ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */ ++ ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */ ++ ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */ ++ ++ ARGON2_MEMORY_ALLOCATION_ERROR = -22, ++ ++ ARGON2_FREE_MEMORY_CBK_NULL = -23, ++ ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24, ++ ++ ARGON2_INCORRECT_PARAMETER = -25, ++ ARGON2_INCORRECT_TYPE = -26, ++ ++ ARGON2_OUT_PTR_MISMATCH = -27, ++ ++ ARGON2_THREADS_TOO_FEW = -28, ++ ARGON2_THREADS_TOO_MANY = -29, ++ ++ ARGON2_MISSING_ARGS = -30, ++ ++ ARGON2_ENCODING_FAIL = -31, ++ ++ ARGON2_DECODING_FAIL = -32, ++ ++ ARGON2_THREAD_FAIL = -33, ++ ++ ARGON2_DECODING_LENGTH_FAIL = -34, ++ ++ ARGON2_VERIFY_MISMATCH = -35 ++} argon2_error_codes; ++ ++/* Memory allocator types --- for external allocation */ ++typedef int (*allocate_fptr)(grub_uint8_t **memory, grub_size_t bytes_to_allocate); ++typedef void (*deallocate_fptr)(grub_uint8_t *memory, grub_size_t bytes_to_allocate); ++ ++/* Argon2 external data structures */ ++ ++/* ++ ***** ++ * Context: structure to hold Argon2 inputs: ++ * output array and its length, ++ * password and its length, ++ * salt and its length, ++ * secret and its length, ++ * associated data and its length, ++ * number of passes, amount of used memory (in KBytes, can be rounded up a bit) ++ * number of parallel threads that will be run. ++ * All the parameters above affect the output hash value. ++ * Additionally, two function pointers can be provided to allocate and ++ * deallocate the memory (if NULL, memory will be allocated internally). ++ * Also, three flags indicate whether to erase password, secret as soon as they ++ * are pre-hashed (and thus not needed anymore), and the entire memory ++ ***** ++ * Simplest situation: you have output array out[8], password is stored in ++ * pwd[32], salt is stored in salt[16], you do not have keys nor associated ++ * data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with ++ * 4 parallel lanes. ++ * You want to erase the password, but you're OK with last pass not being ++ * erased. You want to use the default memory allocator. ++ * Then you initialize: ++ Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false) ++ */ ++typedef struct Argon2_Context { ++ grub_uint8_t *out; /* output array */ ++ grub_uint32_t outlen; /* digest length */ ++ ++ grub_uint8_t *pwd; /* password array */ ++ grub_uint32_t pwdlen; /* password length */ ++ ++ grub_uint8_t *salt; /* salt array */ ++ grub_uint32_t saltlen; /* salt length */ ++ ++ grub_uint8_t *secret; /* key array */ ++ grub_uint32_t secretlen; /* key length */ ++ ++ grub_uint8_t *ad; /* associated data array */ ++ grub_uint32_t adlen; /* associated data length */ ++ ++ grub_uint32_t t_cost; /* number of passes */ ++ grub_uint32_t m_cost; /* amount of memory requested (KB) */ ++ grub_uint32_t lanes; /* number of lanes */ ++ grub_uint32_t threads; /* maximum number of threads */ ++ ++ grub_uint32_t version; /* version number */ ++ ++ allocate_fptr allocate_cbk; /* pointer to memory allocator */ ++ deallocate_fptr grub_free_cbk; /* pointer to memory deallocator */ ++ ++ grub_uint32_t flags; /* array of bool options */ ++} argon2_context; ++ ++/* Argon2 primitive type */ ++typedef enum Argon2_type { ++ Argon2_d = 0, ++ Argon2_i = 1, ++ Argon2_id = 2 ++} argon2_type; ++ ++/* Version of the algorithm */ ++typedef enum Argon2_version { ++ ARGON2_VERSION_10 = 0x10, ++ ARGON2_VERSION_13 = 0x13, ++ ARGON2_VERSION_NUMBER = ARGON2_VERSION_13 ++} argon2_version; ++ ++/** ++ * Hashes a password with Argon2, producing a raw hash at @hash ++ * @param t_cost Number of iterations ++ * @param m_cost Sets memory usage to m_cost kibibytes ++ * @param parallelism Number of threads and compute lanes ++ * @param pwd Pointer to password ++ * @param pwdlen Password size in bytes ++ * @param salt Pointer to salt ++ * @param saltlen Salt size in bytes ++ * @param hash Buffer where to write the raw hash - updated by the function ++ * @param hashlen Desired length of the hash in bytes ++ * @pre Different parallelism levels will give different results ++ * @pre Returns ARGON2_OK if successful ++ */ ++ARGON2_PUBLIC int argon2_hash(const grub_uint32_t t_cost, const grub_uint32_t m_cost, ++ const grub_uint32_t parallelism, const void *pwd, ++ const grub_size_t pwdlen, const void *salt, ++ const grub_size_t saltlen, void *hash, ++ const grub_size_t hashlen, argon2_type type, ++ const grub_uint32_t version); ++ ++/** ++ * Get the associated error message for given error code ++ * @return The error message associated with the given error code ++ */ ++ARGON2_PUBLIC const char *argon2_error_message(int error_code); ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#endif +diff --git a/grub-core/lib/argon2/blake2/blake2-impl.h b/grub-core/lib/argon2/blake2/blake2-impl.h +new file mode 100644 +index 000000000..3a795680b +--- /dev/null ++++ b/grub-core/lib/argon2/blake2/blake2-impl.h +@@ -0,0 +1,151 @@ ++/* ++ * Argon2 reference source code package - reference C implementations ++ * ++ * Copyright 2015 ++ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves ++ * ++ * You may use this work under the terms of a Creative Commons CC0 1.0 ++ * License/Waiver or the Apache Public License 2.0, at your option. The terms of ++ * these licenses can be found at: ++ * ++ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 ++ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * You should have received a copy of both of these licenses along with this ++ * software. If not, they may be obtained at the above URLs. ++ */ ++ ++#ifndef PORTABLE_BLAKE2_IMPL_H ++#define PORTABLE_BLAKE2_IMPL_H ++ ++#if defined(_MSC_VER) ++#define BLAKE2_INLINE __inline ++#elif defined(__GNUC__) || defined(__clang__) ++#define BLAKE2_INLINE __inline__ ++#else ++#define BLAKE2_INLINE ++#endif ++ ++/* Argon2 Team - Begin Code */ ++/* ++ Not an exhaustive list, but should cover the majority of modern platforms ++ Additionally, the code will always be correct---this is only a performance ++ tweak. ++*/ ++#if (defined(__BYTE_ORDER__) && \ ++ (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || \ ++ defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \ ++ defined(__AARCH64EL__) || defined(__amd64__) || defined(__i386__) || \ ++ defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || \ ++ defined(_M_ARM) ++#define NATIVE_LITTLE_ENDIAN ++#endif ++/* Argon2 Team - End Code */ ++ ++static BLAKE2_INLINE grub_uint32_t load32(const void *src) { ++#if defined(NATIVE_LITTLE_ENDIAN) ++ grub_uint32_t w; ++ grub_memcpy(&w, src, sizeof w); ++ return w; ++#else ++ const grub_uint8_t *p = (const grub_uint8_t *)src; ++ grub_uint32_t w = *p++; ++ w |= (grub_uint32_t)(*p++) << 8; ++ w |= (grub_uint32_t)(*p++) << 16; ++ w |= (grub_uint32_t)(*p++) << 24; ++ return w; ++#endif ++} ++ ++static BLAKE2_INLINE grub_uint64_t load64(const void *src) { ++#if defined(NATIVE_LITTLE_ENDIAN) ++ grub_uint64_t w; ++ grub_memcpy(&w, src, sizeof w); ++ return w; ++#else ++ const grub_uint8_t *p = (const grub_uint8_t *)src; ++ grub_uint64_t w = *p++; ++ w |= (grub_uint64_t)(*p++) << 8; ++ w |= (grub_uint64_t)(*p++) << 16; ++ w |= (grub_uint64_t)(*p++) << 24; ++ w |= (grub_uint64_t)(*p++) << 32; ++ w |= (grub_uint64_t)(*p++) << 40; ++ w |= (grub_uint64_t)(*p++) << 48; ++ w |= (grub_uint64_t)(*p++) << 56; ++ return w; ++#endif ++} ++ ++static BLAKE2_INLINE void store32(void *dst, grub_uint32_t w) { ++#if defined(NATIVE_LITTLE_ENDIAN) ++ grub_memcpy(dst, &w, sizeof w); ++#else ++ grub_uint8_t *p = (grub_uint8_t *)dst; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++#endif ++} ++ ++static BLAKE2_INLINE void store64(void *dst, grub_uint64_t w) { ++#if defined(NATIVE_LITTLE_ENDIAN) ++ grub_memcpy(dst, &w, sizeof w); ++#else ++ grub_uint8_t *p = (grub_uint8_t *)dst; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++#endif ++} ++ ++static BLAKE2_INLINE grub_uint64_t load48(const void *src) { ++ const grub_uint8_t *p = (const grub_uint8_t *)src; ++ grub_uint64_t w = *p++; ++ w |= (grub_uint64_t)(*p++) << 8; ++ w |= (grub_uint64_t)(*p++) << 16; ++ w |= (grub_uint64_t)(*p++) << 24; ++ w |= (grub_uint64_t)(*p++) << 32; ++ w |= (grub_uint64_t)(*p++) << 40; ++ return w; ++} ++ ++static BLAKE2_INLINE void store48(void *dst, grub_uint64_t w) { ++ grub_uint8_t *p = (grub_uint8_t *)dst; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++ w >>= 8; ++ *p++ = (grub_uint8_t)w; ++} ++ ++static BLAKE2_INLINE grub_uint32_t rotr32(const grub_uint32_t w, const unsigned c) { ++ return (w >> c) | (w << (32 - c)); ++} ++ ++static BLAKE2_INLINE grub_uint64_t rotr64(const grub_uint64_t w, const unsigned c) { ++ return (w >> c) | (w << (64 - c)); ++} ++ ++#endif +diff --git a/grub-core/lib/argon2/blake2/blake2.h b/grub-core/lib/argon2/blake2/blake2.h +new file mode 100644 +index 000000000..4e8efeb22 +--- /dev/null ++++ b/grub-core/lib/argon2/blake2/blake2.h +@@ -0,0 +1,89 @@ ++/* ++ * Argon2 reference source code package - reference C implementations ++ * ++ * Copyright 2015 ++ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves ++ * ++ * You may use this work under the terms of a Creative Commons CC0 1.0 ++ * License/Waiver or the Apache Public License 2.0, at your option. The terms of ++ * these licenses can be found at: ++ * ++ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 ++ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * You should have received a copy of both of these licenses along with this ++ * software. If not, they may be obtained at the above URLs. ++ */ ++ ++#ifndef PORTABLE_BLAKE2_H ++#define PORTABLE_BLAKE2_H ++ ++#include "../argon2.h" ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++enum blake2b_constant { ++ BLAKE2B_BLOCKBYTES = 128, ++ BLAKE2B_OUTBYTES = 64, ++ BLAKE2B_KEYBYTES = 64, ++ BLAKE2B_SALTBYTES = 16, ++ BLAKE2B_PERSONALBYTES = 16 ++}; ++ ++#pragma pack(push, 1) ++typedef struct __blake2b_param { ++ grub_uint8_t digest_length; /* 1 */ ++ grub_uint8_t key_length; /* 2 */ ++ grub_uint8_t fanout; /* 3 */ ++ grub_uint8_t depth; /* 4 */ ++ grub_uint32_t leaf_length; /* 8 */ ++ grub_uint64_t node_offset; /* 16 */ ++ grub_uint8_t node_depth; /* 17 */ ++ grub_uint8_t inner_length; /* 18 */ ++ grub_uint8_t reserved[14]; /* 32 */ ++ grub_uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ ++ grub_uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ ++} blake2b_param; ++#pragma pack(pop) ++ ++typedef struct __blake2b_state { ++ grub_uint64_t h[8]; ++ grub_uint64_t t[2]; ++ grub_uint64_t f[2]; ++ grub_uint8_t buf[BLAKE2B_BLOCKBYTES]; ++ unsigned buflen; ++ unsigned outlen; ++ grub_uint8_t last_node; ++} blake2b_state; ++ ++/* Ensure param structs have not been wrongly padded */ ++/* Poor man's static_assert */ ++enum { ++ blake2_size_check_0 = 1 / !!(GRUB_CHAR_BIT == 8), ++ blake2_size_check_2 = ++ 1 / !!(sizeof(blake2b_param) == sizeof(grub_uint64_t) * GRUB_CHAR_BIT) ++}; ++ ++/* Streaming API */ ++ARGON2_LOCAL int blake2b_init(blake2b_state *S, grub_size_t outlen); ++ARGON2_LOCAL int blake2b_init_key(blake2b_state *S, grub_size_t outlen, const void *key, ++ grub_size_t keylen); ++ARGON2_LOCAL int blake2b_init_param(blake2b_state *S, const blake2b_param *P); ++ARGON2_LOCAL int blake2b_update(blake2b_state *S, const void *in, grub_size_t inlen); ++ARGON2_LOCAL int blake2b_final(blake2b_state *S, void *out, grub_size_t outlen); ++ ++/* Simple API */ ++ARGON2_LOCAL int blake2b(void *out, grub_size_t outlen, const void *in, grub_size_t inlen, ++ const void *key, grub_size_t keylen); ++ ++/* Argon2 Team - Begin Code */ ++ARGON2_LOCAL int blake2b_long(void *out, grub_size_t outlen, const void *in, grub_size_t inlen); ++/* Argon2 Team - End Code */ ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#endif +diff --git a/grub-core/lib/argon2/blake2/blake2b.c b/grub-core/lib/argon2/blake2/blake2b.c +new file mode 100644 +index 000000000..53abd7bef +--- /dev/null ++++ b/grub-core/lib/argon2/blake2/blake2b.c +@@ -0,0 +1,388 @@ ++/* ++ * Argon2 reference source code package - reference C implementations ++ * ++ * Copyright 2015 ++ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves ++ * ++ * You may use this work under the terms of a Creative Commons CC0 1.0 ++ * License/Waiver or the Apache Public License 2.0, at your option. The terms of ++ * these licenses can be found at: ++ * ++ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 ++ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * You should have received a copy of both of these licenses along with this ++ * software. If not, they may be obtained at the above URLs. ++ */ ++ ++#include "blake2.h" ++#include "blake2-impl.h" ++ ++static const grub_uint64_t blake2b_IV[8] = { ++ GRUB_UINT64_C(0x6a09e667f3bcc908), GRUB_UINT64_C(0xbb67ae8584caa73b), ++ GRUB_UINT64_C(0x3c6ef372fe94f82b), GRUB_UINT64_C(0xa54ff53a5f1d36f1), ++ GRUB_UINT64_C(0x510e527fade682d1), GRUB_UINT64_C(0x9b05688c2b3e6c1f), ++ GRUB_UINT64_C(0x1f83d9abfb41bd6b), GRUB_UINT64_C(0x5be0cd19137e2179)}; ++ ++static const unsigned int blake2b_sigma[12][16] = { ++ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, ++ {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, ++ {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, ++ {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, ++ {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, ++ {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, ++ {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, ++ {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, ++ {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, ++ {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}, ++ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, ++ {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, ++}; ++ ++void clear_internal_memory(void *v, grub_size_t n); ++ ++static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) { ++ S->f[1] = (grub_uint64_t)-1; ++} ++ ++static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) { ++ if (S->last_node) { ++ blake2b_set_lastnode(S); ++ } ++ S->f[0] = (grub_uint64_t)-1; ++} ++ ++static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S, ++ grub_uint64_t inc) { ++ S->t[0] += inc; ++ S->t[1] += (S->t[0] < inc); ++} ++ ++static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) { ++ clear_internal_memory(S, sizeof(*S)); /* wipe */ ++ blake2b_set_lastblock(S); /* invalidate for further use */ ++} ++ ++static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) { ++ grub_memset(S, 0, sizeof(*S)); ++ grub_memcpy(S->h, blake2b_IV, sizeof(S->h)); ++} ++ ++int blake2b_init_param(blake2b_state *S, const blake2b_param *P) { ++ const unsigned char *p = (const unsigned char *)P; ++ unsigned int i; ++ ++ if (NULL == P || NULL == S) { ++ return -1; ++ } ++ ++ blake2b_init0(S); ++ /* IV XOR Parameter Block */ ++ for (i = 0; i < 8; ++i) { ++ S->h[i] ^= load64(&p[i * sizeof(S->h[i])]); ++ } ++ S->outlen = P->digest_length; ++ return 0; ++} ++ ++/* Sequential blake2b initialization */ ++int blake2b_init(blake2b_state *S, grub_size_t outlen) { ++ blake2b_param P; ++ ++ if (S == NULL) { ++ return -1; ++ } ++ ++ if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) { ++ blake2b_invalidate_state(S); ++ return -1; ++ } ++ ++ /* Setup Parameter Block for unkeyed BLAKE2 */ ++ P.digest_length = (grub_uint8_t)outlen; ++ P.key_length = 0; ++ P.fanout = 1; ++ P.depth = 1; ++ P.leaf_length = 0; ++ P.node_offset = 0; ++ P.node_depth = 0; ++ P.inner_length = 0; ++ grub_memset(P.reserved, 0, sizeof(P.reserved)); ++ grub_memset(P.salt, 0, sizeof(P.salt)); ++ grub_memset(P.personal, 0, sizeof(P.personal)); ++ ++ return blake2b_init_param(S, &P); ++} ++ ++int blake2b_init_key(blake2b_state *S, grub_size_t outlen, const void *key, ++ grub_size_t keylen) { ++ blake2b_param P; ++ ++ if (S == NULL) { ++ return -1; ++ } ++ ++ if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) { ++ blake2b_invalidate_state(S); ++ return -1; ++ } ++ ++ if ((key == 0) || (keylen == 0) || (keylen > BLAKE2B_KEYBYTES)) { ++ blake2b_invalidate_state(S); ++ return -1; ++ } ++ ++ /* Setup Parameter Block for keyed BLAKE2 */ ++ P.digest_length = (grub_uint8_t)outlen; ++ P.key_length = (grub_uint8_t)keylen; ++ P.fanout = 1; ++ P.depth = 1; ++ P.leaf_length = 0; ++ P.node_offset = 0; ++ P.node_depth = 0; ++ P.inner_length = 0; ++ grub_memset(P.reserved, 0, sizeof(P.reserved)); ++ grub_memset(P.salt, 0, sizeof(P.salt)); ++ grub_memset(P.personal, 0, sizeof(P.personal)); ++ ++ if (blake2b_init_param(S, &P) < 0) { ++ blake2b_invalidate_state(S); ++ return -1; ++ } ++ ++ { ++ grub_uint8_t block[BLAKE2B_BLOCKBYTES]; ++ grub_memset(block, 0, BLAKE2B_BLOCKBYTES); ++ grub_memcpy(block, key, keylen); ++ blake2b_update(S, block, BLAKE2B_BLOCKBYTES); ++ /* Burn the key from stack */ ++ clear_internal_memory(block, BLAKE2B_BLOCKBYTES); ++ } ++ return 0; ++} ++ ++static void blake2b_compress(blake2b_state *S, const grub_uint8_t *block) { ++ grub_uint64_t m[16]; ++ grub_uint64_t v[16]; ++ unsigned int i, r; ++ ++ for (i = 0; i < 16; ++i) { ++ m[i] = load64(block + i * sizeof(m[i])); ++ } ++ ++ for (i = 0; i < 8; ++i) { ++ v[i] = S->h[i]; ++ } ++ ++ v[8] = blake2b_IV[0]; ++ v[9] = blake2b_IV[1]; ++ v[10] = blake2b_IV[2]; ++ v[11] = blake2b_IV[3]; ++ v[12] = blake2b_IV[4] ^ S->t[0]; ++ v[13] = blake2b_IV[5] ^ S->t[1]; ++ v[14] = blake2b_IV[6] ^ S->f[0]; ++ v[15] = blake2b_IV[7] ^ S->f[1]; ++ ++#define G(r, i, a, b, c, d) \ ++ do { \ ++ a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ ++ d = rotr64(d ^ a, 32); \ ++ c = c + d; \ ++ b = rotr64(b ^ c, 24); \ ++ a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ ++ d = rotr64(d ^ a, 16); \ ++ c = c + d; \ ++ b = rotr64(b ^ c, 63); \ ++ } while ((void)0, 0) ++ ++#define ROUND(r) \ ++ do { \ ++ G(r, 0, v[0], v[4], v[8], v[12]); \ ++ G(r, 1, v[1], v[5], v[9], v[13]); \ ++ G(r, 2, v[2], v[6], v[10], v[14]); \ ++ G(r, 3, v[3], v[7], v[11], v[15]); \ ++ G(r, 4, v[0], v[5], v[10], v[15]); \ ++ G(r, 5, v[1], v[6], v[11], v[12]); \ ++ G(r, 6, v[2], v[7], v[8], v[13]); \ ++ G(r, 7, v[3], v[4], v[9], v[14]); \ ++ } while ((void)0, 0) ++ ++ for (r = 0; r < 12; ++r) { ++ ROUND(r); ++ } ++ ++ for (i = 0; i < 8; ++i) { ++ S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; ++ } ++ ++#undef G ++#undef ROUND ++} ++ ++int blake2b_update(blake2b_state *S, const void *in, grub_size_t inlen) { ++ const grub_uint8_t *pin = (const grub_uint8_t *)in; ++ ++ if (inlen == 0) { ++ return 0; ++ } ++ ++ /* Sanity check */ ++ if (S == NULL || in == NULL) { ++ return -1; ++ } ++ ++ /* Is this a reused state? */ ++ if (S->f[0] != 0) { ++ return -1; ++ } ++ ++ if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) { ++ /* Complete current block */ ++ grub_size_t left = S->buflen; ++ grub_size_t fill = BLAKE2B_BLOCKBYTES - left; ++ grub_memcpy(&S->buf[left], pin, fill); ++ blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); ++ blake2b_compress(S, S->buf); ++ S->buflen = 0; ++ inlen -= fill; ++ pin += fill; ++ /* Avoid buffer copies when possible */ ++ while (inlen > BLAKE2B_BLOCKBYTES) { ++ blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); ++ blake2b_compress(S, pin); ++ inlen -= BLAKE2B_BLOCKBYTES; ++ pin += BLAKE2B_BLOCKBYTES; ++ } ++ } ++ grub_memcpy(&S->buf[S->buflen], pin, inlen); ++ S->buflen += (unsigned int)inlen; ++ return 0; ++} ++ ++int blake2b_final(blake2b_state *S, void *out, grub_size_t outlen) { ++ grub_uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; ++ unsigned int i; ++ ++ /* Sanity checks */ ++ if (S == NULL || out == NULL || outlen < S->outlen) { ++ return -1; ++ } ++ ++ /* Is this a reused state? */ ++ if (S->f[0] != 0) { ++ return -1; ++ } ++ ++ blake2b_increment_counter(S, S->buflen); ++ blake2b_set_lastblock(S); ++ grub_memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */ ++ blake2b_compress(S, S->buf); ++ ++ for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ ++ store64(buffer + sizeof(S->h[i]) * i, S->h[i]); ++ } ++ ++ grub_memcpy(out, buffer, S->outlen); ++ clear_internal_memory(buffer, sizeof(buffer)); ++ clear_internal_memory(S->buf, sizeof(S->buf)); ++ clear_internal_memory(S->h, sizeof(S->h)); ++ return 0; ++} ++ ++int blake2b(void *out, grub_size_t outlen, const void *in, grub_size_t inlen, ++ const void *key, grub_size_t keylen) { ++ blake2b_state S; ++ int ret = -1; ++ ++ /* Verify parameters */ ++ if (NULL == in && inlen > 0) { ++ goto fail; ++ } ++ ++ if (NULL == out || outlen == 0 || outlen > BLAKE2B_OUTBYTES) { ++ goto fail; ++ } ++ ++ if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) { ++ goto fail; ++ } ++ ++ if (keylen > 0) { ++ if (blake2b_init_key(&S, outlen, key, keylen) < 0) { ++ goto fail; ++ } ++ } else { ++ if (blake2b_init(&S, outlen) < 0) { ++ goto fail; ++ } ++ } ++ ++ if (blake2b_update(&S, in, inlen) < 0) { ++ goto fail; ++ } ++ ret = blake2b_final(&S, out, outlen); ++ ++fail: ++ clear_internal_memory(&S, sizeof(S)); ++ return ret; ++} ++ ++/* Argon2 Team - Begin Code */ ++int blake2b_long(void *pout, grub_size_t outlen, const void *in, grub_size_t inlen) { ++ grub_uint8_t *out = (grub_uint8_t *)pout; ++ blake2b_state blake_state; ++ grub_uint8_t outlen_bytes[sizeof(grub_uint32_t)] = {0}; ++ int ret = -1; ++ ++ if (outlen > GRUB_UINT32_MAX) { ++ goto fail; ++ } ++ ++ /* Ensure little-endian byte order! */ ++ store32(outlen_bytes, (grub_uint32_t)outlen); ++ ++#define TRY(statement) \ ++ do { \ ++ ret = statement; \ ++ if (ret < 0) { \ ++ goto fail; \ ++ } \ ++ } while ((void)0, 0) ++ ++ if (outlen <= BLAKE2B_OUTBYTES) { ++ TRY(blake2b_init(&blake_state, outlen)); ++ TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes))); ++ TRY(blake2b_update(&blake_state, in, inlen)); ++ TRY(blake2b_final(&blake_state, out, outlen)); ++ } else { ++ grub_uint32_t toproduce; ++ grub_uint8_t out_buffer[BLAKE2B_OUTBYTES]; ++ grub_uint8_t in_buffer[BLAKE2B_OUTBYTES]; ++ TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES)); ++ TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes))); ++ TRY(blake2b_update(&blake_state, in, inlen)); ++ TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES)); ++ grub_memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2); ++ out += BLAKE2B_OUTBYTES / 2; ++ toproduce = (grub_uint32_t)outlen - BLAKE2B_OUTBYTES / 2; ++ ++ while (toproduce > BLAKE2B_OUTBYTES) { ++ grub_memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES); ++ TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer, ++ BLAKE2B_OUTBYTES, NULL, 0)); ++ grub_memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2); ++ out += BLAKE2B_OUTBYTES / 2; ++ toproduce -= BLAKE2B_OUTBYTES / 2; ++ } ++ ++ grub_memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES); ++ TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL, ++ 0)); ++ grub_memcpy(out, out_buffer, toproduce); ++ } ++fail: ++ clear_internal_memory(&blake_state, sizeof(blake_state)); ++ return ret; ++#undef TRY ++} ++/* Argon2 Team - End Code */ +diff --git a/grub-core/lib/argon2/blake2/blamka-round-ref.h b/grub-core/lib/argon2/blake2/blamka-round-ref.h +new file mode 100644 +index 000000000..7f0071ada +--- /dev/null ++++ b/grub-core/lib/argon2/blake2/blamka-round-ref.h +@@ -0,0 +1,56 @@ ++/* ++ * Argon2 reference source code package - reference C implementations ++ * ++ * Copyright 2015 ++ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves ++ * ++ * You may use this work under the terms of a Creative Commons CC0 1.0 ++ * License/Waiver or the Apache Public License 2.0, at your option. The terms of ++ * these licenses can be found at: ++ * ++ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 ++ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * You should have received a copy of both of these licenses along with this ++ * software. If not, they may be obtained at the above URLs. ++ */ ++ ++#ifndef BLAKE_ROUND_MKA_H ++#define BLAKE_ROUND_MKA_H ++ ++#include "blake2.h" ++#include "blake2-impl.h" ++ ++/* designed by the Lyra PHC team */ ++static BLAKE2_INLINE grub_uint64_t fBlaMka(grub_uint64_t x, grub_uint64_t y) { ++ const grub_uint64_t m = GRUB_UINT64_C(0xFFFFFFFF); ++ const grub_uint64_t xy = (x & m) * (y & m); ++ return x + y + 2 * xy; ++} ++ ++#define G(a, b, c, d) \ ++ do { \ ++ a = fBlaMka(a, b); \ ++ d = rotr64(d ^ a, 32); \ ++ c = fBlaMka(c, d); \ ++ b = rotr64(b ^ c, 24); \ ++ a = fBlaMka(a, b); \ ++ d = rotr64(d ^ a, 16); \ ++ c = fBlaMka(c, d); \ ++ b = rotr64(b ^ c, 63); \ ++ } while ((void)0, 0) ++ ++#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \ ++ v12, v13, v14, v15) \ ++ do { \ ++ G(v0, v4, v8, v12); \ ++ G(v1, v5, v9, v13); \ ++ G(v2, v6, v10, v14); \ ++ G(v3, v7, v11, v15); \ ++ G(v0, v5, v10, v15); \ ++ G(v1, v6, v11, v12); \ ++ G(v2, v7, v8, v13); \ ++ G(v3, v4, v9, v14); \ ++ } while ((void)0, 0) ++ ++#endif +diff --git a/grub-core/lib/argon2/core.c b/grub-core/lib/argon2/core.c +new file mode 100644 +index 000000000..0fe5b74cb +--- /dev/null ++++ b/grub-core/lib/argon2/core.c +@@ -0,0 +1,506 @@ ++/* ++ * Argon2 reference source code package - reference C implementations ++ * ++ * Copyright 2015 ++ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves ++ * ++ * You may use this work under the terms of a Creative Commons CC0 1.0 ++ * License/Waiver or the Apache Public License 2.0, at your option. The terms of ++ * these licenses can be found at: ++ * ++ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 ++ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * You should have received a copy of both of these licenses along with this ++ * software. If not, they may be obtained at the above URLs. ++ */ ++ ++/*For memory wiping*/ ++#ifdef _MSC_VER ++#include <windows.h> ++#include <winbase.h> /* For SecureZeroMemory */ ++#endif ++#if defined __STDC_LIB_EXT1__ ++#define __STDC_WANT_LIB_EXT1__ 1 ++#endif ++#define VC_GE_2005(version) (version >= 1400) ++ ++#include "core.h" ++#include "blake2/blake2.h" ++#include "blake2/blake2-impl.h" ++ ++#ifdef GENKAT ++#include "genkat.h" ++#endif ++ ++#if defined(__clang__) ++#if __has_attribute(optnone) ++#define NOT_OPTIMIZED __attribute__((optnone)) ++#endif ++#elif defined(__GNUC__) ++#define GCC_VERSION \ ++ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) ++#if GCC_VERSION >= 40400 ++#define NOT_OPTIMIZED __attribute__((optimize("O0"))) ++#endif ++#endif ++#ifndef NOT_OPTIMIZED ++#define NOT_OPTIMIZED ++#endif ++ ++/***************Instance and Position constructors**********/ ++void init_block_value(block *b, grub_uint8_t in) { grub_memset(b->v, in, sizeof(b->v)); } ++ ++void copy_block(block *dst, const block *src) { ++ grub_memcpy(dst->v, src->v, sizeof(grub_uint64_t) * ARGON2_QWORDS_IN_BLOCK); ++} ++ ++void xor_block(block *dst, const block *src) { ++ int i; ++ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { ++ dst->v[i] ^= src->v[i]; ++ } ++} ++ ++static void load_block(block *dst, const void *input) { ++ unsigned i; ++ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { ++ dst->v[i] = load64((const grub_uint8_t *)input + i * sizeof(dst->v[i])); ++ } ++} ++ ++static void store_block(void *output, const block *src) { ++ unsigned i; ++ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { ++ store64((grub_uint8_t *)output + i * sizeof(src->v[i]), src->v[i]); ++ } ++} ++ ++/***************Memory functions*****************/ ++ ++int allocate_memory(const argon2_context *context, grub_uint8_t **memory, ++ grub_size_t num, grub_size_t size) { ++ grub_size_t memory_size = num*size; ++ if (memory == NULL) { ++ return ARGON2_MEMORY_ALLOCATION_ERROR; ++ } ++ ++ /* 1. Check for multiplication overflow */ ++ if (size != 0 && memory_size / size != num) { ++ return ARGON2_MEMORY_ALLOCATION_ERROR; ++ } ++ ++ /* 2. Try to allocate with appropriate allocator */ ++ if (context->allocate_cbk) { ++ (context->allocate_cbk)(memory, memory_size); ++ } else { ++ *memory = grub_malloc(memory_size); ++ } ++ ++ if (*memory == NULL) { ++ return ARGON2_MEMORY_ALLOCATION_ERROR; ++ } ++ ++ return ARGON2_OK; ++} ++ ++void grub_free_memory(const argon2_context *context, grub_uint8_t *memory, ++ grub_size_t num, grub_size_t size) { ++ grub_size_t memory_size = num*size; ++ clear_internal_memory(memory, memory_size); ++ if (context->grub_free_cbk) { ++ (context->grub_free_cbk)(memory, memory_size); ++ } else { ++ grub_free(memory); ++ } ++} ++ ++void NOT_OPTIMIZED secure_wipe_memory(void *v, grub_size_t n) { ++ static void *(*const volatile grub_memset_sec)(void *, int, grub_size_t) = &grub_memset; ++ grub_memset_sec(v, 0, n); ++} ++ ++/* Memory clear flag defaults to true. */ ++int FLAG_clear_internal_memory = 1; ++void clear_internal_memory(void *v, grub_size_t n) { ++ if (FLAG_clear_internal_memory && v) { ++ secure_wipe_memory(v, n); ++ } ++} ++ ++void finalize(const argon2_context *context, argon2_instance_t *instance) { ++ if (context != NULL && instance != NULL) { ++ block blockhash; ++ grub_uint32_t l; ++ ++ copy_block(&blockhash, instance->memory + instance->lane_length - 1); ++ ++ /* XOR the last blocks */ ++ for (l = 1; l < instance->lanes; ++l) { ++ grub_uint32_t last_block_in_lane = ++ l * instance->lane_length + (instance->lane_length - 1); ++ xor_block(&blockhash, instance->memory + last_block_in_lane); ++ } ++ ++ /* Hash the result */ ++ { ++ grub_uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; ++ store_block(blockhash_bytes, &blockhash); ++ blake2b_long(context->out, context->outlen, blockhash_bytes, ++ ARGON2_BLOCK_SIZE); ++ /* clear blockhash and blockhash_bytes */ ++ clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE); ++ clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); ++ } ++ ++#ifdef GENKAT ++ print_tag(context->out, context->outlen); ++#endif ++ ++ grub_free_memory(context, (grub_uint8_t *)instance->memory, ++ instance->memory_blocks, sizeof(block)); ++ } ++} ++ ++grub_uint32_t index_alpha(const argon2_instance_t *instance, ++ const argon2_position_t *position, grub_uint32_t pseudo_rand, ++ int same_lane) { ++ /* ++ * Pass 0: ++ * This lane : all already finished segments plus already constructed ++ * blocks in this segment ++ * Other lanes : all already finished segments ++ * Pass 1+: ++ * This lane : (SYNC_POINTS - 1) last segments plus already constructed ++ * blocks in this segment ++ * Other lanes : (SYNC_POINTS - 1) last segments ++ */ ++ grub_uint32_t reference_area_size; ++ grub_uint64_t relative_position; ++ grub_uint64_t start_position, absolute_position; ++ ++ if (0 == position->pass) { ++ /* First pass */ ++ if (0 == position->slice) { ++ /* First slice */ ++ reference_area_size = ++ position->index - 1; /* all but the previous */ ++ } else { ++ if (same_lane) { ++ /* The same lane => add current segment */ ++ reference_area_size = ++ position->slice * instance->segment_length + ++ position->index - 1; ++ } else { ++ reference_area_size = ++ position->slice * instance->segment_length + ++ ((position->index == 0) ? (-1) : 0); ++ } ++ } ++ } else { ++ /* Second pass */ ++ if (same_lane) { ++ reference_area_size = instance->lane_length - ++ instance->segment_length + position->index - ++ 1; ++ } else { ++ reference_area_size = instance->lane_length - ++ instance->segment_length + ++ ((position->index == 0) ? (-1) : 0); ++ } ++ } ++ ++ /* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce ++ * relative position */ ++ relative_position = pseudo_rand; ++ relative_position = relative_position * relative_position >> 32; ++ relative_position = reference_area_size - 1 - ++ (reference_area_size * relative_position >> 32); ++ ++ /* 1.2.5 Computing starting position */ ++ start_position = 0; ++ ++ if (0 != position->pass) { ++ start_position = (position->slice == ARGON2_SYNC_POINTS - 1) ++ ? 0 ++ : (position->slice + 1) * instance->segment_length; ++ } ++ ++ /* 1.2.6. Computing absolute position */ ++ grub_divmod64 (start_position + relative_position, instance->lane_length, ++ &absolute_position); /* absolute position */ ++ return absolute_position; ++} ++ ++/* Single-threaded version for p=1 case */ ++static int fill_memory_blocks_st(argon2_instance_t *instance) { ++ grub_uint32_t r, s, l; ++ ++ for (r = 0; r < instance->passes; ++r) { ++ for (s = 0; s < ARGON2_SYNC_POINTS; ++s) { ++ for (l = 0; l < instance->lanes; ++l) { ++ argon2_position_t position = {r, l, (grub_uint8_t)s, 0}; ++ fill_segment(instance, position); ++ } ++ } ++#ifdef GENKAT ++ internal_kat(instance, r); /* Print all memory blocks */ ++#endif ++ } ++ return ARGON2_OK; ++} ++ ++int fill_memory_blocks(argon2_instance_t *instance) { ++ if (instance == NULL || instance->lanes == 0) { ++ return ARGON2_INCORRECT_PARAMETER; ++ } ++ return fill_memory_blocks_st(instance); ++} ++ ++int validate_inputs(const argon2_context *context) { ++ if (NULL == context) { ++ return ARGON2_INCORRECT_PARAMETER; ++ } ++ ++ if (NULL == context->out) { ++ return ARGON2_OUTPUT_PTR_NULL; ++ } ++ ++ /* Validate output length */ ++ if (ARGON2_MIN_OUTLEN > context->outlen) { ++ return ARGON2_OUTPUT_TOO_SHORT; ++ } ++ ++ if (ARGON2_MAX_OUTLEN < context->outlen) { ++ return ARGON2_OUTPUT_TOO_LONG; ++ } ++ ++ /* Validate password (required param) */ ++ if (NULL == context->pwd) { ++ if (0 != context->pwdlen) { ++ return ARGON2_PWD_PTR_MISMATCH; ++ } ++ } ++ ++ if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) { ++ return ARGON2_PWD_TOO_LONG; ++ } ++ ++ /* Validate salt (required param) */ ++ if (NULL == context->salt) { ++ if (0 != context->saltlen) { ++ return ARGON2_SALT_PTR_MISMATCH; ++ } ++ } ++ ++ if (ARGON2_MIN_SALT_LENGTH > context->saltlen) { ++ return ARGON2_SALT_TOO_SHORT; ++ } ++ ++ if (ARGON2_MAX_SALT_LENGTH < context->saltlen) { ++ return ARGON2_SALT_TOO_LONG; ++ } ++ ++ /* Validate secret (optional param) */ ++ if (NULL == context->secret) { ++ if (0 != context->secretlen) { ++ return ARGON2_SECRET_PTR_MISMATCH; ++ } ++ } else { ++ if (ARGON2_MAX_SECRET < context->secretlen) { ++ return ARGON2_SECRET_TOO_LONG; ++ } ++ } ++ ++ /* Validate associated data (optional param) */ ++ if (NULL == context->ad) { ++ if (0 != context->adlen) { ++ return ARGON2_AD_PTR_MISMATCH; ++ } ++ } else { ++ if (ARGON2_MAX_AD_LENGTH < context->adlen) { ++ return ARGON2_AD_TOO_LONG; ++ } ++ } ++ ++ /* Validate memory cost */ ++ if (ARGON2_MIN_MEMORY > context->m_cost) { ++ return ARGON2_MEMORY_TOO_LITTLE; ++ } ++ ++ if (context->m_cost < 8 * context->lanes) { ++ return ARGON2_MEMORY_TOO_LITTLE; ++ } ++ ++ /* Validate time cost */ ++ if (ARGON2_MIN_TIME > context->t_cost) { ++ return ARGON2_TIME_TOO_SMALL; ++ } ++ ++ if (ARGON2_MAX_TIME < context->t_cost) { ++ return ARGON2_TIME_TOO_LARGE; ++ } ++ ++ /* Validate lanes */ ++ if (ARGON2_MIN_LANES > context->lanes) { ++ return ARGON2_LANES_TOO_FEW; ++ } ++ ++ if (ARGON2_MAX_LANES < context->lanes) { ++ return ARGON2_LANES_TOO_MANY; ++ } ++ ++ /* Validate threads */ ++ if (ARGON2_MIN_THREADS > context->threads) { ++ return ARGON2_THREADS_TOO_FEW; ++ } ++ ++ if (ARGON2_MAX_THREADS < context->threads) { ++ return ARGON2_THREADS_TOO_MANY; ++ } ++ ++ if (NULL != context->allocate_cbk && NULL == context->grub_free_cbk) { ++ return ARGON2_FREE_MEMORY_CBK_NULL; ++ } ++ ++ if (NULL == context->allocate_cbk && NULL != context->grub_free_cbk) { ++ return ARGON2_ALLOCATE_MEMORY_CBK_NULL; ++ } ++ ++ return ARGON2_OK; ++} ++ ++void fill_first_blocks(grub_uint8_t *blockhash, const argon2_instance_t *instance) { ++ grub_uint32_t l; ++ /* Make the first and second block in each lane as G(H0||0||i) or ++ G(H0||1||i) */ ++ grub_uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; ++ for (l = 0; l < instance->lanes; ++l) { ++ ++ store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0); ++ store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l); ++ blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash, ++ ARGON2_PREHASH_SEED_LENGTH); ++ load_block(&instance->memory[l * instance->lane_length + 0], ++ blockhash_bytes); ++ ++ store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1); ++ blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash, ++ ARGON2_PREHASH_SEED_LENGTH); ++ load_block(&instance->memory[l * instance->lane_length + 1], ++ blockhash_bytes); ++ } ++ clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); ++} ++ ++void initial_hash(grub_uint8_t *blockhash, argon2_context *context, ++ argon2_type type) { ++ blake2b_state BlakeHash; ++ grub_uint8_t value[sizeof(grub_uint32_t)]; ++ ++ if (NULL == context || NULL == blockhash) { ++ return; ++ } ++ ++ blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH); ++ ++ store32(&value, context->lanes); ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); ++ ++ store32(&value, context->outlen); ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); ++ ++ store32(&value, context->m_cost); ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); ++ ++ store32(&value, context->t_cost); ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); ++ ++ store32(&value, context->version); ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); ++ ++ store32(&value, (grub_uint32_t)type); ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); ++ ++ store32(&value, context->pwdlen); ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); ++ ++ if (context->pwd != NULL) { ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)context->pwd, ++ context->pwdlen); ++ ++ if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) { ++ secure_wipe_memory(context->pwd, context->pwdlen); ++ context->pwdlen = 0; ++ } ++ } ++ ++ store32(&value, context->saltlen); ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); ++ ++ if (context->salt != NULL) { ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)context->salt, ++ context->saltlen); ++ } ++ ++ store32(&value, context->secretlen); ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); ++ ++ if (context->secret != NULL) { ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)context->secret, ++ context->secretlen); ++ ++ if (context->flags & ARGON2_FLAG_CLEAR_SECRET) { ++ secure_wipe_memory(context->secret, context->secretlen); ++ context->secretlen = 0; ++ } ++ } ++ ++ store32(&value, context->adlen); ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); ++ ++ if (context->ad != NULL) { ++ blake2b_update(&BlakeHash, (const grub_uint8_t *)context->ad, ++ context->adlen); ++ } ++ ++ blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH); ++} ++ ++int initialize(argon2_instance_t *instance, argon2_context *context) { ++ grub_uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; ++ int result = ARGON2_OK; ++ ++ if (instance == NULL || context == NULL) ++ return ARGON2_INCORRECT_PARAMETER; ++ instance->context_ptr = context; ++ ++ /* 1. Memory allocation */ ++ result = allocate_memory(context, (grub_uint8_t **)&(instance->memory), ++ instance->memory_blocks, sizeof(block)); ++ if (result != ARGON2_OK) { ++ return result; ++ } ++ ++ /* 2. Initial hashing */ ++ /* H_0 + 8 extra bytes to produce the first blocks */ ++ /* grub_uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */ ++ /* Hashing all inputs */ ++ initial_hash(blockhash, context, instance->type); ++ /* Zeroing 8 extra bytes */ ++ clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, ++ ARGON2_PREHASH_SEED_LENGTH - ++ ARGON2_PREHASH_DIGEST_LENGTH); ++ ++#ifdef GENKAT ++ initial_kat(blockhash, context, instance->type); ++#endif ++ ++ /* 3. Creating first blocks, we always have at least two blocks in a slice ++ */ ++ fill_first_blocks(blockhash, instance); ++ /* Clearing the hash */ ++ clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH); ++ ++ return ARGON2_OK; ++} +diff --git a/grub-core/lib/argon2/core.h b/grub-core/lib/argon2/core.h +new file mode 100644 +index 000000000..bbcd56998 +--- /dev/null ++++ b/grub-core/lib/argon2/core.h +@@ -0,0 +1,228 @@ ++/* ++ * Argon2 reference source code package - reference C implementations ++ * ++ * Copyright 2015 ++ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves ++ * ++ * You may use this work under the terms of a Creative Commons CC0 1.0 ++ * License/Waiver or the Apache Public License 2.0, at your option. The terms of ++ * these licenses can be found at: ++ * ++ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 ++ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * You should have received a copy of both of these licenses along with this ++ * software. If not, they may be obtained at the above URLs. ++ */ ++ ++#ifndef ARGON2_CORE_H ++#define ARGON2_CORE_H ++ ++#include "argon2.h" ++ ++#define CONST_CAST(x) (x)(grub_addr_t) ++ ++/**********************Argon2 internal constants*******************************/ ++ ++enum argon2_core_constants { ++ /* Memory block size in bytes */ ++ ARGON2_BLOCK_SIZE = 1024, ++ ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8, ++ ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16, ++ ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32, ++ ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64, ++ ++ /* Number of pseudo-random values generated by one call to Blake in Argon2i ++ to ++ generate reference block positions */ ++ ARGON2_ADDRESSES_IN_BLOCK = 128, ++ ++ /* Pre-hashing digest length and its extension*/ ++ ARGON2_PREHASH_DIGEST_LENGTH = 64, ++ ARGON2_PREHASH_SEED_LENGTH = 72 ++}; ++ ++/*************************Argon2 internal data types***********************/ ++ ++/* ++ * Structure for the (1KB) memory block implemented as 128 64-bit words. ++ * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no ++ * bounds checking). ++ */ ++typedef struct block_ { grub_uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block; ++ ++/*****************Functions that work with the block******************/ ++ ++/* Initialize each byte of the block with @in */ ++void init_block_value(block *b, grub_uint8_t in); ++ ++/* Copy block @src to block @dst */ ++void copy_block(block *dst, const block *src); ++ ++/* XOR @src onto @dst bytewise */ ++void xor_block(block *dst, const block *src); ++ ++/* ++ * Argon2 instance: memory pointer, number of passes, amount of memory, type, ++ * and derived values. ++ * Used to evaluate the number and location of blocks to construct in each ++ * thread ++ */ ++typedef struct Argon2_instance_t { ++ block *memory; /* Memory pointer */ ++ grub_uint32_t version; ++ grub_uint32_t passes; /* Number of passes */ ++ grub_uint32_t memory_blocks; /* Number of blocks in memory */ ++ grub_uint32_t segment_length; ++ grub_uint32_t lane_length; ++ grub_uint32_t lanes; ++ grub_uint32_t threads; ++ argon2_type type; ++ int print_internals; /* whether to print the memory blocks */ ++ argon2_context *context_ptr; /* points back to original context */ ++} argon2_instance_t; ++ ++/* ++ * Argon2 position: where we construct the block right now. Used to distribute ++ * work between threads. ++ */ ++typedef struct Argon2_position_t { ++ grub_uint32_t pass; ++ grub_uint32_t lane; ++ grub_uint8_t slice; ++ grub_uint32_t index; ++} argon2_position_t; ++ ++/*Struct that holds the inputs for thread handling FillSegment*/ ++typedef struct Argon2_thread_data { ++ argon2_instance_t *instance_ptr; ++ argon2_position_t pos; ++} argon2_thread_data; ++ ++/*************************Argon2 core functions********************************/ ++ ++/* Allocates memory to the given pointer, uses the appropriate allocator as ++ * specified in the context. Total allocated memory is num*size. ++ * @param context argon2_context which specifies the allocator ++ * @param memory pointer to the pointer to the memory ++ * @param size the size in bytes for each element to be allocated ++ * @param num the number of elements to be allocated ++ * @return ARGON2_OK if @memory is a valid pointer and memory is allocated ++ */ ++int allocate_memory(const argon2_context *context, grub_uint8_t **memory, ++ grub_size_t num, grub_size_t size); ++ ++/* ++ * Frees memory at the given pointer, uses the appropriate deallocator as ++ * specified in the context. Also cleans the memory using clear_internal_memory. ++ * @param context argon2_context which specifies the deallocator ++ * @param memory pointer to buffer to be grub_freed ++ * @param size the size in bytes for each element to be deallocated ++ * @param num the number of elements to be deallocated ++ */ ++void grub_free_memory(const argon2_context *context, grub_uint8_t *memory, ++ grub_size_t num, grub_size_t size); ++ ++/* Function that securely cleans the memory. This ignores any flags set ++ * regarding clearing memory. Usually one just calls clear_internal_memory. ++ * @param mem Pointer to the memory ++ * @param s Memory size in bytes ++ */ ++void secure_wipe_memory(void *v, grub_size_t n); ++ ++/* Function that securely clears the memory if FLAG_clear_internal_memory is ++ * set. If the flag isn't set, this function does nothing. ++ * @param mem Pointer to the memory ++ * @param s Memory size in bytes ++ */ ++void clear_internal_memory(void *v, grub_size_t n); ++ ++/* ++ * Computes absolute position of reference block in the lane following a skewed ++ * distribution and using a pseudo-random value as input ++ * @param instance Pointer to the current instance ++ * @param position Pointer to the current position ++ * @param pseudo_rand 32-bit pseudo-random value used to determine the position ++ * @param same_lane Indicates if the block will be taken from the current lane. ++ * If so we can reference the current segment ++ * @pre All pointers must be valid ++ */ ++grub_uint32_t index_alpha(const argon2_instance_t *instance, ++ const argon2_position_t *position, grub_uint32_t pseudo_rand, ++ int same_lane); ++ ++/* ++ * Function that validates all inputs against predefined restrictions and return ++ * an error code ++ * @param context Pointer to current Argon2 context ++ * @return ARGON2_OK if everything is all right, otherwise one of error codes ++ * (all defined in <argon2.h> ++ */ ++int validate_inputs(const argon2_context *context); ++ ++/* ++ * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears ++ * password and secret if needed ++ * @param context Pointer to the Argon2 internal structure containing memory ++ * pointer, and parameters for time and space requirements. ++ * @param blockhash Buffer for pre-hashing digest ++ * @param type Argon2 type ++ * @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes ++ * allocated ++ */ ++void initial_hash(grub_uint8_t *blockhash, argon2_context *context, ++ argon2_type type); ++ ++/* ++ * Function creates first 2 blocks per lane ++ * @param instance Pointer to the current instance ++ * @param blockhash Pointer to the pre-hashing digest ++ * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values ++ */ ++void fill_first_blocks(grub_uint8_t *blockhash, const argon2_instance_t *instance); ++ ++/* ++ * Function allocates memory, hashes the inputs with Blake, and creates first ++ * two blocks. Returns the pointer to the main memory with 2 blocks per lane ++ * initialized ++ * @param context Pointer to the Argon2 internal structure containing memory ++ * pointer, and parameters for time and space requirements. ++ * @param instance Current Argon2 instance ++ * @return Zero if successful, -1 if memory failed to allocate. @context->state ++ * will be modified if successful. ++ */ ++int initialize(argon2_instance_t *instance, argon2_context *context); ++ ++/* ++ * XORing the last block of each lane, hashing it, making the tag. Deallocates ++ * the memory. ++ * @param context Pointer to current Argon2 context (use only the out parameters ++ * from it) ++ * @param instance Pointer to current instance of Argon2 ++ * @pre instance->state must point to necessary amount of memory ++ * @pre context->out must point to outlen bytes of memory ++ * @pre if context->grub_free_cbk is not NULL, it should point to a function that ++ * deallocates memory ++ */ ++void finalize(const argon2_context *context, argon2_instance_t *instance); ++ ++/* ++ * Function that fills the segment using previous segments also from other ++ * threads ++ * @param context current context ++ * @param instance Pointer to the current instance ++ * @param position Current position ++ * @pre all block pointers must be valid ++ */ ++void fill_segment(const argon2_instance_t *instance, ++ argon2_position_t position); ++ ++/* ++ * Function that fills the entire memory t_cost times based on the first two ++ * blocks in each lane ++ * @param instance Pointer to the current instance ++ * @return ARGON2_OK if successful, @context->state ++ */ ++int fill_memory_blocks(argon2_instance_t *instance); ++ ++#endif +diff --git a/grub-core/lib/argon2/ref.c b/grub-core/lib/argon2/ref.c +new file mode 100644 +index 000000000..c933df80d +--- /dev/null ++++ b/grub-core/lib/argon2/ref.c +@@ -0,0 +1,190 @@ ++/* ++ * Argon2 reference source code package - reference C implementations ++ * ++ * Copyright 2015 ++ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves ++ * ++ * You may use this work under the terms of a Creative Commons CC0 1.0 ++ * License/Waiver or the Apache Public License 2.0, at your option. The terms of ++ * these licenses can be found at: ++ * ++ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 ++ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * You should have received a copy of both of these licenses along with this ++ * software. If not, they may be obtained at the above URLs. ++ */ ++ ++#include "argon2.h" ++#include "core.h" ++ ++#include "blake2/blamka-round-ref.h" ++#include "blake2/blake2-impl.h" ++#include "blake2/blake2.h" ++ ++ ++/* ++ * Function fills a new memory block and optionally XORs the old block over the new one. ++ * @next_block must be initialized. ++ * @param prev_block Pointer to the previous block ++ * @param ref_block Pointer to the reference block ++ * @param next_block Pointer to the block to be constructed ++ * @param with_xor Whether to XOR into the new block (1) or just overwrite (0) ++ * @pre all block pointers must be valid ++ */ ++static void fill_block(const block *prev_block, const block *ref_block, ++ block *next_block, int with_xor) { ++ block blockR, block_tmp; ++ unsigned i; ++ ++ copy_block(&blockR, ref_block); ++ xor_block(&blockR, prev_block); ++ copy_block(&block_tmp, &blockR); ++ /* Now blockR = ref_block + prev_block and block_tmp = ref_block + prev_block */ ++ if (with_xor) { ++ /* Saving the next block contents for XOR over: */ ++ xor_block(&block_tmp, next_block); ++ /* Now blockR = ref_block + prev_block and ++ block_tmp = ref_block + prev_block + next_block */ ++ } ++ ++ /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then ++ (16,17,..31)... finally (112,113,...127) */ ++ for (i = 0; i < 8; ++i) { ++ BLAKE2_ROUND_NOMSG( ++ blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2], ++ blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5], ++ blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8], ++ blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11], ++ blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14], ++ blockR.v[16 * i + 15]); ++ } ++ ++ /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then ++ (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */ ++ for (i = 0; i < 8; i++) { ++ BLAKE2_ROUND_NOMSG( ++ blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16], ++ blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33], ++ blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64], ++ blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81], ++ blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112], ++ blockR.v[2 * i + 113]); ++ } ++ ++ copy_block(next_block, &block_tmp); ++ xor_block(next_block, &blockR); ++} ++ ++static void next_addresses(block *address_block, block *input_block, ++ const block *zero_block) { ++ input_block->v[6]++; ++ fill_block(zero_block, input_block, address_block, 0); ++ fill_block(zero_block, address_block, address_block, 0); ++} ++ ++void fill_segment(const argon2_instance_t *instance, ++ argon2_position_t position) { ++ block *ref_block = NULL, *curr_block = NULL; ++ block address_block, input_block, zero_block; ++ grub_uint64_t pseudo_rand, ref_index, ref_lane; ++ grub_uint32_t prev_offset, curr_offset; ++ grub_uint32_t starting_index; ++ grub_uint32_t i; ++ int data_independent_addressing; ++ ++ if (instance == NULL) { ++ return; ++ } ++ ++ data_independent_addressing = ++ (instance->type == Argon2_i) || ++ (instance->type == Argon2_id && (position.pass == 0) && ++ (position.slice < ARGON2_SYNC_POINTS / 2)); ++ ++ if (data_independent_addressing) { ++ init_block_value(&zero_block, 0); ++ init_block_value(&input_block, 0); ++ ++ input_block.v[0] = position.pass; ++ input_block.v[1] = position.lane; ++ input_block.v[2] = position.slice; ++ input_block.v[3] = instance->memory_blocks; ++ input_block.v[4] = instance->passes; ++ input_block.v[5] = instance->type; ++ } ++ ++ starting_index = 0; ++ ++ if ((0 == position.pass) && (0 == position.slice)) { ++ starting_index = 2; /* we have already generated the first two blocks */ ++ ++ /* Don't forget to generate the first block of addresses: */ ++ if (data_independent_addressing) { ++ next_addresses(&address_block, &input_block, &zero_block); ++ } ++ } ++ ++ /* Offset of the current block */ ++ curr_offset = position.lane * instance->lane_length + ++ position.slice * instance->segment_length + starting_index; ++ ++ if (0 == curr_offset % instance->lane_length) { ++ /* Last block in this lane */ ++ prev_offset = curr_offset + instance->lane_length - 1; ++ } else { ++ /* Previous block */ ++ prev_offset = curr_offset - 1; ++ } ++ ++ for (i = starting_index; i < instance->segment_length; ++ ++i, ++curr_offset, ++prev_offset) { ++ /*1.1 Rotating prev_offset if needed */ ++ if (curr_offset % instance->lane_length == 1) { ++ prev_offset = curr_offset - 1; ++ } ++ ++ /* 1.2 Computing the index of the reference block */ ++ /* 1.2.1 Taking pseudo-random value from the previous block */ ++ if (data_independent_addressing) { ++ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { ++ next_addresses(&address_block, &input_block, &zero_block); ++ } ++ pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK]; ++ } else { ++ pseudo_rand = instance->memory[prev_offset].v[0]; ++ } ++ ++ /* 1.2.2 Computing the lane of the reference block */ ++ grub_divmod64 (pseudo_rand >> 32, instance->lanes, &ref_lane); ++ ++ if ((position.pass == 0) && (position.slice == 0)) { ++ /* Can not reference other lanes yet */ ++ ref_lane = position.lane; ++ } ++ ++ /* 1.2.3 Computing the number of possible reference block within the ++ * lane. ++ */ ++ position.index = i; ++ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF, ++ ref_lane == position.lane); ++ ++ /* 2 Creating a new block */ ++ ref_block = ++ instance->memory + instance->lane_length * ref_lane + ref_index; ++ curr_block = instance->memory + curr_offset; ++ if (ARGON2_VERSION_10 == instance->version) { ++ /* version 1.2.1 and earlier: overwrite, not XOR */ ++ fill_block(instance->memory + prev_offset, ref_block, curr_block, 0); ++ } else { ++ if(0 == position.pass) { ++ fill_block(instance->memory + prev_offset, ref_block, ++ curr_block, 0); ++ } else { ++ fill_block(instance->memory + prev_offset, ref_block, ++ curr_block, 1); ++ } ++ } ++ } ++} +-- +2.32.0 + + +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEP4xsACgkQVbJhu7ck +PpRmAA/8C5AlxA0SBA3Avgcm0QDyb1ifNtc8mNCiaVsDV0xfBafVK2IX/dm+q0H7 +fB5Qazpqb+502nZCzyeuyx4PFJj2EPxbw5SSfZKQw97cqO2DArIMduKselHSuopL +N9myVreoX7bumzeOt4TNFVRKvxqZ1cYCBoLz6AOm9sPhmjf8dzLi0sZ3ZAF7YLza +bi/lts1TahIOBPk7cpJBOWYK5N/EiLiLmsfSwsZyhrPbzo2f+LVSkf+Ev7/MZfJN +zhY4OdGb6MCq5JJ6fcAFrqKNfinGbHwfz5S/WyClhfzbbtgGX8NofYx0JNHdVVRw +pT6/Na/L1gIkVTMfgQn8w0VGcKKXMbqE+pas42W0ZH8pgThh87utZZtlbYQG3kRL +7oviRYqS1fVKLiDTi1dYE2CKnk2lyy6J8T+Ia2/PR/UGsWbxR5pwFlEWJyqnOIDg +vq46AQBndRYf8RuJAJr2uPZkl9ZniSL/7IS96yJFzRTAgbYNwgoT8EEI4NJiUmA3 +ySqbEzAx/p7F1E8FFBUtY2onpaiIJAcl39RDK+hd6juHplUfAboUYlznu03YnX7o +GAWSpA90LuZZ8hTwkBOwOK8SExmOOFh4FvqfJPwSPgHIdM71nsZN2ktHWTymapAg +ds11gWlKJ50mz4K9KpmA+EdHENmtPhsRb6OcWycYq9X5+o/1TCk= +=05dK +-----END PGP SIGNATURE----- + + diff --git a/argon_4.patch b/argon_4.patch new file mode 100644 index 000000000000..051cf7bd477b --- /dev/null +++ b/argon_4.patch @@ -0,0 +1,71 @@ +--- + grub-core/disk/luks2.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c +index 371a53b83..02822c777 100644 +--- a/grub-core/disk/luks2.c ++++ b/grub-core/disk/luks2.c +@@ -40,6 +40,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + enum grub_luks2_kdf_type + { + LUKS2_KDF_TYPE_ARGON2I, ++ LUKS2_KDF_TYPE_ARGON2ID, + LUKS2_KDF_TYPE_PBKDF2 + }; + typedef enum grub_luks2_kdf_type grub_luks2_kdf_type_t; +@@ -92,7 +93,7 @@ struct grub_luks2_keyslot + grub_int64_t time; + grub_int64_t memory; + grub_int64_t cpus; +- } argon2i; ++ } argon2; + struct + { + const char *hash; +@@ -162,10 +163,11 @@ luks2_parse_keyslot (grub_luks2_keyslot_t *out, const grub_json_t *keyslot) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing or invalid KDF"); + else if (!grub_strcmp (type, "argon2i") || !grub_strcmp (type, "argon2id")) + { +- out->kdf.type = LUKS2_KDF_TYPE_ARGON2I; +- if (grub_json_getint64 (&out->kdf.u.argon2i.time, &kdf, "time") || +- grub_json_getint64 (&out->kdf.u.argon2i.memory, &kdf, "memory") || +- grub_json_getint64 (&out->kdf.u.argon2i.cpus, &kdf, "cpus")) ++ out->kdf.type = !grub_strcmp (type, "argon2i") ++ ? LUKS2_KDF_TYPE_ARGON2I : LUKS2_KDF_TYPE_ARGON2ID; ++ if (grub_json_getint64 (&out->kdf.u.argon2.time, &kdf, "time") || ++ grub_json_getint64 (&out->kdf.u.argon2.memory, &kdf, "memory") || ++ grub_json_getint64 (&out->kdf.u.argon2.cpus, &kdf, "cpus")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing Argon2i parameters"); + } + else if (!grub_strcmp (type, "pbkdf2")) +@@ -445,6 +447,7 @@ luks2_decrypt_key (grub_uint8_t *out_key, + switch (k->kdf.type) + { + case LUKS2_KDF_TYPE_ARGON2I: ++ case LUKS2_KDF_TYPE_ARGON2ID: + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Argon2 not supported"); + goto err; + case LUKS2_KDF_TYPE_PBKDF2: +-- +2.32.0 + + +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEP4x8ACgkQVbJhu7ck +PpQ/1g/9EM6PVsjbyTdgy3rNWWEuk2VJrjagm4+qwr2Nt1d69NvsyQIzGw4wTnI3 +ZgDQW3ddn4KhWioBusD8XOgZEySc3Q0wOh2tbjGVV235bmxUTu22Z6vhnj34BN/2 +0sOFjSjRtRNh5LmfR+7HP39id2ZppljDaDNzDeRZzCEXUymt3xKtGNlASAe1IW6G +PKIYkols3GsYp406P/Fjqvu8YRJuAGv6VyrS4QineAR1Iv70pBWkQTtE7JgWBmv4 ++cCs+MD88kSwxf40DEo5o0AVjrsAv6VqMp89yi3z8TRbDTtMERPr0zP5hWCkkuXd +st8FqPCunHv+afEk3q8Xn9LlJ65wXJ7XflIwbBEsdSf4cL03rx3WgPGu1sK+s8o+ +JxjkYKH+GJUbDZ+uw7ngcNKUnsWNxe0Lpu+zEakkJmoWQ/GIhFf93G2yJag7mKMP +q0A/oh6+z6L2+pg91jPwAatisICYks1S5MpWKiNP+EnEGHrr2dnjfOEWq9W0Qghx +ixJtltwfVh3EIcLwitGrRhQykL1E1DG8yJyjWzsaf+6moF9uvZSHN/7JxEw3oOtB +9NQi7m4okMe3ACqLAp2z2VcvVZ1hVCp7HlTp5tK6j2FCQJYsku8tuaxuYrJ/qThz +iOraDrwHv/wo84K5J20na/xEroQYZvVudRJZj/cjBdgzjzqFAUA= +=wl50 +-----END PGP SIGNATURE----- + + diff --git a/argon_5.patch b/argon_5.patch new file mode 100644 index 000000000000..bca5449f1455 --- /dev/null +++ b/argon_5.patch @@ -0,0 +1,96 @@ +--- + Makefile.util.def | 6 +++++- + grub-core/Makefile.core.def | 2 +- + grub-core/disk/luks2.c | 13 +++++++++++-- + 3 files changed, 17 insertions(+), 4 deletions(-) + +diff --git a/Makefile.util.def b/Makefile.util.def +index f8b356cc1..39fe9cb7c 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -3,7 +3,7 @@ AutoGen definitions Makefile.tpl; + library = { + name = libgrubkern.a; + cflags = '$(CFLAGS_GNULIB)'; +- cppflags = '$(CPPFLAGS_GNULIB) -I$(srcdir)/grub-core/lib/json'; ++ cppflags = '$(CPPFLAGS_GNULIB) -I$(srcdir)/grub-core/lib/json -I$(srcdir)/grub-core/lib/argon2'; + + common = util/misc.c; + common = grub-core/kern/command.c; +@@ -36,6 +36,10 @@ library = { + common = grub-core/kern/misc.c; + common = grub-core/kern/partition.c; + common = grub-core/lib/crypto.c; ++ common = grub-core/lib/argon2/argon2.c; ++ common = grub-core/lib/argon2/core.c; ++ common = grub-core/lib/argon2/ref.c; ++ common = grub-core/lib/argon2/blake2/blake2b.c; + common = grub-core/lib/json/json.c; + common = grub-core/disk/luks.c; + common = grub-core/disk/luks2.c; +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 3a004e88c..e5e5b216b 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1197,7 +1197,7 @@ module = { + common = disk/luks2.c; + common = lib/gnulib/base64.c; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; +- cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/json'; ++ cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/json -I$(srcdir)/lib/argon2'; + }; + + module = { +diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c +index 02822c777..2ec0d4116 100644 +--- a/grub-core/disk/luks2.c ++++ b/grub-core/disk/luks2.c +@@ -27,6 +27,7 @@ + #include <grub/partition.h> + #include <grub/i18n.h> + ++#include <argon2.h> + #include <base64.h> + #include <json.h> + +@@ -448,8 +449,16 @@ luks2_decrypt_key (grub_uint8_t *out_key, + { + case LUKS2_KDF_TYPE_ARGON2I: + case LUKS2_KDF_TYPE_ARGON2ID: +- ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Argon2 not supported"); +- goto err; ++ ret = argon2_hash (k->kdf.u.argon2.time, k->kdf.u.argon2.memory, k->kdf.u.argon2.cpus, ++ passphrase, passphraselen, salt, saltlen, area_key, k->area.key_size, ++ k->kdf.type == LUKS2_KDF_TYPE_ARGON2I ? Argon2_i : Argon2_id, ++ ARGON2_VERSION_NUMBER); ++ if (ret) ++ { ++ grub_dprintf ("luks2", "Argon2 failed: %s\n", argon2_error_message (ret)); ++ goto err; ++ } ++ break; + case LUKS2_KDF_TYPE_PBKDF2: + hash = grub_crypto_lookup_md_by_name (k->kdf.u.pbkdf2.hash); + if (!hash) +-- +2.32.0 + + +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEP4yQACgkQVbJhu7ck +PpSm3g//WJHea428olgraKZcMWFBq4CpJJUYtaDq/Sxdy/VubY42Or3s90mKTFPw +xiu3/r/WQXnzR5QnwhsVsk7eQNz2oxR5Bpw8XvNBFhMvMrCc8T+RhUeytsCFSjCg +koW7Bub3TLhUnzPH/qHaXtK8inKk3G49fUi+iUFhj6YcMZFIKbiKX5B/SseswUwm +9hJeA2aqgflOQT2ucEKxNJ7VQoqdn7QE0dxWd/7wUPoirBvePa3NcYcp/+QJ+gfr +77N8Sb4hPhU63apnTbzkq72jLyng4h1LTnQMFvcfs1ktUPHWOKHnDxYgLAVEAMKR +nKpfDyEGaAXtO1s2outPHykBnNzQYFiz06vFMoLfXr986m2/5I6XSBIKhEC3XUbO +ZO2Kbys5u/T+O5j9KNlTKX2/9+XhCQwGZP+UXtz2KxTUQm1ZKKjJvNa7LLe6qm0c +ps3YV20jXp5bI7Nsw0MN6+Vu67UXHcr0reCwhI4A/oUrNAVG3DYqaxQAbpKDcIlk +FtVrmwAC3gOw2vjT6Z5T5CGD3jwLX1zN50G8GiSIMzYN7o0S8fU1AEdNpkfZAG8h ++CgCuSBwBY0wfDX1SKWczhVcodJ+E6hoPaXNhk4f31cvNFYuq0IUPKJ4WxNU3NJI +56TdrKzrS322Pb16CC3GX7MgSlTvv3LcbX3Akv2SOpeOxsyc3OI= +=Vrqy +-----END PGP SIGNATURE----- + + diff --git a/detect-archlinux-initramfs.patch b/detect-archlinux-initramfs.patch new file mode 100644 index 000000000000..0f5568bf219e --- /dev/null +++ b/detect-archlinux-initramfs.patch @@ -0,0 +1,49 @@ +From 058d08a025f9a6ec77d5ddd1fc62c7bd6abe1a52 Mon Sep 17 00:00:00 2001 +From: Christian Hesse <mail@eworm.de> +Date: Wed, 10 Mar 2021 18:40:00 +0100 +Subject: [PATCH] 10_linux: detect archlinux initramfs +--- + util/grub.d/10_linux.in | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index e8b01c0d0..e703dcdb0 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -93,6 +93,8 @@ linux_entry () + case $type in + recovery) + title="$(gettext_printf "%s, with Linux %s (recovery mode)" "${os}" "${version}")" ;; ++ fallback) ++ title="$(gettext_printf "%s, with Linux %s (fallback initramfs)" "${os}" "${version}")" ;; + *) + title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;; + esac +@@ -198,7 +200,7 @@ while [ "x$list" != "x" ] ; do + basename=`basename $linux` + dirname=`dirname $linux` + rel_dirname=`make_system_path_relative_to_its_root $dirname` +- version=`echo $basename | sed -e "s,^[^0-9]*-,,g"` ++ version=`echo $basename | sed -e "s,vmlinuz-,,g"` + alt_version=`echo $version | sed -e "s,\.old$,,g"` + linux_root_device_thisversion="${LINUX_ROOT_DEVICE}" + +@@ -285,6 +287,18 @@ while [ "x$list" != "x" ] ; do + + linux_entry "${OS}" "${version}" advanced \ + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" ++ ++ if test -e "${dirname}/initramfs-${version}-fallback.img" ; then ++ initrd="initramfs-${version}-fallback.img" ++ ++ if test -n "${initrd}" ; then ++ gettext_printf "Found fallback initrd image(s) in %s:%s\n" "${dirname}" "${initrd_extra} ${initrd}" >&2 ++ fi ++ ++ linux_entry "${OS}" "${version}" fallback \ ++ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" ++ fi ++ + if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then + linux_entry "${OS}" "${version}" recovery \ + "single ${GRUB_CMDLINE_LINUX}" diff --git a/grub-improved-luks2-git.install b/grub-improved-luks2-git.install new file mode 100644 index 000000000000..c13ef99c77c5 --- /dev/null +++ b/grub-improved-luks2-git.install @@ -0,0 +1,17 @@ +#!/bin/sh + +post_upgrade() { + # We used to package /boot/grub/grub.cfg, but there is no reason to. + # Remove the file from package, but move real file back in place. + if [ ! -f /boot/grub/grub.cfg -a -f /boot/grub/grub.cfg.pacsave ]; then + mv /boot/grub/grub.cfg.pacsave /boot/grub/grub.cfg + fi +} + +post_install() { + cat << 'EOM' +Generate your bootloader configuration with: + grub-mkconfig -o /boot/grub/grub.cfg +EOM +} + diff --git a/grub-install_luks2.patch b/grub-install_luks2.patch new file mode 100644 index 000000000000..3748d4b399eb --- /dev/null +++ b/grub-install_luks2.patch @@ -0,0 +1,263 @@ +diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c +index ccfacb63a..1aaac1da6 100644 +--- a/grub-core/disk/luks2.c ++++ b/grub-core/disk/luks2.c +@@ -350,8 +350,15 @@ luks2_scan (grub_disk_t disk, grub_cryptomount_args_t cargs) + { + grub_cryptodisk_t cryptodisk; + grub_luks2_header_t header; ++ grub_luks2_keyslot_t keyslot; ++ grub_luks2_digest_t digest; ++ grub_luks2_segment_t segment; ++ char *json_header = NULL, *ptr; ++ grub_size_t candidate_key_len = 0, json_idx, size; + char uuid[sizeof (header.uuid) + 1]; + grub_size_t i, j; ++ grub_err_t ret; ++ grub_json_t *json = NULL, keyslots; + + if (cargs->check_boot) + return NULL; +@@ -361,6 +368,157 @@ luks2_scan (grub_disk_t disk, grub_cryptomount_args_t cargs) + grub_errno = GRUB_ERR_NONE; + return NULL; + } ++ json_header = grub_zalloc (grub_be_to_cpu64 (header.hdr_size) - sizeof (header)); ++ if (!json_header) ++ return GRUB_ERR_OUT_OF_MEMORY; ++ ++ /* Read the JSON area. */ ++ ret = grub_disk_read (disk, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header), ++ grub_be_to_cpu64 (header.hdr_size) - sizeof (header), json_header); ++ if (ret) ++ goto err; ++ ++ ptr = grub_memchr (json_header, 0, grub_be_to_cpu64 (header.hdr_size) - sizeof (header)); ++ if (!ptr) ++ goto err; ++ ++ ret = grub_json_parse (&json, json_header, grub_be_to_cpu64 (header.hdr_size)); ++ if (ret) ++ { ++ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid LUKS2 JSON header"); ++ goto err; ++ } ++ ++ if (grub_json_getvalue (&keyslots, json, "keyslots") || ++ grub_json_getsize (&size, &keyslots)) ++ { ++ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get keyslots"); ++ goto err; ++ } ++ ++ if (grub_disk_native_sectors (disk) == GRUB_DISK_SIZE_UNKNOWN) ++ { ++ /* FIXME: Allow use of source disk, and maybe cause errors in read. */ ++ grub_dprintf ("luks2", "Source disk %s has an unknown size, " ++ "conservatively returning error\n", disk->name); ++ ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source device"); ++ goto err; ++ } ++ ++ cryptodisk = grub_zalloc (sizeof (*cryptodisk)); ++ if (!cryptodisk) ++ return NULL; ++ ++ ++ /* Try all keyslot */ ++ for (json_idx = 0; json_idx < size; json_idx++) ++ { ++ char indexstr[21]; /* log10(2^64) ~ 20, plus NUL character. */ ++ typeof (disk->total_sectors) max_crypt_sectors = 0; ++ ++ grub_errno = GRUB_ERR_NONE; ++ ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, json_idx); ++ if (ret) ++ goto err; ++ if (grub_errno != GRUB_ERR_NONE) ++ grub_dprintf ("luks2", "Ignoring unhandled error %d from luks2_get_keyslot\n", grub_errno); ++ ++ if (keyslot.priority == 0) ++ { ++ grub_dprintf ("luks2", "Ignoring keyslot \"%" PRIuGRUB_UINT64_T "\" due to priority\n", keyslot.idx); ++ continue; ++ } ++ ++ grub_dprintf ("luks2", "Trying keyslot \"%" PRIuGRUB_UINT64_T "\"\n", keyslot.idx); ++ ++ /* Sector size should be one of 512, 1024, 2048, or 4096. */ ++ if (!(segment.sector_size == 512 || segment.sector_size == 1024 || ++ segment.sector_size == 2048 || segment.sector_size == 4096)) ++ { ++ grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" sector" ++ " size %" PRIuGRUB_UINT64_T " is not one of" ++ " 512, 1024, 2048, or 4096\n", ++ segment.idx, segment.sector_size); ++ continue; ++ } ++ ++ /* Set up disk according to keyslot's segment. */ ++ cryptodisk->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL); ++ cryptodisk->log_sector_size = grub_log2ull (segment.sector_size); ++ /* Set to the source disk/partition size, which is the maximum we allow. */ ++ max_crypt_sectors = grub_disk_native_sectors (disk); ++ max_crypt_sectors = grub_convert_sector (max_crypt_sectors, GRUB_DISK_SECTOR_BITS, ++ cryptodisk->log_sector_size); ++ ++ if (max_crypt_sectors < cryptodisk->offset_sectors) ++ { ++ grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" has offset" ++ " %" PRIuGRUB_UINT64_T " which is greater than" ++ " source disk size %" PRIuGRUB_UINT64_T "," ++ " skipping\n", segment.idx, cryptodisk->offset_sectors, ++ max_crypt_sectors); ++ continue; ++ } ++ ++ if (grub_strcmp (segment.size, "dynamic") == 0) ++ cryptodisk->total_sectors = max_crypt_sectors - cryptodisk->offset_sectors; ++ else ++ { ++ grub_errno = GRUB_ERR_NONE; ++ ++ /* Convert segment.size to sectors, rounding up to nearest sector */ ++ cryptodisk->total_sectors = grub_strtoull (segment.size, NULL, 10); ++ ++ if (grub_errno == GRUB_ERR_NONE) ++ { ++ cryptodisk->total_sectors = ALIGN_UP (cryptodisk->total_sectors, ++ 1 << cryptodisk->log_sector_size); ++ cryptodisk->total_sectors >>= cryptodisk->log_sector_size; ++ } ++ else if (grub_errno == GRUB_ERR_BAD_NUMBER) ++ { ++ grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" size" ++ " \"%s\" is not a parsable number," ++ " skipping keyslot\n", ++ segment.idx, segment.size); ++ continue; ++ } ++ else if (grub_errno == GRUB_ERR_OUT_OF_RANGE) ++ { ++ /* ++ * There was an overflow in parsing segment.size, so disk must ++ * be very large or the string is incorrect. ++ * ++ * TODO: Allow reading of at least up max_crypt_sectors. Really, ++ * its very unlikely one would be booting from such a large drive ++ * anyway. Use another smaller LUKS2 boot device. ++ */ ++ grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" size" ++ " %s overflowed 64-bit unsigned integer," ++ " skipping keyslot\n", segment.idx, segment.size); ++ continue; ++ } ++ } ++ ++ if (cryptodisk->total_sectors == 0) ++ { ++ grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" has zero" ++ " sectors, skipping\n", segment.idx); ++ continue; ++ } ++ else if (max_crypt_sectors < (cryptodisk->offset_sectors + cryptodisk->total_sectors)) ++ { ++ grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" has last" ++ " data position greater than source disk size," ++ " the end of the crypto device will be" ++ " inaccessible\n", segment.idx); ++ ++ /* Allow decryption up to the end of the source disk. */ ++ cryptodisk->total_sectors = max_crypt_sectors - cryptodisk->offset_sectors; ++ } ++ ++ break; ++ } + + for (i = 0, j = 0; i < sizeof (header.uuid); i++) + if (header.uuid[i] != '-') +@@ -373,15 +531,16 @@ luks2_scan (grub_disk_t disk, grub_cryptomount_args_t cargs) + return NULL; + } + +- cryptodisk = grub_zalloc (sizeof (*cryptodisk)); +- if (!cryptodisk) +- return NULL; +- + COMPILE_TIME_ASSERT (sizeof (cryptodisk->uuid) >= sizeof (uuid)); + grub_memcpy (cryptodisk->uuid, uuid, sizeof (uuid)); + + cryptodisk->modname = "luks2"; + return cryptodisk; ++err: ++ grub_free (json_header); ++ grub_json_free (json); ++ grub_errno = ret; ++ return NULL; + } + + static grub_err_t +diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c +index 9ba5c9865..9ae1780c9 100644 +--- a/grub-core/osdep/devmapper/getroot.c ++++ b/grub-core/osdep/devmapper/getroot.c +@@ -141,7 +141,12 @@ grub_util_get_dm_abstraction (const char *os_dev) + if (strncmp (uuid, "CRYPT-LUKS1-", 12) == 0) + { + grub_free (uuid); +- return GRUB_DEV_ABSTRACTION_LUKS; ++ return GRUB_DEV_ABSTRACTION_LUKS1; ++ } ++ if (strncmp (uuid, "CRYPT-LUKS2-", 12) == 0) ++ { ++ grub_free (uuid); ++ return GRUB_DEV_ABSTRACTION_LUKS2; + } + + grub_free (uuid); +@@ -179,7 +184,7 @@ grub_util_pull_devmapper (const char *os_dev) + grub_util_pull_device (subdev); + } + } +- if (uuid && strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0 ++ if (uuid && (strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0 || strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0) + && lastsubdev) + { + char *grdev = grub_util_get_grub_dev (lastsubdev); +@@ -249,7 +254,8 @@ grub_util_get_devmapper_grub_dev (const char *os_dev) + return grub_dev; + } + +- case GRUB_DEV_ABSTRACTION_LUKS: ++ case GRUB_DEV_ABSTRACTION_LUKS1: ++ case GRUB_DEV_ABSTRACTION_LUKS2: + { + char *dash; + +diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h +index 73fa2d34a..1a27faf28 100644 +--- a/include/grub/emu/getroot.h ++++ b/include/grub/emu/getroot.h +@@ -29,7 +29,8 @@ enum grub_dev_abstraction_types { + GRUB_DEV_ABSTRACTION_NONE, + GRUB_DEV_ABSTRACTION_LVM, + GRUB_DEV_ABSTRACTION_RAID, +- GRUB_DEV_ABSTRACTION_LUKS, ++ GRUB_DEV_ABSTRACTION_LUKS1, ++ GRUB_DEV_ABSTRACTION_LUKS2, + GRUB_DEV_ABSTRACTION_GELI, + }; + +diff --git a/util/getroot.c b/util/getroot.c +index a5eaa64fd..76d86c174 100644 +--- a/util/getroot.c ++++ b/util/getroot.c +@@ -100,7 +100,8 @@ grub_util_pull_device (const char *os_dev) + case GRUB_DEV_ABSTRACTION_LVM: + grub_util_pull_lvm_by_command (os_dev); + /* Fallthrough - in case that lvm-tools are unavailable. */ +- case GRUB_DEV_ABSTRACTION_LUKS: ++ case GRUB_DEV_ABSTRACTION_LUKS1: ++ case GRUB_DEV_ABSTRACTION_LUKS2: + grub_util_pull_devmapper (os_dev); + return; diff --git a/grub.default b/grub.default new file mode 100644 index 000000000000..6fd21c7fd223 --- /dev/null +++ b/grub.default @@ -0,0 +1,57 @@ +# GRUB boot loader configuration + +GRUB_DEFAULT=0 +GRUB_TIMEOUT=5 +GRUB_DISTRIBUTOR="Arch" +GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet" +GRUB_CMDLINE_LINUX="" + +# Preload both GPT and MBR modules so that they are not missed +GRUB_PRELOAD_MODULES="part_gpt part_msdos" + +# Uncomment to enable booting from LUKS encrypted devices +#GRUB_ENABLE_CRYPTODISK=y + +# Set to 'countdown' or 'hidden' to change timeout behavior, +# press ESC key to display menu. +GRUB_TIMEOUT_STYLE=menu + +# Uncomment to use basic console +GRUB_TERMINAL_INPUT=console + +# Uncomment to disable graphical terminal +#GRUB_TERMINAL_OUTPUT=console + +# The resolution used on graphical terminal +# note that you can use only modes which your graphic card supports via VBE +# you can see them in real GRUB with the command `vbeinfo' +GRUB_GFXMODE=auto + +# Uncomment to allow the kernel use the same resolution used by grub +GRUB_GFXPAYLOAD_LINUX=keep + +# Uncomment if you want GRUB to pass to the Linux kernel the old parameter +# format "root=/dev/xxx" instead of "root=/dev/disk/by-uuid/xxx" +#GRUB_DISABLE_LINUX_UUID=true + +# Uncomment to disable generation of recovery mode menu entries +GRUB_DISABLE_RECOVERY=true + +# Uncomment and set to the desired menu colors. Used by normal and wallpaper +# modes only. Entries specified as foreground/background. +#GRUB_COLOR_NORMAL="light-blue/black" +#GRUB_COLOR_HIGHLIGHT="light-cyan/blue" + +# Uncomment one of them for the gfx desired, a image background or a gfxtheme +#GRUB_BACKGROUND="/path/to/wallpaper" +#GRUB_THEME="/path/to/gfxtheme" + +# Uncomment to get a beep at GRUB start +#GRUB_INIT_TUNE="480 440 1" + +# Uncomment to make GRUB remember the last selection. This requires +# setting 'GRUB_DEFAULT=saved' above. +#GRUB_SAVEDEFAULT=true + +# Uncomment to disable submenus in boot menu +#GRUB_DISABLE_SUBMENU=y diff --git a/mm_1.patch b/mm_1.patch new file mode 100644 index 000000000000..146dcefc911f --- /dev/null +++ b/mm_1.patch @@ -0,0 +1,87 @@ +--- + grub-core/kern/dl.c | 20 -------------------- + grub-core/kern/mm.c | 8 -------- + include/grub/dl.h | 1 - + 3 files changed, 29 deletions(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index 48f8a7907..a62dbeebb 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -803,23 +803,3 @@ grub_dl_unload (grub_dl_t mod) + grub_free (mod); + return 1; + } +- +-/* Unload unneeded modules. */ +-void +-grub_dl_unload_unneeded (void) +-{ +- /* Because grub_dl_remove modifies the list of modules, this +- implementation is tricky. */ +- grub_dl_t p = grub_dl_head; +- +- while (p) +- { +- if (grub_dl_unload (p)) +- { +- p = grub_dl_head; +- continue; +- } +- +- p = p->next; +- } +-} +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index c070afc62..e0e580270 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -360,14 +360,6 @@ grub_memalign (grub_size_t align, grub_size_t size) + count++; + goto again; + +-#if 0 +- case 1: +- /* Unload unneeded modules. */ +- grub_dl_unload_unneeded (); +- count++; +- goto again; +-#endif +- + default: + break; + } +diff --git a/include/grub/dl.h b/include/grub/dl.h +index b3753c9ca..536717776 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -203,7 +203,6 @@ grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name); + grub_dl_t grub_dl_load_core (void *addr, grub_size_t size); + grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size); + int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod); +-extern void grub_dl_unload_unneeded (void); + extern int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod); + extern int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod); + extern int EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod); +-- +2.32.0 + + +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEY9dUACgkQVbJhu7ck +PpQ9xg/9E2CLh95L+w3TAgbclAkA6/KaVDnOy+woDUwGRv2yVxtTqMWakOSbZruD +JTFCNPQdug+HHjqGFkjsS0nBu9U+DRlb/5RTOSyK+BKEnp3f9/OlaJnvHwy1AKe1 +Vhg4KdkXdmQ99ER8at7JMLs7n0KaetMegpLHVRCOuxr7VbtiGaJD1VcQS8ubIbwh +jkvzJQVmJPt4dyD1I88oB2Xm/QKLimPtMCLNcWh0fXTUBBctOS6vZiacvMlF2/HX +e7tWaNQMMayS1uZJL8B4Bl31iWFF7pm6CEZrPA4LK9Oggj7NUri+W1QLpzjUeBSw +lJ6ZMfZXccUwrdqF7NDpxPuVe7cYUUIgcHmzxHWK028JHicaeA2v7/rZxlBkFqS5 +OF7JSD7ncngu8TAYFzhaHKRFouj9APY3x7q/IV1yuBOgw8yhD8T+hevoekqj8Dvg +jbxIBaWulR/IyPcCEofapIr6xGSpQxPtwQIzTnXa8yTdguf832rUG3wguHeWfHQq +uTiBYjzDMglon/ySlpPnv6z33TRZLHRcyhXeLjc9DJTgQIl3n4XZGLAf+itGTKOL +EUPTs2b30oX7wYTLgBxtPpbmtNRVxEfY1nNxDp3U9ffQHkEaKkvfrtI8Fl3dK1nB +XtjvaGDt/DfYOlWoyT9qwSsSKO7P/GRp2Fjiz5r9kISxwFuPLdA= +=jVOn +-----END PGP SIGNATURE----- + + diff --git a/mm_2.patch b/mm_2.patch new file mode 100644 index 000000000000..817b017e2b39 --- /dev/null +++ b/mm_2.patch @@ -0,0 +1,89 @@ +--- + grub-core/kern/mm.c | 10 ++++++++++ + include/grub/mm.h | 16 ++++++++++++++++ + 2 files changed, 26 insertions(+) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index e0e580270..2df835392 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -81,6 +81,7 @@ + + + grub_mm_region_t grub_mm_base; ++grub_mm_add_region_func_t grub_mm_add_region_fn; + + /* Get a header from the pointer PTR, and set *P and *R to a pointer + to the header and a pointer to its region, respectively. PTR must +@@ -360,6 +361,15 @@ grub_memalign (grub_size_t align, grub_size_t size) + count++; + goto again; + ++ case 1: ++ /* Request additional pages. */ ++ count++; ++ ++ if (grub_mm_add_region_fn && grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) ++ goto again; ++ ++ /* fallthrough */ ++ + default: + break; + } +diff --git a/include/grub/mm.h b/include/grub/mm.h +index 9c38dd3ca..afde57d2e 100644 +--- a/include/grub/mm.h ++++ b/include/grub/mm.h +@@ -20,6 +20,7 @@ + #ifndef GRUB_MM_H + #define GRUB_MM_H 1 + ++#include <grub/err.h> + #include <grub/types.h> + #include <grub/symbol.h> + #include <config.h> +@@ -28,6 +29,21 @@ + # define NULL ((void *) 0) + #endif + ++#define GRUB_MM_ADD_REGION_NONE 0 ++#define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0) ++ ++/* ++ * Function used to request memory regions of `grub_size_t` bytes. The second ++ * parameter is a bitfield of `GRUB_MM_ADD_REGION` flags. ++ */ ++typedef grub_err_t (*grub_mm_add_region_func_t) (grub_size_t, unsigned int); ++ ++/* ++ * Set this function pointer to enable adding memory-regions at runtime in case ++ * a memory allocation cannot be satisfied with existing regions. ++ */ ++extern grub_mm_add_region_func_t EXPORT_VAR(grub_mm_add_region_fn); ++ + void grub_mm_init_region (void *addr, grub_size_t size); + void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size); + void *EXPORT_FUNC(grub_malloc) (grub_size_t size); +-- +2.32.0 + + +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEY9dkACgkQVbJhu7ck +PpScOQ//UbROjKLOAviqmbQoJLJHxwcOKGzpSWDmHI4mjXxc+wafFL6rPOa75//8 +R5QoYbEN1uCSkrK4Mgjn4aqwCHp9PyL+thJXuryzHNVtyPrz96aUi4kwXWfsX6Jw +O6a1JpqTJieJyRcTWG91i6k8SMdtPuNXAt/tsllbRy6jp/fYDz4inJHgtG6p//WI +4ORbW4OcFO7n3FCFa1l4EYqsaWJDSkAuKLk5QUKgpAKn3YEc1uL32TgFt77jIjSi +4RIVZT4kNv6aVhCfwLQQW8g1BZkTYO5ehzDXB6SnI+4CjxeGwVMgeZFF6NbU68LX +B4ZBO+SfTpwMoexHykM3VtVEzAQfmY8idIeS0m0ptC5j8rlz/oxI3TrqHkoTxgSU +ZhyrqNOdMOnYx2jLqnh79qmizEebai1nPA/bl2Jke0lQvWSORH9h/HpfN3vCFTW3 +Vw8nfZS7MgbU0hk/14rFd/1TWV9m+aEgUITYxL1cnOI70V/Ne+HO41O+NJh6fT14 +5yZScrJ3FD8BkvJi/IW4PBZ2Iq8n7u9/UIvhKiNisQuHr13jgaGF2NYm6RYYZANg +1qz7wkf3ora3nN74fu26ohWejlC9hcNGYlIjBI0iRF5E6IJ/mT4jq8PVJ0DJnrUc +8AeLPgnW6BiPgTUevUOODo5jGZQ3oJ6zFumZNLl28wN0Lr9Mqnw= +=+47H +-----END PGP SIGNATURE----- + + diff --git a/mm_3.patch b/mm_3.patch new file mode 100644 index 000000000000..8f709d90dd77 --- /dev/null +++ b/mm_3.patch @@ -0,0 +1,99 @@ +--- + grub-core/kern/efi/mm.c | 35 +++-------------------------------- + 1 file changed, 3 insertions(+), 32 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 9838fb2f5..4d276bc87 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -38,9 +38,8 @@ + a multiplier of 4KB. */ + #define MEMORY_MAP_SIZE 0x3000 + +-/* The minimum and maximum heap size for GRUB itself. */ +-#define MIN_HEAP_SIZE 0x100000 +-#define MAX_HEAP_SIZE (1600 * 0x100000) ++/* The default heap size for GRUB itself in bytes. */ ++#define DEFAULT_HEAP_SIZE 0x100000 + + static void *finish_mmap_buf = 0; + static grub_efi_uintn_t finish_mmap_size = 0; +@@ -478,23 +477,6 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + return filtered_desc; + } + +-/* Return the total number of pages. */ +-static grub_efi_uint64_t +-get_total_pages (grub_efi_memory_descriptor_t *memory_map, +- grub_efi_uintn_t desc_size, +- grub_efi_memory_descriptor_t *memory_map_end) +-{ +- grub_efi_memory_descriptor_t *desc; +- grub_efi_uint64_t total = 0; +- +- for (desc = memory_map; +- desc < memory_map_end; +- desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) +- total += desc->num_pages; +- +- return total; +-} +- + /* Add memory regions. */ + static void + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, +@@ -583,8 +565,6 @@ grub_efi_mm_init (void) + grub_efi_memory_descriptor_t *filtered_memory_map_end; + grub_efi_uintn_t map_size; + grub_efi_uintn_t desc_size; +- grub_efi_uint64_t total_pages; +- grub_efi_uint64_t required_pages; + int mm_status; + + /* Prepare a memory region to store two memory maps. */ +@@ -624,22 +604,13 @@ grub_efi_mm_init (void) + filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, + desc_size, memory_map_end); + +- /* By default, request a quarter of the available memory. */ +- total_pages = get_total_pages (filtered_memory_map, desc_size, +- filtered_memory_map_end); +- required_pages = (total_pages >> 2); +- if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE)) +- required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE); +- else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE)) +- required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE); +- + /* Sort the filtered descriptors, so that GRUB can allocate pages + from smaller regions. */ + sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); + + /* Allocate memory regions for GRUB's memory management. */ + add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, required_pages); ++ filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE)); + + #if 0 + /* For debug. */ +-- +2.32.0 + + +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEY9d0ACgkQVbJhu7ck +PpQn3w//WJu1uNsOVPLPU6TPLWVvEuPApH97bUrMjNnvzNYbPlR82ym+u+zMGoJ7 +Es77CEqgMDhCOxdD3oEi9PMZtXASgnw7uGKJycdGZOObzGBu4IZ4ZWQdWVfwlIZp +4Qlc+ROTQoEWyLWpB/mJwrcXX8ILOdeRSX071zfHhJNcauEWMKEE88M/HH0VxCeT +ZHGrmSzBE9gu3HQ8kir9wibroBeI4siW1feR5PWDmp/3R96z5MKN2xyy6BkH3Z0M +sbl7zrlSu+NSnsmLzcH8oyfCBI+2soXgmGHQ1QCY8v8rbNx77sXKxTZniK7lH70Z +X+0pcRm8aEYaT4ReWAxqJFykMn/9zfX4XRqEUBXTK/vWzSB4/5v0RLiUftvLfl7A +Du8w+mocoOELAwCi4+VydHO9jUMnHJAlR+HAazd2jifi9jWsU7gxkD7FO+zFlble +Eq5XFRgKzYmDHzPbD3udEH1+8792eGa0BjXwmIGpvFYfHpo4Jm24obykVVpH2m6j +be99L+9A7PIxUg3GB6RAerR2Lc6a+nPRC47Jrp63BGtQ7SHPKCY7lzvw7q0nv0d+ +FmlcXQvOoeQeUNUzCaEmHaRP/WKSeeKL86Rp6pUIOXho6ON5llwSexJYEJlWA6rj +p9wPIz8BA0iHFMix/Ch9DmUg1BNIE2vGaf+qhPmPNMF1ZFonbl8= +=L7Ky +-----END PGP SIGNATURE----- + + diff --git a/mm_4.patch b/mm_4.patch new file mode 100644 index 000000000000..6a141025b67f --- /dev/null +++ b/mm_4.patch @@ -0,0 +1,101 @@ +--- + grub-core/kern/efi/mm.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 4d276bc87..cfc6a67fc 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -504,7 +504,7 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + + addr = grub_efi_allocate_pages_real (start, pages, + GRUB_EFI_ALLOCATE_ADDRESS, +- GRUB_EFI_LOADER_CODE); ++ GRUB_EFI_LOADER_CODE); + if (! addr) + grub_fatal ("cannot allocate conventional memory %p with %u pages", + (void *) ((grub_addr_t) start), +@@ -556,8 +556,8 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map, + } + #endif + +-void +-grub_efi_mm_init (void) ++static grub_err_t ++grub_efi_mm_add_regions (grub_efi_uint64_t required_bytes) + { + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; +@@ -570,7 +570,7 @@ grub_efi_mm_init (void) + /* Prepare a memory region to store two memory maps. */ + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + if (! memory_map) +- grub_fatal ("cannot allocate memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory"); + + /* Obtain descriptors for available memory. */ + map_size = MEMORY_MAP_SIZE; +@@ -588,14 +588,14 @@ grub_efi_mm_init (void) + + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size)); + if (! memory_map) +- grub_fatal ("cannot allocate memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory"); + + mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, + &desc_size, 0); + } + + if (mm_status < 0) +- grub_fatal ("cannot get memory map"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot get memory map"); + + memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); + +@@ -610,7 +610,7 @@ grub_efi_mm_init (void) + + /* Allocate memory regions for GRUB's memory management. */ + add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE)); ++ filtered_memory_map_end, BYTES_TO_PAGES (required_bytes)); + + #if 0 + /* For debug. */ +@@ -628,6 +628,15 @@ grub_efi_mm_init (void) + /* Release the memory maps. */ + grub_efi_free_pages ((grub_addr_t) memory_map, + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); ++ ++ return GRUB_ERR_NONE; ++} ++ ++void ++grub_efi_mm_init (void) ++{ ++ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE) ++ grub_fatal ("%s", grub_errmsg); + } + + #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) +-- +2.32.0 + + +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEY9eEACgkQVbJhu7ck +PpToNRAAmgY8k/pUck1W5suQpoJ3Ck6Kxuh6IUodllFPZskfgMAsddwHnGZCyqMA +rQhxvAizZyS8yoeuQyNeWZQT1QA66XgZNJ7V1jO2Yr3o1fZ4SkNs7pszZbgdfU91 +1koyjg070O7CsdJZsOstCw9BbfuJxb6cfICZzcJjKC1ecOPKsHUzbH8V03IImnes +dBM/VGoGXvazBg7eEVA6O6OvtpCtftHrhokdTDDL0dfhRNf9ps/FDI1sddmycmex +0GBljoPIT7ymCxJ0UxSHotwMExm/odh86jfihcfhWGh16MeAYTaMJIl6Q6RaK9jr +Gzdn65ZHHB7kUAt3JEi72oYw7tnaBOX8wcWe/vgp4XJ8d63T5E44svzUxetS+BvQ +hvuASM2hciIo4Pj33v96rzs9cth549DsBswra3yJlrTKZzyIcDLbGyuCs+cpa1Ek +02I0vlTbZLTAh86vGHESKmLaANDIxzh505fY8unQ61xe4SgLNa6B3Nf/KkwQh0uY +ceClslAq1WgLwoDMeyvCIGO4W7FGvoirH36CXgfOYVGiL4SsZ58FsGNO+7SS7FM7 +68DpuvpzxMUPTD4YOpNE7VIZV59S0/9g3+yL+fcn229jaCzbo48PvBfOUUyYBqw3 +onAqs5TQhn0KS+5zrm1ORnGjN5IXjxu8c+FPm9JGYLw+o6DcwBE= +=8bqP +-----END PGP SIGNATURE----- + + diff --git a/mm_5.patch b/mm_5.patch new file mode 100644 index 000000000000..06ecaefab503 --- /dev/null +++ b/mm_5.patch @@ -0,0 +1,85 @@ +--- + grub-core/kern/efi/mm.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index cfc6a67fc..ced3ee5e7 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -478,7 +478,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + } + + /* Add memory regions. */ +-static void ++static grub_err_t + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end, +@@ -506,9 +506,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + GRUB_EFI_ALLOCATE_ADDRESS, + GRUB_EFI_LOADER_CODE); + if (! addr) +- grub_fatal ("cannot allocate conventional memory %p with %u pages", +- (void *) ((grub_addr_t) start), +- (unsigned) pages); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "cannot allocate conventional memory %p with %u pages", ++ (void *) ((grub_addr_t) start), (unsigned) pages); + + grub_mm_init_region (addr, PAGES_TO_BYTES (pages)); + +@@ -518,7 +518,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + } + + if (required_pages > 0) +- grub_fatal ("too little memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "too little memory"); ++ ++ return GRUB_ERR_NONE; + } + + void +@@ -565,6 +567,7 @@ grub_efi_mm_add_regions (grub_efi_uint64_t required_bytes) + grub_efi_memory_descriptor_t *filtered_memory_map_end; + grub_efi_uintn_t map_size; + grub_efi_uintn_t desc_size; ++ grub_err_t err; + int mm_status; + + /* Prepare a memory region to store two memory maps. */ +@@ -609,8 +612,11 @@ grub_efi_mm_add_regions (grub_efi_uint64_t required_bytes) + sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); + + /* Allocate memory regions for GRUB's memory management. */ +- add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, BYTES_TO_PAGES (required_bytes)); ++ err = add_memory_regions (filtered_memory_map, desc_size, ++ filtered_memory_map_end, ++ BYTES_TO_PAGES (required_bytes)); ++ if (err != GRUB_ERR_NONE) ++ return err; + + #if 0 + /* For debug. */ +-- +2.32.0 + + +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEY9eYACgkQVbJhu7ck +PpQ8oA//VdC2Bv1hz/RkaRrhMM2vg/MSOeCer4RUrDhXWh8Kvt8koc1D7ZoE9MO7 +p8h1wkIsEEOrxkF5rwf+D0ZTg6joJcAmXPU/A2BY3oXuMSbKgOY/9/vJfDJio2dt +UNeduTlAJ9YuFtEHEfGEGRVq5egajEoHlas91ScsiYKRqdQmHgkfXeEKGGTr3XMo +RE/FI1duWhmqgzS9kjDq0dbvTtXEBKRndcDPVxyXpFbl1GE+swJzAUsVRNW7PZe8 +IYopqz3+6wlp7jo80REtV6ndIw2/N1nvScCF/Mfn5VHf/ObDoWw4cnZvgI/5YEnZ +48v1gMPft95CBjijnoD+F29jFBB6zmK8lFUN4FNY+edoGtlNrmEoZB0FkQJLXWNp +TS6y4EEx9pJzPuxf2VAF5+eMBzqU6f8qZDoty3NMDPNTDXMr0SjeiSJGMfDdU1Qg +Ouk9/I7XOLi91QzbyJP4dpfsI78002rzyibOim8jZ8JFv4InKG1krj1JU2BnVj0h ++7OYIfmDkGZs5ZvZ5PdFgpzqqmlH6wXWZYUMaYHlK2c/mOnJ3ty4NV14cWb8YqrF +VQ3U5EUzUL+8sTQAxwGGCDuC+E6ZuqZ7qVx0O1c5OeOxVh7o3rPLQ24D9a+6J0iv +eGvcgaHX+abwi/1fVL2ItovrGiGtfLtxd8y9G0zctgDBrpqVfvU= +=u8uk +-----END PGP SIGNATURE----- + + diff --git a/mm_6.patch b/mm_6.patch new file mode 100644 index 000000000000..c7b370863461 --- /dev/null +++ b/mm_6.patch @@ -0,0 +1,81 @@ +--- + grub-core/kern/efi/mm.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index ced3ee5e7..f3d2e2b99 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -482,7 +482,8 @@ static grub_err_t + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end, +- grub_efi_uint64_t required_pages) ++ grub_efi_uint64_t required_pages, ++ unsigned int flags) + { + grub_efi_memory_descriptor_t *desc; + +@@ -496,6 +497,10 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + + start = desc->physical_start; + pages = desc->num_pages; ++ ++ if (pages < required_pages && (flags & GRUB_MM_ADD_REGION_CONSECUTIVE)) ++ continue; ++ + if (pages > required_pages) + { + start += PAGES_TO_BYTES (pages - required_pages); +@@ -559,7 +564,7 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map, + #endif + + static grub_err_t +-grub_efi_mm_add_regions (grub_efi_uint64_t required_bytes) ++grub_efi_mm_add_regions (grub_efi_uint64_t required_bytes, unsigned int flags) + { + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; +@@ -614,7 +619,8 @@ grub_efi_mm_add_regions (grub_efi_uint64_t required_bytes) + /* Allocate memory regions for GRUB's memory management. */ + err = add_memory_regions (filtered_memory_map, desc_size, + filtered_memory_map_end, +- BYTES_TO_PAGES (required_bytes)); ++ BYTES_TO_PAGES (required_bytes), ++ flags); + if (err != GRUB_ERR_NONE) + return err; + +@@ -641,8 +647,9 @@ grub_efi_mm_add_regions (grub_efi_uint64_t required_bytes) + void + grub_efi_mm_init (void) + { +- if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE) ++ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE, GRUB_MM_ADD_REGION_NONE) != GRUB_ERR_NONE) + grub_fatal ("%s", grub_errmsg); ++ grub_mm_add_region_fn = grub_efi_mm_add_regions; + } + + #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) +-- +2.32.0 + + +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEF9hrgiFbCdvenl/rVbJhu7ckPpQFAmEY9eoACgkQVbJhu7ck +PpSFbQ//Y5G9FkVKWEwCrB7KhbF9pcmTobET1Q7lvrVtK+XArMuZQn/aDTxjoXM/ +87qMkF2OTko79/z1nzveDODPtR1E48jqR41+Qz7CICOH+8oG2Ur+MZt5J2T2M/Gf +JsqJ26Fk36A86IoZHZ73yfHCWgtQo4+jckOLJkGbTmlriOWSOCfvCKIt7aF0Z2Wf +SkfEt0UMV6i81HKkZ6v+nPJJQmZQp+pTpOWr7hrjx/6nUT1QadVQoVL8YYKKxHcX +zMkT7hAg+D6vAVJhfOSt/VoMcBJeBK8Or2OD5gDOKcqZ19nixa1u3r6NnkkG10OH +PyVL35svdUMMiIC2LXy2YCf7hbrOCOuCk10sT8Q05TrDvFpkvOn6QcGhvcSXtzmB +5wju6EVqCtIrrcSYl3Y2bWjrKFZXL3w1vOUnObF3yae2soR2h3Nvgyg98J3Qoee+ +7dNYGs3WmDb3wF9p/0TY54g89ZotKwZUEuaVu7qtcp3y6HpmcZ1XbnA8Y3aWmdmm +EeiUKAMSacyqxt1QBWciQTs7BaXWwxj8hI8xDjpCEMVFCux4nxdw6aXQXqocAaor +mDhjjriqmwTRNpZnUlUkScwczSJuh5WqnLWj5RKC01drUlcbnJjvdsaU1VAvzEju +24KGNqanC+jc1ZqKcx4eeCQHF21x8+xgsmgjYJZ8PGptT0bg/Xc= +=PvkK +-----END PGP SIGNATURE----- + + |