diff options
Diffstat (limited to 'resources')
6 files changed, 2859 insertions, 0 deletions
| diff --git a/resources/grub/patches/0003-Add-CC0-license.patch b/resources/grub/patches/0003-Add-CC0-license.patch new file mode 100644 index 00000000..dc9060c3 --- /dev/null +++ b/resources/grub/patches/0003-Add-CC0-license.patch @@ -0,0 +1,42 @@ +From de6e7cc62522ce1be21bd2f06e7c15cd234b5426 Mon Sep 17 00:00:00 2001 +From: Ax333l <main@axelen.xyz> +Date: Thu, 17 Aug 2023 00:00:00 +0000 +Subject: [PATCH 1/6] Add CC0 license + +Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> +--- + 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 0bf40caa6..4011e2d15 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -470,7 +470,8 @@ grub_dl_check_license (grub_dl_t mod, Elf_Ehdr *e) +  +   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 a42c20bd1..7157a30aa 100644 +--- a/util/grub-module-verifierXX.c ++++ b/util/grub-module-verifierXX.c +@@ -236,7 +236,8 @@ check_license (const char * const filename, +   Elf_Shdr *s = find_section (arch, e, ".module_license", module_size); +   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.39.2 + diff --git a/resources/grub/patches/0004-Define-GRUB_UINT32_MAX.patch b/resources/grub/patches/0004-Define-GRUB_UINT32_MAX.patch new file mode 100644 index 00000000..be875e67 --- /dev/null +++ b/resources/grub/patches/0004-Define-GRUB_UINT32_MAX.patch @@ -0,0 +1,39 @@ +From 9edaaffac91d593a439e44bac3b6f5558f5a8245 Mon Sep 17 00:00:00 2001 +From: Ax333l <main@axelen.xyz> +Date: Thu, 17 Aug 2023 00:00:00 +0000 +Subject: [PATCH 2/6] Define GRUB_UINT32_MAX + +Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> +--- + include/grub/types.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/include/grub/types.h b/include/grub/types.h +index 0d96006fe..a13f3a60b 100644 +--- a/include/grub/types.h ++++ b/include/grub/types.h +@@ -156,6 +156,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 +@@ -177,6 +178,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.39.2 + diff --git a/resources/grub/patches/0005-Add-Argon2-algorithm.patch b/resources/grub/patches/0005-Add-Argon2-algorithm.patch new file mode 100644 index 00000000..1c6b4f04 --- /dev/null +++ b/resources/grub/patches/0005-Add-Argon2-algorithm.patch @@ -0,0 +1,2611 @@ +From 5b63da5c4267933f573ca37ce39a073098c443ba Mon Sep 17 00:00:00 2001 +From: Ax333l <main@axelen.xyz> +Date: Thu, 17 Aug 2023 00:00:00 +0000 +Subject: [PATCH 3/6] Add Argon2 algorithm + +Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> +--- + 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 a695b02f0..313335a53 100644 +--- a/docs/grub-dev.texi ++++ b/docs/grub-dev.texi +@@ -503,11 +503,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 d2cf29584..4a06789e5 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1215,6 +1215,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..97aae2925 +--- /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.39.2 + diff --git a/resources/grub/patches/0006-Error-on-missing-Argon2id-parameters.patch b/resources/grub/patches/0006-Error-on-missing-Argon2id-parameters.patch new file mode 100644 index 00000000..5d56bd61 --- /dev/null +++ b/resources/grub/patches/0006-Error-on-missing-Argon2id-parameters.patch @@ -0,0 +1,58 @@ +From 0044d32121bf52c4547c6b3c78f12d7305f57e6b Mon Sep 17 00:00:00 2001 +From: Ax333l <main@axelen.xyz> +Date: Thu, 17 Aug 2023 00:00:00 +0000 +Subject: [PATCH 4/6] Error on missing Argon2id parameters + +Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> +--- + 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 d5106402f..bc818ea69 100644 +--- a/grub-core/disk/luks2.c ++++ b/grub-core/disk/luks2.c +@@ -38,6 +38,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; +@@ -90,7 +91,7 @@ struct grub_luks2_keyslot + 	grub_int64_t time; + 	grub_int64_t memory; + 	grub_int64_t cpus; +-      } argon2i; ++      } argon2; +       struct +       { + 	const char   *hash; +@@ -160,10 +161,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")) +@@ -459,6 +461,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.39.2 + diff --git a/resources/grub/patches/0007-Compile-with-Argon2id-support.patch b/resources/grub/patches/0007-Compile-with-Argon2id-support.patch new file mode 100644 index 00000000..f2e26fd4 --- /dev/null +++ b/resources/grub/patches/0007-Compile-with-Argon2id-support.patch @@ -0,0 +1,83 @@ +From 0a21695c55f76f1c958bb633481d55b3168562f7 Mon Sep 17 00:00:00 2001 +From: Ax333l <main@axelen.xyz> +Date: Thu, 17 Aug 2023 00:00:00 +0000 +Subject: [PATCH 5/6] Compile with Argon2id support + +Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> +--- + 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 1e9a13d3e..a167825c3 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 4a06789e5..e939dcc99 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1238,7 +1238,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 bc818ea69..5b9eaa599 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> +  +@@ -462,8 +463,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.39.2 + diff --git a/resources/grub/patches/0008-Make-grub-install-work-with-Argon2.patch b/resources/grub/patches/0008-Make-grub-install-work-with-Argon2.patch new file mode 100644 index 00000000..dc65b7a6 --- /dev/null +++ b/resources/grub/patches/0008-Make-grub-install-work-with-Argon2.patch @@ -0,0 +1,26 @@ +From 6c9a6625c0dc038d1bdbdc13665f40e269e86496 Mon Sep 17 00:00:00 2001 +From: Ax333l <main@axelen.xyz> +Date: Thu, 17 Aug 2023 00:00:00 +0000 +Subject: [PATCH 6/6] Make grub-install work with Argon2 + +Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> +--- + util/grub-install.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/util/grub-install.c b/util/grub-install.c +index 1ad04db36..a8a3330b8 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -448,6 +448,8 @@ probe_mods (grub_disk_t disk) +     { +       grub_util_cryptodisk_get_abstraction (disk, + 					    push_cryptodisk_module, NULL); ++      /* HACK: always push argon2 */ ++      grub_install_push_module ("argon2"); +       have_abstractions = 1; +       have_cryptodisk = 1; +     } +--  +2.39.2 + | 
