From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1jBlk2-0004vP-A9 for mharc-grub-devel@gnu.org; Tue, 10 Mar 2020 16:44:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34864) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jBljr-0004lN-Sb for grub-devel@gnu.org; Tue, 10 Mar 2020 16:44:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jBljk-0006kE-0J for grub-devel@gnu.org; Tue, 10 Mar 2020 16:44:31 -0400 Received: from orion.archlinux.org ([88.198.91.70]:35554) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1jBlji-0006en-HA for grub-devel@gnu.org; Tue, 10 Mar 2020 16:44:23 -0400 Received: from orion.archlinux.org (localhost [127.0.0.1]) by orion.archlinux.org (Postfix) with ESMTP id E4E9819EC4314F for ; Tue, 10 Mar 2020 20:44:15 +0000 (UTC) Received: from [IPv6:2600:1700:57f0:ca20:763a:c795:fcf6:91ea] (unknown [IPv6:2600:1700:57f0:ca20:763a:c795:fcf6:91ea]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits)) (No client certificate requested) (Authenticated sender: eschwartz) by orion.archlinux.org (Postfix) with ESMTPSA id 2924819EC4314E for ; Tue, 10 Mar 2020 20:44:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=archlinux.org; s=orion; t=1583873055; bh=gjtxaaLlYcNEXwOcdWWsbMzLCFYKRlc/9t7ZAxcEYZg=; h=Subject:To:References:From:Date:In-Reply-To; b=kNw0IxByaEehTQjtJ2IgPzf5hGvevG1QK5F1oQe9Kw18bKdZY6ytvo1a4f2FWKPiO TS5SmIcbgPwMJ0hLWYn6Fh5KNrHiP/whi2+agbnLaYOSIdsm0/Bw+7KWAlafUUdHFl x6rDWXq9hqIEQueD2G0L8hXpaX5mjK5qkrqOJF+g/1FVfpiSM2oB2LK6+reROhEnov JSCbxk7bkK1zETGZ7PbMs9mYGQd765TCCAzSORvQHlGQ+RsCiLBocr37NEAcn+JUnT udO0uUIVXSmc49a/tB6SIvN7S5Q/6c3s78tmYsM4K8zfBigs4ICrPgrdXQOHQZJVlV VJnxL6vaqvPRhTtbFEAQhiXFk7DbinNkBEnzbiL660m1CSVaB9mv0sFoUenDY2aFYT H+LO69DcPePv49P5si6z2LzwmMu5TOluwQk///qL4EMDJdoV5GvFzlCGsG9pHQ+Mzl gpvwgj4CmE/OIguqbuyjv5eJzsvhBYvpPyVToX73myQVw+2aOxHseC5xgoq788qW+D 3lOinwMQu4/ZdeVyr8ZHFAE8jfxiBvXye5VvMy9J6+EyjalmE3SKf/KAK2rw/sgeih ZIh+UT9gWHeIFJWw24VnWGTggcKYYdJS8/yR39SVZSpJ+QhoQVHFOei4wMF4KG7Q+t yjLWI/7luc8hv2FnmhCjW5Ww= Subject: Re: [PATCH v3 3/5] argon2: Import Argon2 from cryptsetup To: grub-devel@gnu.org References: From: Eli Schwartz X-Clacks-Overhead: GNU Terry Pratchett Message-ID: <1f64edde-3e20-951b-02d7-9880af1835c8@archlinux.org> Date: Tue, 10 Mar 2020 16:44:11 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="S2yeuaR6lLBgrEgzbnmmeIcPfVtCEEDOS" X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 88.198.91.70 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Mar 2020 20:44:40 -0000 This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --S2yeuaR6lLBgrEgzbnmmeIcPfVtCEEDOS Content-Type: multipart/mixed; boundary="IuvbERz88djuqzcuci4eRfFi1lFp4D1KP" --IuvbERz88djuqzcuci4eRfFi1lFp4D1KP Content-Type: text/plain; charset=utf-8 Content-Language: en-US-large Content-Transfer-Encoding: quoted-printable On 3/10/20 2:58 PM, Patrick Steinhardt wrote: > In order to support the Argon2 key derival function for LUKS2, we > obviously need to implement Argon2. It doesn't make a lot of sense to > hand-code any crypto, which is why this commit instead imports Argon2 > from the cryptsetup project. This commit thus imports the code from the= > official reference implementation located at [1]. Which one is it? :p Perhaps, "which is why this commit instead imports the Argon2 implementation used by the cryptsetup project, that is, the official reference implementation located at [1]." > The code is licensed > under CC0 1.0 Universal/Apache 2.0. Given that both LGPLv2.1+ and Apach= e > 2.0 are compatible with GPLv3, it should be fine to import that code. >=20 > The code is imported from commit 62358ba (Merge pull request #270 from > bitmark-property-system/master, 2019-05-20). To make it work for GRUB, > several adjustments were required that have beed documented in > "grub-dev.texi". typo: "beed" -> "been" > [1]: https://github.com/P-H-C/phc-winner-argon2 >=20 > Signed-off-by: Patrick Steinhardt > --- > docs/grub-dev.texi | 64 +++ > grub-core/Makefile.core.def | 8 + > 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 | 525 ++++++++++++++++++= > grub-core/lib/argon2/core.h | 228 ++++++++ > grub-core/lib/argon2/ref.c | 190 +++++++ > 11 files changed, 2195 insertions(+) > 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 >=20 > diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi > index 837873094..4af07f11a 100644 > --- a/docs/grub-dev.texi > +++ b/docs/grub-dev.texi > @@ -489,11 +489,75 @@ GRUB includes some code from other projects, and = it is sometimes necessary > to update it. > =20 > @menu > +* Argon2:: > * Gnulib:: > * jsmn:: > * minilzo:: > @end menu > =20 > +@node Argon2 > +@section Argon2 > + > +Argon2 is a key derivation function used by LUKS2 in order to derive e= ncryption > +keys from a user-provided password. GRUB imports the official referenc= e > +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 vario= us > +conversions. This is mainly due to the fact that the imported code mak= es use of > +types and functions defined in the C standard library, which isn't ava= ilable. > +Furthermore, using the POSIX wrapper library is not possible as the co= de 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" an= d > + "thread.h". > +@item Add includes and to "argon2.h". > +@item Add include and module license declaration to "argon= 2.c". > +@item Remove the following declarations and functions from "argon2.h" = and > + "argon2.c": argon2_type2string, argon2i_hash_encoded, argon2i_has= h_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, argon2= id_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-imp= l.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 a= nd > + ARGON2_MAX_MEMORY to fix compiler warnings. > +@item Mark the function argon2_ctx as static. > +@end enumerate > + > @node Gnulib > @section Gnulib > =20 > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index 91297e4eb..30147a899 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -1181,6 +1181,14 @@ module =3D { > common =3D lib/json/json.c; > }; > =20 > +module =3D { > + name =3D argon2; > + common =3D lib/argon2/argon2.c; > + common =3D lib/argon2/core.c; > + common =3D lib/argon2/ref.c; > + common =3D lib/argon2/blake2/blake2b.c; > +}; > + > module =3D { > name =3D afsplitter; > common =3D disk/AFSplitter.c; > diff --git a/grub-core/lib/argon2/argon2.c b/grub-core/lib/argon2/argon= 2.c > new file mode 100644 > index 000000000..c77f7f6ff > --- /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 Samue= l 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. Th= e 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 wit= h this > + * software. If not, they may be obtained at the above URLs. > + */ > + > +#include > + > +#include "argon2.h" > +#include "core.h" > + > +GRUB_MOD_LICENSE ("GPLv3"); > + > +static int argon2_ctx(argon2_context *context, argon2_type type) { > + /* 1. Validate all inputs */ > + int result =3D validate_inputs(context); > + grub_uint32_t memory_blocks, segment_length; > + argon2_instance_t instance; > + > + if (ARGON2_OK !=3D result) { > + return result; > + } > + > + if (Argon2_d !=3D type && Argon2_i !=3D type && Argon2_id !=3D typ= e) { > + return ARGON2_INCORRECT_TYPE; > + } > + > + /* 2. Align memory size */ > + /* Minimum memory_blocks =3D 8L blocks, where L is the number of l= anes */ > + memory_blocks =3D context->m_cost; > + > + if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) { > + memory_blocks =3D 2 * ARGON2_SYNC_POINTS * context->lanes; > + } > + > + segment_length =3D memory_blocks / (context->lanes * ARGON2_SYNC_P= OINTS); > + /* Ensure that all segments have equal length */ > + memory_blocks =3D segment_length * (context->lanes * ARGON2_SYNC_P= OINTS); > + > + instance.version =3D context->version; > + instance.memory =3D NULL; > + instance.passes =3D context->t_cost; > + instance.memory_blocks =3D memory_blocks; > + instance.segment_length =3D segment_length; > + instance.lane_length =3D segment_length * ARGON2_SYNC_POINTS; > + instance.lanes =3D context->lanes; > + instance.threads =3D context->threads; > + instance.type =3D type; > + > + if (instance.threads > instance.lanes) { > + instance.threads =3D instance.lanes; > + } > + > + /* 3. Initialization: Hashing inputs, allocating memory, filling f= irst > + * blocks > + */ > + result =3D initialize(&instance, context); > + > + if (ARGON2_OK !=3D result) { > + return result; > + } > + > + /* 4. Filling memory */ > + result =3D fill_memory_blocks(&instance); > + > + if (ARGON2_OK !=3D 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 typ= e, > + 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 =3D grub_malloc(hashlen); > + if (!out) { > + return ARGON2_MEMORY_ALLOCATION_ERROR; > + } > + > + context.out =3D (grub_uint8_t *)out; > + context.outlen =3D (grub_uint32_t)hashlen; > + context.pwd =3D CONST_CAST(grub_uint8_t *)pwd; > + context.pwdlen =3D (grub_uint32_t)pwdlen; > + context.salt =3D CONST_CAST(grub_uint8_t *)salt; > + context.saltlen =3D (grub_uint32_t)saltlen; > + context.secret =3D NULL; > + context.secretlen =3D 0; > + context.ad =3D NULL; > + context.adlen =3D 0; > + context.t_cost =3D t_cost; > + context.m_cost =3D m_cost; > + context.lanes =3D parallelism; > + context.threads =3D parallelism; > + context.allocate_cbk =3D NULL; > + context.grub_free_cbk =3D NULL; > + context.flags =3D ARGON2_DEFAULT_FLAGS; > + context.version =3D version; > + > + result =3D argon2_ctx(&context, type); > + > + if (result !=3D 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/argon= 2.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 Samue= l 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. Th= e 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 wit= h this > + * software. If not, they may be obtained at the above URLs. > + */ > + > +#ifndef ARGON2_H > +#define ARGON2_H > + > +#include > +#include > + > +#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 byt= es) */ > +#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per sli= ce */ > + > +#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_M= AX_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 =3D 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 =3D 0, > + > + ARGON2_OUTPUT_PTR_NULL =3D -1, > + > + ARGON2_OUTPUT_TOO_SHORT =3D -2, > + ARGON2_OUTPUT_TOO_LONG =3D -3, > + > + ARGON2_PWD_TOO_SHORT =3D -4, > + ARGON2_PWD_TOO_LONG =3D -5, > + > + ARGON2_SALT_TOO_SHORT =3D -6, > + ARGON2_SALT_TOO_LONG =3D -7, > + > + ARGON2_AD_TOO_SHORT =3D -8, > + ARGON2_AD_TOO_LONG =3D -9, > + > + ARGON2_SECRET_TOO_SHORT =3D -10, > + ARGON2_SECRET_TOO_LONG =3D -11, > + > + ARGON2_TIME_TOO_SMALL =3D -12, > + ARGON2_TIME_TOO_LARGE =3D -13, > + > + ARGON2_MEMORY_TOO_LITTLE =3D -14, > + ARGON2_MEMORY_TOO_MUCH =3D -15, > + > + ARGON2_LANES_TOO_FEW =3D -16, > + ARGON2_LANES_TOO_MANY =3D -17, > + > + ARGON2_PWD_PTR_MISMATCH =3D -18, /* NULL ptr with non-zero leng= th */ > + ARGON2_SALT_PTR_MISMATCH =3D -19, /* NULL ptr with non-zero leng= th */ > + ARGON2_SECRET_PTR_MISMATCH =3D -20, /* NULL ptr with non-zero leng= th */ > + ARGON2_AD_PTR_MISMATCH =3D -21, /* NULL ptr with non-zero leng= th */ > + > + ARGON2_MEMORY_ALLOCATION_ERROR =3D -22, > + > + ARGON2_FREE_MEMORY_CBK_NULL =3D -23, > + ARGON2_ALLOCATE_MEMORY_CBK_NULL =3D -24, > + > + ARGON2_INCORRECT_PARAMETER =3D -25, > + ARGON2_INCORRECT_TYPE =3D -26, > + > + ARGON2_OUT_PTR_MISMATCH =3D -27, > + > + ARGON2_THREADS_TOO_FEW =3D -28, > + ARGON2_THREADS_TOO_MANY =3D -29, > + > + ARGON2_MISSING_ARGS =3D -30, > + > + ARGON2_ENCODING_FAIL =3D -31, > + > + ARGON2_DECODING_FAIL =3D -32, > + > + ARGON2_THREAD_FAIL =3D -33, > + > + ARGON2_DECODING_LENGTH_FAIL =3D -34, > + > + ARGON2_VERIFY_MISMATCH =3D -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 byte= s_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 soo= n as they > + * are pre-hashed (and thus not needed anymore), and the entire memory= > + ***** > + * Simplest situation: you have output array out[8], password is store= d in > + * pwd[32], salt is stored in salt[16], you do not have keys nor assoc= iated > + * 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 be= ing > + * 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,NU= LL,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 =3D 0, > + Argon2_i =3D 1, > + Argon2_id =3D 2 > +} argon2_type; > + > +/* Version of the algorithm */ > +typedef enum Argon2_version { > + ARGON2_VERSION_10 =3D 0x10, > + ARGON2_VERSION_13 =3D 0x13, > + ARGON2_VERSION_NUMBER =3D 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 fun= ction > + * @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_u= int32_t m_cost, > + const grub_uint32_t parallelism, const v= oid *pwd, > + const grub_size_t pwdlen, const void *sa= lt, > + const grub_size_t saltlen, void *hash, > + const grub_size_t hashlen, argon2_type t= ype, > + 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 Samue= l 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. Th= e 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 wit= h 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 pla= tforms > + Additionally, the code will always be correct---this is only a perf= ormance > + tweak. > +*/ > +#if (defined(__BYTE_ORDER__) && = \ > + (__BYTE_ORDER__ =3D=3D __ORDER_LITTLE_ENDIAN__)) || = \ > + defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPS= EL__) || \ > + 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 =3D (const grub_uint8_t *)src; > + grub_uint32_t w =3D *p++; > + w |=3D (grub_uint32_t)(*p++) << 8; > + w |=3D (grub_uint32_t)(*p++) << 16; > + w |=3D (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 =3D (const grub_uint8_t *)src; > + grub_uint64_t w =3D *p++; > + w |=3D (grub_uint64_t)(*p++) << 8; > + w |=3D (grub_uint64_t)(*p++) << 16; > + w |=3D (grub_uint64_t)(*p++) << 24; > + w |=3D (grub_uint64_t)(*p++) << 32; > + w |=3D (grub_uint64_t)(*p++) << 40; > + w |=3D (grub_uint64_t)(*p++) << 48; > + w |=3D (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 =3D (grub_uint8_t *)dst; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (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 =3D (grub_uint8_t *)dst; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > +#endif > +} > + > +static BLAKE2_INLINE grub_uint64_t load48(const void *src) { > + const grub_uint8_t *p =3D (const grub_uint8_t *)src; > + grub_uint64_t w =3D *p++; > + w |=3D (grub_uint64_t)(*p++) << 8; > + w |=3D (grub_uint64_t)(*p++) << 16; > + w |=3D (grub_uint64_t)(*p++) << 24; > + w |=3D (grub_uint64_t)(*p++) << 32; > + w |=3D (grub_uint64_t)(*p++) << 40; > + return w; > +} > + > +static BLAKE2_INLINE void store48(void *dst, grub_uint64_t w) { > + grub_uint8_t *p =3D (grub_uint8_t *)dst; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (grub_uint8_t)w; > + w >>=3D 8; > + *p++ =3D (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/argon= 2/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 Samue= l 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. Th= e 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 wit= h 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 =3D 128, > + BLAKE2B_OUTBYTES =3D 64, > + BLAKE2B_KEYBYTES =3D 64, > + BLAKE2B_SALTBYTES =3D 16, > + BLAKE2B_PERSONALBYTES =3D 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 =3D 1 / !!(GRUB_CHAR_BIT =3D=3D 8), > + blake2_size_check_2 =3D > + 1 / !!(sizeof(blake2b_param) =3D=3D sizeof(grub_uint64_t) * GR= UB_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_pa= ram *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 voi= d *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/argo= n2/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 Samue= l 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. Th= e 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 wit= h 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] =3D { > + GRUB_UINT64_C(0x6a09e667f3bcc908), GRUB_UINT64_C(0xbb67ae8584caa73= b), > + GRUB_UINT64_C(0x3c6ef372fe94f82b), GRUB_UINT64_C(0xa54ff53a5f1d36f= 1), > + GRUB_UINT64_C(0x510e527fade682d1), GRUB_UINT64_C(0x9b05688c2b3e6c1= f), > + GRUB_UINT64_C(0x1f83d9abfb41bd6b), GRUB_UINT64_C(0x5be0cd19137e217= 9)}; > + > +static const unsigned int blake2b_sigma[12][16] =3D { > + {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] =3D (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] =3D (grub_uint64_t)-1; > +} > + > +static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S, > + grub_uint64_t inc)= { > + S->t[0] +=3D inc; > + S->t[1] +=3D (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 =3D (const unsigned char *)P; > + unsigned int i; > + > + if (NULL =3D=3D P || NULL =3D=3D S) { > + return -1; > + } > + > + blake2b_init0(S); > + /* IV XOR Parameter Block */ > + for (i =3D 0; i < 8; ++i) { > + S->h[i] ^=3D load64(&p[i * sizeof(S->h[i])]); > + } > + S->outlen =3D P->digest_length; > + return 0; > +} > + > +/* Sequential blake2b initialization */ > +int blake2b_init(blake2b_state *S, grub_size_t outlen) { > + blake2b_param P; > + > + if (S =3D=3D NULL) { > + return -1; > + } > + > + if ((outlen =3D=3D 0) || (outlen > BLAKE2B_OUTBYTES)) { > + blake2b_invalidate_state(S); > + return -1; > + } > + > + /* Setup Parameter Block for unkeyed BLAKE2 */ > + P.digest_length =3D (grub_uint8_t)outlen; > + P.key_length =3D 0; > + P.fanout =3D 1; > + P.depth =3D 1; > + P.leaf_length =3D 0; > + P.node_offset =3D 0; > + P.node_depth =3D 0; > + P.inner_length =3D 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 =3D=3D NULL) { > + return -1; > + } > + > + if ((outlen =3D=3D 0) || (outlen > BLAKE2B_OUTBYTES)) { > + blake2b_invalidate_state(S); > + return -1; > + } > + > + if ((key =3D=3D 0) || (keylen =3D=3D 0) || (keylen > BLAKE2B_KEYBY= TES)) { > + blake2b_invalidate_state(S); > + return -1; > + } > + > + /* Setup Parameter Block for keyed BLAKE2 */ > + P.digest_length =3D (grub_uint8_t)outlen; > + P.key_length =3D (grub_uint8_t)keylen; > + P.fanout =3D 1; > + P.depth =3D 1; > + P.leaf_length =3D 0; > + P.node_offset =3D 0; > + P.node_depth =3D 0; > + P.inner_length =3D 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 *blo= ck) { > + grub_uint64_t m[16]; > + grub_uint64_t v[16]; > + unsigned int i, r; > + > + for (i =3D 0; i < 16; ++i) { > + m[i] =3D load64(block + i * sizeof(m[i])); > + } > + > + for (i =3D 0; i < 8; ++i) { > + v[i] =3D S->h[i]; > + } > + > + v[8] =3D blake2b_IV[0]; > + v[9] =3D blake2b_IV[1]; > + v[10] =3D blake2b_IV[2]; > + v[11] =3D blake2b_IV[3]; > + v[12] =3D blake2b_IV[4] ^ S->t[0]; > + v[13] =3D blake2b_IV[5] ^ S->t[1]; > + v[14] =3D blake2b_IV[6] ^ S->f[0]; > + v[15] =3D blake2b_IV[7] ^ S->f[1]; > + > +#define G(r, i, a, b, c, d) = \ > + do { = \ > + a =3D a + b + m[blake2b_sigma[r][2 * i + 0]]; = \ > + d =3D rotr64(d ^ a, 32); = \ > + c =3D c + d; = \ > + b =3D rotr64(b ^ c, 24); = \ > + a =3D a + b + m[blake2b_sigma[r][2 * i + 1]]; = \ > + d =3D rotr64(d ^ a, 16); = \ > + c =3D c + d; = \ > + b =3D 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 =3D 0; r < 12; ++r) { > + ROUND(r); > + } > + > + for (i =3D 0; i < 8; ++i) { > + S->h[i] =3D 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 =3D (const grub_uint8_t *)in; > + > + if (inlen =3D=3D 0) { > + return 0; > + } > + > + /* Sanity check */ > + if (S =3D=3D NULL || in =3D=3D NULL) { > + return -1; > + } > + > + /* Is this a reused state? */ > + if (S->f[0] !=3D 0) { > + return -1; > + } > + > + if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) { > + /* Complete current block */ > + grub_size_t left =3D S->buflen; > + grub_size_t fill =3D BLAKE2B_BLOCKBYTES - left; > + grub_memcpy(&S->buf[left], pin, fill); > + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); > + blake2b_compress(S, S->buf); > + S->buflen =3D 0; > + inlen -=3D fill; > + pin +=3D fill; > + /* Avoid buffer copies when possible */ > + while (inlen > BLAKE2B_BLOCKBYTES) { > + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); > + blake2b_compress(S, pin); > + inlen -=3D BLAKE2B_BLOCKBYTES; > + pin +=3D BLAKE2B_BLOCKBYTES; > + } > + } > + grub_memcpy(&S->buf[S->buflen], pin, inlen); > + S->buflen +=3D (unsigned int)inlen; > + return 0; > +} > + > +int blake2b_final(blake2b_state *S, void *out, grub_size_t outlen) { > + grub_uint8_t buffer[BLAKE2B_OUTBYTES] =3D {0}; > + unsigned int i; > + > + /* Sanity checks */ > + if (S =3D=3D NULL || out =3D=3D NULL || outlen < S->outlen) { > + return -1; > + } > + > + /* Is this a reused state? */ > + if (S->f[0] !=3D 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 =3D 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 =3D -1; > + > + /* Verify parameters */ > + if (NULL =3D=3D in && inlen > 0) { > + goto fail; > + } > + > + if (NULL =3D=3D out || outlen =3D=3D 0 || outlen > BLAKE2B_OUTBYTE= S) { > + goto fail; > + } > + > + if ((NULL =3D=3D 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 =3D 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 =3D (grub_uint8_t *)pout; > + blake2b_state blake_state; > + grub_uint8_t outlen_bytes[sizeof(grub_uint32_t)] =3D {0}; > + int ret =3D -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 =3D statement; = \ > + if (ret < 0) { = \ > + goto fail; = \ > + } = \ > + } while ((void)0, 0) > + > + if (outlen <=3D BLAKE2B_OUTBYTES) { > + TRY(blake2b_init(&blake_state, outlen)); > + TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_b= ytes))); > + 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_b= ytes))); > + 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 +=3D BLAKE2B_OUTBYTES / 2; > + toproduce =3D (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 +=3D BLAKE2B_OUTBYTES / 2; > + toproduce -=3D 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 Samue= l 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. Th= e 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 wit= h 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_uint6= 4_t y) { > + const grub_uint64_t m =3D GRUB_UINT64_C(0xFFFFFFFF); > + const grub_uint64_t xy =3D (x & m) * (y & m); > + return x + y + 2 * xy; > +} > + > +#define G(a, b, c, d) = \ > + do { = \ > + a =3D fBlaMka(a, b); = \ > + d =3D rotr64(d ^ a, 32); = \ > + c =3D fBlaMka(c, d); = \ > + b =3D rotr64(b ^ c, 24); = \ > + a =3D fBlaMka(a, b); = \ > + d =3D rotr64(d ^ a, 16); = \ > + c =3D fBlaMka(c, d); = \ > + b =3D 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..1bb8e22e2 > --- /dev/null > +++ b/grub-core/lib/argon2/core.c > @@ -0,0 +1,525 @@ > +/* > + * Argon2 reference source code package - reference C implementations > + * > + * Copyright 2015 > + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samue= l 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. Th= e 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 wit= h this > + * software. If not, they may be obtained at the above URLs. > + */ > + > +/*For memory wiping*/ > +#ifdef _MSC_VER > +#include > +#include /* For SecureZeroMemory */ > +#endif > +#if defined __STDC_LIB_EXT1__ > +#define __STDC_WANT_LIB_EXT1__ 1 > +#endif > +#define VC_GE_2005(version) (version >=3D 1400) > + > +/* for explicit_bzero() on glibc */ > +#define _DEFAULT_SOURCE > + > +#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 >=3D 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, i= n, 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 =3D 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { > + dst->v[i] ^=3D src->v[i]; > + } > +} > + > +static void load_block(block *dst, const void *input) { > + unsigned i; > + for (i =3D 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { > + dst->v[i] =3D load64((const grub_uint8_t *)input + i * sizeof(= dst->v[i])); > + } > +} > + > +static void store_block(void *output, const block *src) { > + unsigned i; > + for (i =3D 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 **memo= ry, > + grub_size_t num, grub_size_t size) { > + grub_size_t memory_size =3D num*size; > + if (memory =3D=3D NULL) { > + return ARGON2_MEMORY_ALLOCATION_ERROR; > + } > + > + /* 1. Check for multiplication overflow */ > + if (size !=3D 0 && memory_size / size !=3D 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 =3D grub_malloc(memory_size); > + } > + > + if (*memory =3D=3D NULL) { > + return ARGON2_MEMORY_ALLOCATION_ERROR; > + } > + > + return ARGON2_OK; > +} > + > +void grub_free_memory(const argon2_context *context, grub_uint8_t *mem= ory, > + grub_size_t num, grub_size_t size) { > + grub_size_t memory_size =3D num*size; > + clear_internal_memory(memory, memory_size); > + if (context->grub_free_cbk) { > + (context->grub_free_cbk)(memory, memory_size); > + } else { > + grub_free(memory); > + } > +} > + > +#if defined(__OpenBSD__) > +#define HAVE_EXPLICIT_BZERO 1 > +#elif defined(__GLIBC__) && defined(__GLIBC_PREREQ) > +#if __GLIBC_PREREQ(2,25) > +#define HAVE_EXPLICIT_BZERO 1 > +#endif > +#endif > + > +void NOT_OPTIMIZED secure_wipe_memory(void *v, grub_size_t n) { > +#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER) > + SecureZeroMemory(v, n); > +#elif defined grub_memset_s > + grub_memset_s(v, n, 0, n); > +#elif defined(HAVE_EXPLICIT_BZERO) > + explicit_bzero(v, n); > +#else > + static void *(*const volatile grub_memset_sec)(void *, int, grub_s= ize_t) =3D &grub_memset; > + grub_memset_sec(v, 0, n); > +#endif > +} > + > +/* Memory clear flag defaults to true. */ > +int FLAG_clear_internal_memory =3D 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 *instan= ce) { > + if (context !=3D NULL && instance !=3D NULL) { > + block blockhash; > + grub_uint32_t l; > + > + copy_block(&blockhash, instance->memory + instance->lane_lengt= h - 1); > + > + /* XOR the last blocks */ > + for (l =3D 1; l < instance->lanes; ++l) { > + grub_uint32_t last_block_in_lane =3D > + l * instance->lane_length + (instance->lane_length - 1= ); > + xor_block(&blockhash, instance->memory + last_block_in_lan= e); > + } > + > + /* Hash the result */ > + { > + grub_uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; > + store_block(blockhash_bytes, &blockhash); > + blake2b_long(context->out, context->outlen, blockhash_byte= s, > + 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 con= structed > + * blocks in this segment > + * Other lanes : all already finished segments > + * Pass 1+: > + * This lane : (SYNC_POINTS - 1) last segments plus already c= onstructed > + * blocks in this segment > + * Other lanes : (SYNC_POINTS - 1) last segments > + */ > + grub_uint32_t reference_area_size; > + grub_uint64_t relative_position; > + grub_uint32_t start_position, absolute_position; > + > + if (0 =3D=3D position->pass) { > + /* First pass */ > + if (0 =3D=3D position->slice) { > + /* First slice */ > + reference_area_size =3D > + position->index - 1; /* all but the previous */ > + } else { > + if (same_lane) { > + /* The same lane =3D> add current segment */ > + reference_area_size =3D > + position->slice * instance->segment_length + > + position->index - 1; > + } else { > + reference_area_size =3D > + position->slice * instance->segment_length + > + ((position->index =3D=3D 0) ? (-1) : 0); > + } > + } > + } else { > + /* Second pass */ > + if (same_lane) { > + reference_area_size =3D instance->lane_length - > + instance->segment_length + position-= >index - > + 1; > + } else { > + reference_area_size =3D instance->lane_length - > + instance->segment_length + > + ((position->index =3D=3D 0) ? (-1) := 0); > + } > + } > + > + /* 1.2.4. Mapping pseudo_rand to 0.. and pr= oduce > + * relative position */ > + relative_position =3D pseudo_rand; > + relative_position =3D relative_position * relative_position >> 32;= > + relative_position =3D reference_area_size - 1 - > + (reference_area_size * relative_position >> 32= ); > + > + /* 1.2.5 Computing starting position */ > + start_position =3D 0; > + > + if (0 !=3D position->pass) { > + start_position =3D (position->slice =3D=3D ARGON2_SYNC_POINTS = - 1) > + ? 0 > + : (position->slice + 1) * instance->segme= nt_length; > + } > + > + /* 1.2.6. Computing absolute position */ > + absolute_position =3D (start_position + relative_position) % > + instance->lane_length; /* absolute position */= > + return absolute_position; > +} > + > +/* Single-threaded version for p=3D1 case */ > +static int fill_memory_blocks_st(argon2_instance_t *instance) { > + grub_uint32_t r, s, l; > + > + for (r =3D 0; r < instance->passes; ++r) { > + for (s =3D 0; s < ARGON2_SYNC_POINTS; ++s) { > + for (l =3D 0; l < instance->lanes; ++l) { > + argon2_position_t position =3D {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 =3D=3D NULL || instance->lanes =3D=3D 0) { > + return ARGON2_INCORRECT_PARAMETER; > + } > + return fill_memory_blocks_st(instance); > +} > + > +int validate_inputs(const argon2_context *context) { > + if (NULL =3D=3D context) { > + return ARGON2_INCORRECT_PARAMETER; > + } > + > + if (NULL =3D=3D 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 =3D=3D context->pwd) { > + if (0 !=3D 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 =3D=3D context->salt) { > + if (0 !=3D 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 =3D=3D context->secret) { > + if (0 !=3D 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 =3D=3D context->ad) { > + if (0 !=3D 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 !=3D context->allocate_cbk && NULL =3D=3D context->grub_f= ree_cbk) { > + return ARGON2_FREE_MEMORY_CBK_NULL; > + } > + > + if (NULL =3D=3D context->allocate_cbk && NULL !=3D context->grub_f= ree_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 =3D 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 =3D=3D context || NULL =3D=3D blockhash) { > + return; > + } > + > + blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH); > + > + store32(&value, context->lanes); > + blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(va= lue)); > + > + store32(&value, context->outlen); > + blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(va= lue)); > + > + store32(&value, context->m_cost); > + blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(va= lue)); > + > + store32(&value, context->t_cost); > + blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(va= lue)); > + > + store32(&value, context->version); > + blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(va= lue)); > + > + store32(&value, (grub_uint32_t)type); > + blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(va= lue)); > + > + store32(&value, context->pwdlen); > + blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(va= lue)); > + > + if (context->pwd !=3D 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 =3D 0; > + } > + } > + > + store32(&value, context->saltlen); > + blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(va= lue)); > + > + if (context->salt !=3D 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(va= lue)); > + > + if (context->secret !=3D NULL) { > + blake2b_update(&BlakeHash, (const grub_uint8_t *)context->secr= et, > + context->secretlen); > + > + if (context->flags & ARGON2_FLAG_CLEAR_SECRET) { > + secure_wipe_memory(context->secret, context->secretlen); > + context->secretlen =3D 0; > + } > + } > + > + store32(&value, context->adlen); > + blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(va= lue)); > + > + if (context->ad !=3D 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 =3D ARGON2_OK; > + > + if (instance =3D=3D NULL || context =3D=3D NULL) > + return ARGON2_INCORRECT_PARAMETER; > + instance->context_ptr =3D context; > + > + /* 1. Memory allocation */ > + result =3D allocate_memory(context, (grub_uint8_t **)&(instance->m= emory), > + instance->memory_blocks, sizeof(block)); > + if (result !=3D 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 Samue= l 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. Th= e 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 wit= h 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 =3D 1024, > + ARGON2_QWORDS_IN_BLOCK =3D ARGON2_BLOCK_SIZE / 8, > + ARGON2_OWORDS_IN_BLOCK =3D ARGON2_BLOCK_SIZE / 16, > + ARGON2_HWORDS_IN_BLOCK =3D ARGON2_BLOCK_SIZE / 32, > + ARGON2_512BIT_WORDS_IN_BLOCK =3D ARGON2_BLOCK_SIZE / 64, > + > + /* Number of pseudo-random values generated by one call to Blake i= n Argon2i > + to > + generate reference block positions */ > + ARGON2_ADDRESSES_IN_BLOCK =3D 128, > + > + /* Pre-hashing digest length and its extension*/ > + ARGON2_PREHASH_DIGEST_LENGTH =3D 64, > + ARGON2_PREHASH_SEED_LENGTH =3D 72 > +}; > + > +/*************************Argon2 internal data types******************= *****/ > + > +/* > + * Structure for the (1KB) memory block implemented as 128 64-bit word= s. > + * 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]; } blo= ck; > + > +/*****************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 di= stribute > + * 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 allocat= or 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 alloc= ated > + */ > +int allocate_memory(const argon2_context *context, grub_uint8_t **memo= ry, > + 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_intern= al_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 *mem= ory, > + grub_size_t num, grub_size_t size); > + > +/* Function that securely cleans the memory. This ignores any flags se= t > + * regarding clearing memory. Usually one just calls clear_internal_me= mory. > + * @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_mem= ory 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 curr= ent 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 erro= r codes > + * (all defined in > + */ > +int validate_inputs(const argon2_context *context); > + > +/* > + * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], cle= ars > + * password and secret if needed > + * @param context Pointer to the Argon2 internal structure containin= g 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 by= tes > + * 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 value= s > + */ > +void fill_first_blocks(grub_uint8_t *blockhash, const argon2_instance_= t *instance); > + > +/* > + * Function allocates memory, hashes the inputs with Blake, and creat= es first > + * two blocks. Returns the pointer to the main memory with 2 blocks pe= r lane > + * initialized > + * @param context Pointer to the Argon2 internal structure containin= g memory > + * pointer, and parameters for time and space requirements. > + * @param instance Current Argon2 instance > + * @return Zero if successful, -1 if memory failed to allocate. @conte= xt->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. Dea= llocates > + * 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 fu= nction that > + * deallocates memory > + */ > +void finalize(const argon2_context *context, argon2_instance_t *instan= ce); > + > +/* > + * Function that fills the segment using previous segments also from o= ther > + * 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 fir= st 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..d1f4134b3 > --- /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 Samue= l 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. Th= e 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 wit= h 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 overw= rite (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 =3D ref_block + prev_block and block_tmp =3D ref_blo= ck + prev_block */ > + if (with_xor) { > + /* Saving the next block contents for XOR over: */ > + xor_block(&block_tmp, next_block); > + /* Now blockR =3D ref_block + prev_block and > + block_tmp =3D 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 =3D 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), t= hen > + (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */ > + for (i =3D 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 =3D NULL, *curr_block =3D 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 =3D=3D NULL) { > + return; > + } > + > + data_independent_addressing =3D > + (instance->type =3D=3D Argon2_i) || > + (instance->type =3D=3D Argon2_id && (position.pass =3D=3D 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] =3D position.pass; > + input_block.v[1] =3D position.lane; > + input_block.v[2] =3D position.slice; > + input_block.v[3] =3D instance->memory_blocks; > + input_block.v[4] =3D instance->passes; > + input_block.v[5] =3D instance->type; > + } > + > + starting_index =3D 0; > + > + if ((0 =3D=3D position.pass) && (0 =3D=3D position.slice)) { > + starting_index =3D 2; /* we have already generated the first t= wo 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 =3D position.lane * instance->lane_length + > + position.slice * instance->segment_length + starting= _index; > + > + if (0 =3D=3D curr_offset % instance->lane_length) { > + /* Last block in this lane */ > + prev_offset =3D curr_offset + instance->lane_length - 1; > + } else { > + /* Previous block */ > + prev_offset =3D curr_offset - 1; > + } > + > + for (i =3D starting_index; i < instance->segment_length; > + ++i, ++curr_offset, ++prev_offset) { > + /*1.1 Rotating prev_offset if needed */ > + if (curr_offset % instance->lane_length =3D=3D 1) { > + prev_offset =3D 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 =3D=3D 0) { > + next_addresses(&address_block, &input_block, &zero_blo= ck); > + } > + pseudo_rand =3D address_block.v[i % ARGON2_ADDRESSES_IN_BL= OCK]; > + } else { > + pseudo_rand =3D instance->memory[prev_offset].v[0]; > + } > + > + /* 1.2.2 Computing the lane of the reference block */ > + ref_lane =3D ((pseudo_rand >> 32)) % instance->lanes; > + > + if ((position.pass =3D=3D 0) && (position.slice =3D=3D 0)) { > + /* Can not reference other lanes yet */ > + ref_lane =3D position.lane; > + } > + > + /* 1.2.3 Computing the number of possible reference block with= in the > + * lane. > + */ > + position.index =3D i; > + ref_index =3D index_alpha(instance, &position, pseudo_rand & 0= xFFFFFFFF, > + ref_lane =3D=3D position.lane); > + > + /* 2 Creating a new block */ > + ref_block =3D > + instance->memory + instance->lane_length * ref_lane + ref_= index; > + curr_block =3D instance->memory + curr_offset; > + if (ARGON2_VERSION_10 =3D=3D 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 =3D=3D 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); > + } > + } > + } > +} >=20 --=20 Eli Schwartz Bug Wrangler and Trusted User --IuvbERz88djuqzcuci4eRfFi1lFp4D1KP-- --S2yeuaR6lLBgrEgzbnmmeIcPfVtCEEDOS Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEvSewel70XCra9w4EhIGKaBmvSpsFAl5n/BsACgkQhIGKaBmv SptQaRAAirCi+pPrJVekXa44HIQWFmWxzmLo0mdzg1Zmtnkv3cx0YQ+SlK3Orhf5 GtSwI710ONVOUtveaNE/3AwK5QXlKdT1HkEhFePOjnW9gqQZ00fvb8bCX33O48bH v9ntXkHgqxLYBH5eH9cbUec0u+yBuKBVEwtecbY9mQloIDueK1iuhCxoeTYXpIY3 JhrBMsJK7xL13E8/y0rdeenOptuf4QhuSz5B3rHgc7T8v/nAADALfkdEqpLRigm1 7usNSqV/pHSzUzDPWIsgGZDNxWzk3VBiHN20BbYfVTeFW4hJrSw+17GQ9WjyKYEa 7YmwBPggUZ8fEi5NlqeytwtlcB2D+YCk66UsIGamsTtE4XrJBKAyf4o6jfm+Ev72 VUCYHKj5io0fy1YP47fqx1U6lVDeDkiL/TsboYxA+5E3CdU7/lwsrRry401/6JJv XmIF22Diy2wQt27NS8+cic8Ehy0xOQ8v4qC5FaZG6xTqCjh2oCRofs3wVLzRgJPT N9avmjuwmgiQtuDqgztthczUkNGmY3Mq17/L5FK/mQKgBaItt9h6LkLxrzkEPJxb EwwWOWpkNTbznV1g7Rn9aHClqnu03UGzT7uaSq12zypg5lJ99wMtsWffI2+PDnvQ UspSAUEbUPV4hujey8laMUBv+e/mq4rIwkBcb5LKpYzsX5ZzhOyJAjMEAQEKAB0W IQRgQRMEwJ02YoNA7v/OsWfvtXIr1gUCXmf8GwAKCRDOsWfvtXIr1tsPD/9Elv9D lgbEy82HSP4nxRUXAf9PwQe0zpkZMIYiGPQyWx16c/26y/xAVRmtOIqzhnasLjIj ZJ2Ln+VVw6ROxeRSoAC4ibAy6MjJcqCYXEGB1tC0eZlO9uoSUOlpUtUmCbsYrfGh 1rbVUXF75ZLdDWKLVAnSWHetVaDuOVGIUhsRPIr3NVtZAjH3XA4HMRlZkx+e/Vqr lL6nkoTq6TIXFPLEwb6MGt9EwK2SGwJU66mZRwkt6LJAtYEm7Yyep7cH9ZQZ5kz2 R/opkVQ8ViYsICyTo5Ko52K4ycz4eBoX3k2LkosAGuZuyfMAz8iTbHuySatGlMjC cZyfbbMwzTGN/aG7gVbwIe7SrXlkGilZM2gdUdjNUIrru8rvQOCp5086d9AOQKsX bfGiqRss6w5OgxEQBeY1nuyNcPbkk/7/n8mG3kts0bk+bWVmKBaM+GyElgEKun6f 68I19ik6MBkJkhlh79m1C2qh/kF7guSDiRG+KtQFz5JaYVeWi/lLX2DIMCcx2Z/Q PMbdnEurG3ZwZlJbhSFWqMseWYoNe3b8eMaWykCZrEad79tuiC7TVawZg/H8c5Ne 7sYLqKzY46RLYDE4hXNa4m4XYc2q4u4u9kSz2qDwtNGhAcaAJP92Knwb4EQ2ohxn Szcb/ZsQ9/zOArk83NdfZjfFygPllKzLM4a4ww== =8xUU -----END PGP SIGNATURE----- --S2yeuaR6lLBgrEgzbnmmeIcPfVtCEEDOS--