argon2 1.1.0 → 1.2.0
raw patch · 18 files changed
+1347/−269 lines, 18 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Crypto.Argon2: instance GHC.Generics.Constructor Crypto.Argon2.C1_0Argon2Variant
- Crypto.Argon2: instance GHC.Generics.Constructor Crypto.Argon2.C1_0HashOptions
- Crypto.Argon2: instance GHC.Generics.Constructor Crypto.Argon2.C1_1Argon2Variant
- Crypto.Argon2: instance GHC.Generics.Datatype Crypto.Argon2.D1Argon2Variant
- Crypto.Argon2: instance GHC.Generics.Datatype Crypto.Argon2.D1HashOptions
- Crypto.Argon2: instance GHC.Generics.Selector Crypto.Argon2.S1_0_0HashOptions
- Crypto.Argon2: instance GHC.Generics.Selector Crypto.Argon2.S1_0_1HashOptions
- Crypto.Argon2: instance GHC.Generics.Selector Crypto.Argon2.S1_0_2HashOptions
- Crypto.Argon2: instance GHC.Generics.Selector Crypto.Argon2.S1_0_3HashOptions
+ Crypto.Argon2.FFI: argon2_encodedlen :: (Word32) -> (Word32) -> (Word32) -> (Word32) -> (Word32) -> IO CSize
- Crypto.Argon2: Argon2PasswordLengthOutOfRange :: !Word64 -> Argon2Exception
+ Crypto.Argon2: Argon2PasswordLengthOutOfRange :: !CSize -> Argon2Exception
- Crypto.Argon2: Argon2SaltLengthOutOfRange :: !Word64 -> Argon2Exception
+ Crypto.Argon2: Argon2SaltLengthOutOfRange :: !CSize -> Argon2Exception
- Crypto.Argon2.FFI: argon2d_hash_encoded :: (Word32) -> (Word32) -> (Word32) -> Ptr a -> (Word64) -> Ptr b -> (Word64) -> (Word64) -> CString -> (Word64) -> IO (Int32)
+ Crypto.Argon2.FFI: argon2d_hash_encoded :: (Word32) -> (Word32) -> (Word32) -> Ptr a -> CSize -> Ptr b -> CSize -> CSize -> CString -> CSize -> IO (Int32)
- Crypto.Argon2.FFI: argon2d_hash_raw :: (Word32) -> (Word32) -> (Word32) -> Ptr a -> (Word64) -> Ptr b -> (Word64) -> Ptr c -> (Word64) -> IO (Int32)
+ Crypto.Argon2.FFI: argon2d_hash_raw :: (Word32) -> (Word32) -> (Word32) -> Ptr a -> CSize -> Ptr b -> CSize -> Ptr c -> CSize -> IO (Int32)
- Crypto.Argon2.FFI: argon2d_verify :: CString -> Ptr a -> (Word64) -> IO (Int32)
+ Crypto.Argon2.FFI: argon2d_verify :: CString -> Ptr a -> CSize -> IO (Int32)
- Crypto.Argon2.FFI: argon2i_hash_encoded :: (Word32) -> (Word32) -> (Word32) -> Ptr a -> (Word64) -> Ptr b -> (Word64) -> (Word64) -> CString -> (Word64) -> IO (Int32)
+ Crypto.Argon2.FFI: argon2i_hash_encoded :: (Word32) -> (Word32) -> (Word32) -> Ptr a -> CSize -> Ptr b -> CSize -> CSize -> CString -> CSize -> IO (Int32)
- Crypto.Argon2.FFI: argon2i_hash_raw :: (Word32) -> (Word32) -> (Word32) -> Ptr a -> (Word64) -> Ptr b -> (Word64) -> Ptr c -> (Word64) -> IO (Int32)
+ Crypto.Argon2.FFI: argon2i_hash_raw :: (Word32) -> (Word32) -> (Word32) -> Ptr a -> CSize -> Ptr b -> CSize -> Ptr c -> CSize -> IO (Int32)
- Crypto.Argon2.FFI: argon2i_verify :: CString -> Ptr a -> (Word64) -> IO (Int32)
+ Crypto.Argon2.FFI: argon2i_verify :: CString -> Ptr a -> CSize -> IO (Int32)
Files
- Changelog.md +21/−0
- argon2.cabal +25/−9
- phc-winner-argon2/include/argon2.h +374/−0
- phc-winner-argon2/src/argon2.c +146/−149
- phc-winner-argon2/src/blake2/blake2-impl.h +139/−0
- phc-winner-argon2/src/blake2/blake2.h +74/−0
- phc-winner-argon2/src/blake2/blake2b.c +7/−7
- phc-winner-argon2/src/blake2/blamka-round-ref.h +39/−0
- phc-winner-argon2/src/core.c +8/−6
- phc-winner-argon2/src/core.h +219/−0
- phc-winner-argon2/src/encoding.c +77/−74
- phc-winner-argon2/src/encoding.h +40/−0
- phc-winner-argon2/src/ref.c +58/−6
- phc-winner-argon2/src/ref.h +51/−0
- phc-winner-argon2/src/thread.c +1/−1
- phc-winner-argon2/src/thread.h +46/−0
- src/Crypto/Argon2.hs +14/−11
- src/Crypto/Argon2/FFI.hsc +8/−6
Changelog.md view
@@ -1,3 +1,24 @@+# 1.2.0++- Updated embedded phc-winner-argon2, so that hashes are generated+ using version 1.3 of the argon2 specification.+ + Note that that hashes generated using this version are different than+ hashes generated using previous versions, so anything that compares them+ or relies on them being stable may be broken by this update. + However, Crypto.Argon2.verify will continue to be able to verify+ hashes produced by previous versions.++- Use CSize for portability instead of Word64, fixing build on 32 bit+ systems. This changed the constructors of Argon2Exception, an API change.++- Bug fix: Crypto.Argon2.hash returned a ByteString truncated at the first+ NULL.++- Added use-system-library build flag.++- Build against `base-4.9`+ # 1.1.0 - First stable release. Same API as 1.0.0, but now features documentation and
argon2.cabal view
@@ -1,5 +1,5 @@ name: argon2-version: 1.1.0+version: 1.2.0 synopsis: Haskell bindings to libargon2 - the reference implementation of the Argon2 password-hashing function -- description: homepage: https://github.com/ocharles/argon2.git@@ -12,20 +12,36 @@ build-type: Simple extra-source-files: Changelog.md cabal-version: >=1.10+extra-source-files: phc-winner-argon2/src/blake2/blake2.h+ phc-winner-argon2/src/blake2/blake2-impl.h+ phc-winner-argon2/src/blake2/blamka-round-ref.h+ phc-winner-argon2/include/argon2.h +flag use-system-library+ description: Link against system libargon2 library rather than embedded copy+ default: False+ library exposed-modules: Crypto.Argon2.FFI Crypto.Argon2- build-depends: base >=4.8 && <4.9, bytestring, text, transformers+ build-depends: base >=4.8 && <4.10, bytestring, text, transformers hs-source-dirs: src default-language: Haskell2010- c-sources: phc-winner-argon2/src/argon2.c- phc-winner-argon2/src/core.c- phc-winner-argon2/src/blake2/blake2b.c- phc-winner-argon2/src/thread.c- phc-winner-argon2/src/ref.c- phc-winner-argon2/src/encoding.c- include-dirs: phc-winner-argon2/src+ if flag(use-system-library)+ extra-libraries: argon2+ else+ c-sources: phc-winner-argon2/src/argon2.c+ phc-winner-argon2/src/core.c+ phc-winner-argon2/src/blake2/blake2b.c+ phc-winner-argon2/src/thread.c+ phc-winner-argon2/src/ref.c+ phc-winner-argon2/src/encoding.c+ phc-winner-argon2/src/encoding.h+ phc-winner-argon2/src/core.h+ phc-winner-argon2/src/thread.h+ phc-winner-argon2/src/ref.h+ include-dirs: phc-winner-argon2/src+ phc-winner-argon2/include test-suite tests type: exitcode-stdio-1.0
+ phc-winner-argon2/include/argon2.h view
@@ -0,0 +1,374 @@+/*+ * Argon2 source code package+ *+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015+ *+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.+ *+ * You should have received a copy of the CC0 Public Domain Dedication+ * along with this software. If not, see+ * <http://creativecommons.org/publicdomain/zero/1.0/>.+ */++#ifndef ARGON2_H+#define ARGON2_H++#include <stdint.h>+#include <stddef.h>+#include <limits.h>++#if defined(__cplusplus)+extern "C" {+#endif++/* Symbols visibility control */+#ifdef A2_VISCTL+#define ARGON2_PUBLIC __attribute__((visibility("default")))+#elif _MSC_VER+#define ARGON2_PUBLIC __declspec(dllexport)+#else+#define ARGON2_PUBLIC+#endif++/*+ * Argon2 input parameter restrictions+ */++/* Minimum and maximum number of lanes (degree of parallelism) */+#define ARGON2_MIN_LANES UINT32_C(1)+#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF)++/* Minimum and maximum number of threads */+#define ARGON2_MIN_THREADS UINT32_C(1)+#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF)++/* Number of synchronization points between lanes per pass */+#define ARGON2_SYNC_POINTS UINT32_C(4)++/* Minimum and maximum digest size in bytes */+#define ARGON2_MIN_OUTLEN UINT32_C(4)+#define ARGON2_MAX_OUTLEN 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(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))+#define ARGON2_MAX_MEMORY \+ ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)++/* Minimum and maximum number of passes */+#define ARGON2_MIN_TIME UINT32_C(1)+#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF)++/* Minimum and maximum password length in bytes */+#define ARGON2_MIN_PWD_LENGTH UINT32_C(0)+#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF)++/* Minimum and maximum associated data length in bytes */+#define ARGON2_MIN_AD_LENGTH UINT32_C(0)+#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF)++/* Minimum and maximum salt length in bytes */+#define ARGON2_MIN_SALT_LENGTH UINT32_C(8)+#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF)++/* Minimum and maximum key length in bytes */+#define ARGON2_MIN_SECRET UINT32_C(0)+#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF)++#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)+#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)+#define ARGON2_FLAG_CLEAR_MEMORY (UINT32_C(1) << 2)+#define ARGON2_DEFAULT_FLAGS (ARGON2_FLAG_CLEAR_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)(uint8_t **memory, size_t bytes_to_allocate);+typedef void (*deallocate_fptr)(uint8_t *memory, 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 {+ uint8_t *out; /* output array */+ uint32_t outlen; /* digest length */++ uint8_t *pwd; /* password array */+ uint32_t pwdlen; /* password length */++ uint8_t *salt; /* salt array */+ uint32_t saltlen; /* salt length */++ uint8_t *secret; /* key array */+ uint32_t secretlen; /* key length */++ uint8_t *ad; /* associated data array */+ uint32_t adlen; /* associated data length */++ uint32_t t_cost; /* number of passes */+ uint32_t m_cost; /* amount of memory requested (KB) */+ uint32_t lanes; /* number of lanes */+ uint32_t threads; /* maximum number of threads */++ uint32_t version; /* version number */++ allocate_fptr allocate_cbk; /* pointer to memory allocator */+ deallocate_fptr free_cbk; /* pointer to memory deallocator */++ uint32_t flags; /* array of bool options */+} argon2_context;++/* Argon2 primitive type */+typedef enum Argon2_type { Argon2_d = 0, Argon2_i = 1 } 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;++/*+ * Function that performs memory-hard hashing with certain degree of parallelism+ * @param context Pointer to the Argon2 internal structure+ * @return Error code if smth is wrong, ARGON2_OK otherwise+ */+ARGON2_PUBLIC int argon2_ctx(argon2_context *context, argon2_type type);++/**+ * Hashes a password with Argon2i, producing an encoded 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 hashlen Desired length of the hash in bytes+ * @param encoded Buffer where to write the encoded hash+ * @param encodedlen Size of the buffer (thus max size of the encoded hash)+ * @pre Different parallelism levels will give different results+ * @pre Returns ARGON2_OK if successful+ */+ARGON2_PUBLIC int argon2i_hash_encoded(const uint32_t t_cost,+ const uint32_t m_cost,+ const uint32_t parallelism,+ const void *pwd, const size_t pwdlen,+ const void *salt, const size_t saltlen,+ const size_t hashlen, char *encoded,+ const size_t encodedlen);++/**+ * Hashes a password with Argon2i, producing a raw hash by allocating memory 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 argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,+ const uint32_t parallelism, const void *pwd,+ const size_t pwdlen, const void *salt,+ const size_t saltlen, void *hash,+ const size_t hashlen);++ARGON2_PUBLIC int argon2d_hash_encoded(const uint32_t t_cost,+ const uint32_t m_cost,+ const uint32_t parallelism,+ const void *pwd, const size_t pwdlen,+ const void *salt, const size_t saltlen,+ const size_t hashlen, char *encoded,+ const size_t encodedlen);++ARGON2_PUBLIC int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,+ const uint32_t parallelism, const void *pwd,+ const size_t pwdlen, const void *salt,+ const size_t saltlen, void *hash,+ const size_t hashlen);++/* generic function underlying the above ones */+ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,+ const uint32_t parallelism, const void *pwd,+ const size_t pwdlen, const void *salt,+ const size_t saltlen, void *hash,+ const size_t hashlen, char *encoded,+ const size_t encodedlen, argon2_type type,+ const uint32_t version);++/**+ * Verifies a password against an encoded string+ * Encoded string is restricted as in validate_inputs()+ * @param encoded String encoding parameters, salt, hash+ * @param pwd Pointer to password+ * @pre Returns ARGON2_OK if successful+ */+ARGON2_PUBLIC int argon2i_verify(const char *encoded, const void *pwd,+ const size_t pwdlen);++ARGON2_PUBLIC int argon2d_verify(const char *encoded, const void *pwd,+ const size_t pwdlen);++/* generic function underlying the above ones */+ARGON2_PUBLIC int argon2_verify(const char *encoded, const void *pwd,+ const size_t pwdlen, argon2_type type);++/**+ * Argon2d: Version of Argon2 that picks memory blocks depending+ * on the password and salt. Only for side-channel-free+ * environment!!+ *****+ * @param context Pointer to current Argon2 context+ * @return Zero if successful, a non zero error code otherwise+ */+ARGON2_PUBLIC int argon2d_ctx(argon2_context *context);++/**+ * Argon2i: Version of Argon2 that picks memory blocks+ * independent on the password and salt. Good for side-channels,+ * but worse w.r.t. tradeoff attacks if only one pass is used.+ *****+ * @param context Pointer to current Argon2 context+ * @return Zero if successful, a non zero error code otherwise+ */+ARGON2_PUBLIC int argon2i_ctx(argon2_context *context);++/**+ * Verify if a given password is correct for Argon2d hashing+ * @param context Pointer to current Argon2 context+ * @param hash The password hash to verify. The length of the hash is+ * specified by the context outlen member+ * @return Zero if successful, a non zero error code otherwise+ */+ARGON2_PUBLIC int argon2d_verify_ctx(argon2_context *context, const char *hash);++/**+ * Verify if a given password is correct for Argon2i hashing+ * @param context Pointer to current Argon2 context+ * @param hash The password hash to verify. The length of the hash is+ * specified by the context outlen member+ * @return Zero if successful, a non zero error code otherwise+ */+ARGON2_PUBLIC int argon2i_verify_ctx(argon2_context *context, const char *hash);++/* generic function underlying the above ones */+ARGON2_PUBLIC int argon2_verify_ctx(argon2_context *context, const char *hash,+ argon2_type type);++/**+ * 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);++/**+ * Returns the encoded hash length for the given input parameters+ * @param t_cost Number of iterations+ * @param m_cost Memory usage in kibibytes+ * @param parallelism Number of threads; used to compute lanes+ * @param saltlen Salt size in bytes+ * @param hashlen Hash size in bytes+ * @return The encoded hash length in bytes+ */+ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost,+ uint32_t parallelism, uint32_t saltlen,+ uint32_t hashlen);++#if defined(__cplusplus)+}+#endif++#endif
phc-winner-argon2/src/argon2.c view
@@ -19,94 +19,8 @@ #include "encoding.h" #include "core.h" -/* Error messages */-static const char *Argon2_ErrorMessage[] = {- /*{ARGON2_OK, */ "OK",- /*}, - {ARGON2_OUTPUT_PTR_NULL, */ "Output pointer is NULL",- /*},--{ARGON2_OUTPUT_TOO_SHORT, */ "Output is too short",- /*},-{ARGON2_OUTPUT_TOO_LONG, */ "Output is too long",- /*},--{ARGON2_PWD_TOO_SHORT, */ "Password is too short",- /*},-{ARGON2_PWD_TOO_LONG, */ "Password is too long",- /*},--{ARGON2_SALT_TOO_SHORT, */ "Salt is too short",- /*},-{ARGON2_SALT_TOO_LONG, */ "Salt is too long",- /*},--{ARGON2_AD_TOO_SHORT, */ "Associated data is too short",- /*},-{ARGON2_AD_TOO_LONG, */ "Associated date is too long",- /*},--{ARGON2_SECRET_TOO_SHORT, */ "Secret is too short",- /*},-{ARGON2_SECRET_TOO_LONG, */ "Secret is too long",- /*},--{ARGON2_TIME_TOO_SMALL, */ "Time cost is too small",- /*},-{ARGON2_TIME_TOO_LARGE, */ "Time cost is too large",- /*},--{ARGON2_MEMORY_TOO_LITTLE, */ "Memory cost is too small",- /*},-{ARGON2_MEMORY_TOO_MUCH, */ "Memory cost is too large",- /*},--{ARGON2_LANES_TOO_FEW, */ "Too few lanes",- /*},-{ARGON2_LANES_TOO_MANY, */ "Too many lanes",- /*},--{ARGON2_PWD_PTR_MISMATCH, */ "Password pointer is NULL, but password length is not 0",- /*},-{ARGON2_SALT_PTR_MISMATCH, */ "Salt pointer is NULL, but salt length is not 0",- /*},-{ARGON2_SECRET_PTR_MISMATCH, */ "Secret pointer is NULL, but secret length is not 0",- /*},-{ARGON2_AD_PTR_MISMATCH, */ "Associated data pointer is NULL, but ad length is not 0",- /*},--{ARGON2_MEMORY_ALLOCATION_ERROR, */ "Memory allocation error",- /*},--{ARGON2_FREE_MEMORY_CBK_NULL, */ "The free memory callback is NULL",- /*},-{ARGON2_ALLOCATE_MEMORY_CBK_NULL, */ "The allocate memory callback is NULL",- /*},--{ARGON2_INCORRECT_PARAMETER, */ "Argon2_Context context is NULL",- /*},-{ARGON2_INCORRECT_TYPE, */ "There is no such version of Argon2",- /*},--{ARGON2_OUT_PTR_MISMATCH, */ "Output pointer mismatch",- /*},--{ARGON2_THREADS_TOO_FEW, */ "Not enough threads",- /*},-{ARGON2_THREADS_TOO_MANY, */ "Too many threads",- /*},-{ARGON2_MISSING_ARGS, */ "Missing arguments",- /*},-{ARGON2_ENCODING_FAIL, */ "Encoding failed",- /*},-{ARGON2_DECODING_FAIL, */ "Decoding failed",- /*},-{ARGON2_THREAD_FAIL */ "Threading failure", /*},*/-};---int argon2_core(argon2_context *context, argon2_type type) {+int argon2_ctx(argon2_context *context, argon2_type type) { /* 1. Validate all inputs */ int result = validate_inputs(context); uint32_t memory_blocks, segment_length;@@ -132,6 +46,7 @@ /* 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;@@ -162,29 +77,23 @@ return ARGON2_OK; } - int argon2_hash(const uint32_t t_cost, const uint32_t m_cost, const uint32_t parallelism, const void *pwd, const size_t pwdlen, const void *salt, const size_t saltlen, void *hash, const size_t hashlen, char *encoded,- const size_t encodedlen, argon2_type type) {+ const size_t encodedlen, argon2_type type, + const uint32_t version){ argon2_context context; int result; uint8_t *out; - /* Detect and reject overflowing sizes */- /* TODO: This should probably be fixed in the function signature */- if (pwdlen > UINT32_MAX) {- return ARGON2_PWD_TOO_LONG;- }-- if (hashlen > UINT32_MAX) {+ if (hashlen > ARGON2_MAX_OUTLEN) { return ARGON2_OUTPUT_TOO_LONG; } - if (saltlen > UINT32_MAX) {- return ARGON2_SALT_TOO_LONG;+ if (hashlen < ARGON2_MIN_OUTLEN) {+ return ARGON2_OUTPUT_TOO_SHORT; } out = malloc(hashlen);@@ -209,11 +118,12 @@ context.allocate_cbk = NULL; context.free_cbk = NULL; context.flags = ARGON2_DEFAULT_FLAGS;+ context.version = version; - result = argon2_core(&context, type);+ result = argon2_ctx(&context, type); if (result != ARGON2_OK) {- memset(out, 0x00, hashlen);+ secure_wipe_memory(out, hashlen); free(out); return result; }@@ -225,14 +135,14 @@ /* if encoding requested, write it */ if (encoded && encodedlen) {- if (!encode_string(encoded, encodedlen, &context, type)) {- memset(out, 0x00, hashlen);- memset(encoded, 0x00, encodedlen);+ if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {+ secure_wipe_memory(out, hashlen); /* wipe buffers if error */+ secure_wipe_memory(encoded, encodedlen); free(out); return ARGON2_ENCODING_FAIL; } }-+ secure_wipe_memory(out, hashlen); free(out); return ARGON2_OK;@@ -245,7 +155,8 @@ char *encoded, const size_t encodedlen) { return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,- NULL, hashlen, encoded, encodedlen, Argon2_i);+ NULL, hashlen, encoded, encodedlen, Argon2_i,+ ARGON2_VERSION_NUMBER); } int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,@@ -254,7 +165,7 @@ const size_t saltlen, void *hash, const size_t hashlen) { return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,- hash, hashlen, NULL, 0, Argon2_i);+ hash, hashlen, NULL, 0, Argon2_i, ARGON2_VERSION_NUMBER); } int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,@@ -264,7 +175,8 @@ char *encoded, const size_t encodedlen) { return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,- NULL, hashlen, encoded, encodedlen, Argon2_d);+ NULL, hashlen, encoded, encodedlen, Argon2_d,+ ARGON2_VERSION_NUMBER); } int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,@@ -273,7 +185,7 @@ const size_t saltlen, void *hash, const size_t hashlen) { return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,- hash, hashlen, NULL, 0, Argon2_d);+ hash, hashlen, NULL, 0, Argon2_d, ARGON2_VERSION_NUMBER); } static int argon2_compare(const uint8_t *b1, const uint8_t *b2, size_t len) {@@ -292,12 +204,30 @@ argon2_context ctx; uint8_t *out; int ret;+ int decode_result;+ uint32_t encoded_len;+ size_t encoded_len_tmp; + if(encoded == NULL) {+ return ARGON2_DECODING_FAIL;+ }++ encoded_len_tmp = strlen(encoded); /* max values, to be updated in decode_string */- ctx.adlen = 512;- ctx.saltlen = 512;- ctx.outlen = 512;+ if (UINT32_MAX < encoded_len_tmp) {+ return ARGON2_DECODING_FAIL;+ } + encoded_len = (uint32_t)encoded_len_tmp;+ ctx.adlen = encoded_len;+ ctx.saltlen = encoded_len;+ ctx.outlen = encoded_len;+ ctx.allocate_cbk = NULL;+ ctx.free_cbk = NULL;+ ctx.secret = NULL;+ ctx.secretlen = 0;+ ctx.pwdlen = 0;+ ctx.pwd = NULL; ctx.ad = malloc(ctx.adlen); ctx.salt = malloc(ctx.saltlen); ctx.out = malloc(ctx.outlen);@@ -314,30 +244,29 @@ free(ctx.out); return ARGON2_MEMORY_ALLOCATION_ERROR; }-- if(decode_string(&ctx, encoded, type) != 1) {+ decode_result = decode_string(&ctx, encoded, type);+ if (decode_result != ARGON2_OK) { free(ctx.ad); free(ctx.salt); free(ctx.out); free(out);- return ARGON2_DECODING_FAIL;+ return decode_result; } - ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen, ctx.salt,- ctx.saltlen, out, ctx.outlen, NULL, 0, type);+ ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen,+ ctx.salt, ctx.saltlen, out, ctx.outlen, NULL, 0, type,+ ctx.version); free(ctx.ad); free(ctx.salt); - if (ret != ARGON2_OK || argon2_compare(out, ctx.out, ctx.outlen)) {- free(out);- free(ctx.out);- return ARGON2_DECODING_FAIL;+ if (ret == ARGON2_OK && argon2_compare(out, ctx.out, ctx.outlen)) {+ ret = ARGON2_VERIFY_MISMATCH; } free(out); free(ctx.out); - return ARGON2_OK;+ return ret; } int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) {@@ -350,17 +279,22 @@ return argon2_verify(encoded, pwd, pwdlen, Argon2_d); } -int argon2d(argon2_context *context) { return argon2_core(context, Argon2_d); }+int argon2d_ctx(argon2_context *context) {+ return argon2_ctx(context, Argon2_d);+} -int argon2i(argon2_context *context) { return argon2_core(context, Argon2_i); }+int argon2i_ctx(argon2_context *context) {+ return argon2_ctx(context, Argon2_i);+} -int verify_d(argon2_context *context, const char *hash) {+int argon2_verify_ctx(argon2_context *context, const char *hash,+ argon2_type type) { int result; if (0 == context->outlen || NULL == hash) { return ARGON2_OUT_PTR_MISMATCH; } - result = argon2_core(context, Argon2_d);+ result = argon2_ctx(context, type); if (ARGON2_OK != result) { return result;@@ -369,33 +303,96 @@ return 0 == memcmp(hash, context->out, context->outlen); } -int verify_i(argon2_context *context, const char *hash) {- int result;- if (0 == context->outlen || NULL == hash) {- return ARGON2_OUT_PTR_MISMATCH;- }+int argon2d_verify_ctx(argon2_context *context, const char *hash) {+ return argon2_verify_ctx(context, hash, Argon2_d);+} - result = argon2_core(context, Argon2_i);+int argon2i_verify_ctx(argon2_context *context, const char *hash) {+ return argon2_verify_ctx(context, hash, Argon2_i);+} - if (ARGON2_OK != result) {- return result;+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 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"; }-- return 0 == memcmp(hash, context->out, context->outlen); } --const char *error_message(int error_code) {- enum {- /* Make sure---at compile time---that the enum size matches the array- size */- ERROR_STRING_CHECK =- 1 /- !!((sizeof(Argon2_ErrorMessage) / sizeof(Argon2_ErrorMessage[0])) ==- ARGON2_ERROR_CODES_LENGTH)- };- if (error_code >= 0 && error_code < ARGON2_ERROR_CODES_LENGTH) {- return Argon2_ErrorMessage[(argon2_error_codes)error_code];- }- return "Unknown error code.";+size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism,+ uint32_t saltlen, uint32_t hashlen) {+ return strlen("$argon2x$v=$m=,t=,p=$$") + numlen(t_cost) + numlen(m_cost)+ + numlen(parallelism) + b64len(saltlen) + b64len(hashlen)+ + numlen(ARGON2_VERSION_NUMBER) + 1; }
+ phc-winner-argon2/src/blake2/blake2-impl.h view
@@ -0,0 +1,139 @@+#ifndef PORTABLE_BLAKE2_IMPL_H+#define PORTABLE_BLAKE2_IMPL_H++#include <stdint.h>+#include <string.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 uint32_t load32(const void *src) {+#if defined(NATIVE_LITTLE_ENDIAN)+ uint32_t w;+ memcpy(&w, src, sizeof w);+ return w;+#else+ const uint8_t *p = (const uint8_t *)src;+ uint32_t w = *p++;+ w |= (uint32_t)(*p++) << 8;+ w |= (uint32_t)(*p++) << 16;+ w |= (uint32_t)(*p++) << 24;+ return w;+#endif+}++static BLAKE2_INLINE uint64_t load64(const void *src) {+#if defined(NATIVE_LITTLE_ENDIAN)+ uint64_t w;+ memcpy(&w, src, sizeof w);+ return w;+#else+ const uint8_t *p = (const uint8_t *)src;+ uint64_t w = *p++;+ w |= (uint64_t)(*p++) << 8;+ w |= (uint64_t)(*p++) << 16;+ w |= (uint64_t)(*p++) << 24;+ w |= (uint64_t)(*p++) << 32;+ w |= (uint64_t)(*p++) << 40;+ w |= (uint64_t)(*p++) << 48;+ w |= (uint64_t)(*p++) << 56;+ return w;+#endif+}++static BLAKE2_INLINE void store32(void *dst, uint32_t w) {+#if defined(NATIVE_LITTLE_ENDIAN)+ memcpy(dst, &w, sizeof w);+#else+ uint8_t *p = (uint8_t *)dst;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+#endif+}++static BLAKE2_INLINE void store64(void *dst, uint64_t w) {+#if defined(NATIVE_LITTLE_ENDIAN)+ memcpy(dst, &w, sizeof w);+#else+ uint8_t *p = (uint8_t *)dst;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+#endif+}++static BLAKE2_INLINE uint64_t load48(const void *src) {+ const uint8_t *p = (const uint8_t *)src;+ uint64_t w = *p++;+ w |= (uint64_t)(*p++) << 8;+ w |= (uint64_t)(*p++) << 16;+ w |= (uint64_t)(*p++) << 24;+ w |= (uint64_t)(*p++) << 32;+ w |= (uint64_t)(*p++) << 40;+ return w;+}++static BLAKE2_INLINE void store48(void *dst, uint64_t w) {+ uint8_t *p = (uint8_t *)dst;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+ w >>= 8;+ *p++ = (uint8_t)w;+}++static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) {+ return (w >> c) | (w << (32 - c));+}++static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) {+ return (w >> c) | (w << (64 - c));+}++void secure_wipe_memory(void *v, size_t n);++#endif
+ phc-winner-argon2/src/blake2/blake2.h view
@@ -0,0 +1,74 @@+#ifndef PORTABLE_BLAKE2_H+#define PORTABLE_BLAKE2_H++#include <stddef.h>+#include <stdint.h>+#include <limits.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 {+ uint8_t digest_length; /* 1 */+ uint8_t key_length; /* 2 */+ uint8_t fanout; /* 3 */+ uint8_t depth; /* 4 */+ uint32_t leaf_length; /* 8 */+ uint64_t node_offset; /* 16 */+ uint8_t node_depth; /* 17 */+ uint8_t inner_length; /* 18 */+ uint8_t reserved[14]; /* 32 */+ uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */+ uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */+} blake2b_param;+#pragma pack(pop)++typedef struct __blake2b_state {+ uint64_t h[8];+ uint64_t t[2];+ uint64_t f[2];+ uint8_t buf[BLAKE2B_BLOCKBYTES];+ unsigned buflen;+ unsigned outlen;+ 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 / !!(CHAR_BIT == 8),+ blake2_size_check_2 =+ 1 / !!(sizeof(blake2b_param) == sizeof(uint64_t) * CHAR_BIT)+};++/* Streaming API */+int blake2b_init(blake2b_state *S, size_t outlen);+int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,+ size_t keylen);+int blake2b_init_param(blake2b_state *S, const blake2b_param *P);+int blake2b_update(blake2b_state *S, const void *in, size_t inlen);+int blake2b_final(blake2b_state *S, void *out, size_t outlen);++/* Simple API */+int blake2b(void *out, size_t outlen, const void *in, size_t inlen,+ const void *key, size_t keylen);++/* Argon2 Team - Begin Code */+int blake2b_long(void *out, size_t outlen, const void *in, size_t inlen);+/* Argon2 Team - End Code */++#if defined(__cplusplus)+}+#endif++#endif
phc-winner-argon2/src/blake2/blake2b.c view
@@ -44,7 +44,7 @@ } static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) {- burn(S, sizeof(*S)); /* wipe */+ secure_wipe_memory(S, sizeof(*S)); /* wipe */ blake2b_set_lastblock(S); /* invalidate for further use */ } @@ -140,7 +140,7 @@ memset(block, 0, BLAKE2B_BLOCKBYTES); memcpy(block, key, keylen); blake2b_update(S, block, BLAKE2B_BLOCKBYTES);- burn(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */+ secure_wipe_memory(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */ } return 0; }@@ -267,9 +267,9 @@ } memcpy(out, buffer, S->outlen);- burn(buffer, sizeof(buffer));- burn(S->buf, sizeof(S->buf));- burn(S->h, sizeof(S->h));+ secure_wipe_memory(buffer, sizeof(buffer));+ secure_wipe_memory(S->buf, sizeof(S->buf));+ secure_wipe_memory(S->h, sizeof(S->h)); return 0; } @@ -307,7 +307,7 @@ ret = blake2b_final(&S, out, outlen); fail:- burn(&S, sizeof(S));+ secure_wipe_memory(&S, sizeof(S)); return ret; } @@ -365,7 +365,7 @@ memcpy(out, out_buffer, toproduce); } fail:- burn(&blake_state, sizeof(blake_state));+ secure_wipe_memory(&blake_state, sizeof(blake_state)); return ret; #undef TRY }
+ phc-winner-argon2/src/blake2/blamka-round-ref.h view
@@ -0,0 +1,39 @@+#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 uint64_t fBlaMka(uint64_t x, uint64_t y) {+ const uint64_t m = UINT64_C(0xFFFFFFFF);+ const 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
phc-winner-argon2/src/core.c view
@@ -93,7 +93,6 @@ if (!*memory) { return ARGON2_MEMORY_ALLOCATION_ERROR; }- return ARGON2_OK; } else { return ARGON2_MEMORY_ALLOCATION_ERROR;@@ -104,7 +103,7 @@ #if defined(_MSC_VER) && VC_GE_2005(_MSC_VER) SecureZeroMemory(v, n); #elif defined memset_s- memset_s(v, n);+ memset_s(v, n, 0, n); #elif defined(__OpenBSD__) explicit_bzero(v, n); #else@@ -283,6 +282,8 @@ if (l >= instance->threads) { rc = argon2_thread_join(thread[l - instance->threads]); if (rc) {+ free(thr_data);+ free(thread); return ARGON2_THREAD_FAIL; } }@@ -299,6 +300,8 @@ rc = argon2_thread_create(&thread[l], &fill_segment_thr, (void *)&thr_data[l]); if (rc) {+ free(thr_data);+ free(thread); return ARGON2_THREAD_FAIL; } @@ -417,7 +420,7 @@ return ARGON2_MEMORY_TOO_MUCH; } - if (context->m_cost < 8*context->lanes) {+ if (context->m_cost < 8 * context->lanes) { return ARGON2_MEMORY_TOO_LITTLE; } @@ -505,7 +508,7 @@ store32(&value, context->t_cost); blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); - store32(&value, ARGON2_VERSION_NUMBER);+ store32(&value, context->version); blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); store32(&value, (uint32_t)type);@@ -572,7 +575,7 @@ if (ARGON2_OK != result) { return result; }- memcpy(&(instance->memory), p, sizeof(instance->memory));+ instance->memory = (block *)p; } else { result = allocate_memory(&(instance->memory), instance->memory_blocks); if (ARGON2_OK != result) {@@ -602,4 +605,3 @@ return ARGON2_OK; }-
+ phc-winner-argon2/src/core.h view
@@ -0,0 +1,219 @@+/*+ * Argon2 source code package+ *+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015+ *+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.+ *+ * You should have received a copy of the CC0 Public Domain Dedication along+ * with+ * this software. If not, see+ * <http://creativecommons.org/publicdomain/zero/1.0/>.+ */++#ifndef ARGON2_CORE_H+#define ARGON2_CORE_H++#include "argon2.h"++#if defined(_MSC_VER)+#define ALIGN(n) __declspec(align(16))+#elif defined(__GNUC__) || defined(__clang)+#define ALIGN(x) __attribute__((__aligned__(x)))+#else+#define ALIGN(x)+#endif++#define CONST_CAST(x) (x)(uintptr_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,++ /* 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_ { 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, 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 */+ uint32_t version;+ uint32_t passes; /* Number of passes */+ uint32_t memory_blocks; /* Number of blocks in memory */+ uint32_t segment_length;+ uint32_t lane_length;+ uint32_t lanes;+ uint32_t threads;+ argon2_type type;+ int print_internals; /* whether to print the memory blocks */+} argon2_instance_t;++/*+ * Argon2 position: where we construct the block right now. Used to distribute+ * work between threads.+ */+typedef struct Argon2_position_t {+ uint32_t pass;+ uint32_t lane;+ uint8_t slice;+ 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+ * @param memory pointer to the pointer to the memory+ * @param m_cost number of blocks to allocate in the memory+ * @return ARGON2_OK if @memory is a valid pointer and memory is allocated+ */+int allocate_memory(block **memory, uint32_t m_cost);++/* Function that securely cleans the memory+ * @param mem Pointer to the memory+ * @param s Memory size in bytes+ */+void secure_wipe_memory(void *v, size_t n);++/* Clears memory+ * @param instance pointer to the current instance+ * @param clear_memory indicates if we clear the memory with zeros.+ */+void clear_memory(argon2_instance_t *instance, int clear);++/* Deallocates memory+ * @param memory pointer to the blocks+ */+void free_memory(block *memory);++/*+ * 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+ */+uint32_t index_alpha(const argon2_instance_t *instance,+ const argon2_position_t *position, 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(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(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->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 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
phc-winner-argon2/src/encoding.c view
@@ -3,9 +3,10 @@ #include <string.h> #include <limits.h> #include "encoding.h"+#include "core.h" -#/*- * Example code for a decoder and encoder of "hash strings", with Argon2i+/*+ * Example code for a decoder and encoder of "hash strings", with Argon2 * parameters. * * This code comprises three sections:@@ -17,7 +18,7 @@ * the relevant functions are made public (non-static) and be given * reasonable names to avoid collisions with other functions. *- * -- The second section is specific to Argon2i. It encodes and decodes+ * -- The second section is specific to Argon2. It encodes and decodes * the parameters, salts and outputs. It does not compute the hash * itself. *@@ -58,7 +59,7 @@ * Some macros for constant-time comparisons. These work over values in * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true". */-#define EQ(x, y) ((((0U-((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)+#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF) #define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF) #define GE(x, y) (GT(y, x) ^ 0xFF) #define LT(x, y) GT(y, x)@@ -122,11 +123,11 @@ acc_len += 8; while (acc_len >= 6) { acc_len -= 6;- *dst++ = (char) b64_byte_to_char((acc >> acc_len) & 0x3F);+ *dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F); } } if (acc_len > 0) {- *dst++ = (char) b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);+ *dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F); } *dst++ = 0; return olen;@@ -224,16 +225,17 @@ /* ==================================================================== */ /*- * Code specific to Argon2i.+ * Code specific to Argon2. * * The code below applies the following format: *- * $argon2i$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]+ * $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]] *- * where <num> is a decimal integer (positive, fits in an 'unsigned long')- * and <bin> is Base64-encoded data (no '=' padding characters, no newline- * or whitespace). The "keyid" is a binary identifier for a key (up to 8- * bytes); "data" is associated data (up to 32 bytes). When the 'keyid'+ * where <T> is either 'd' or 'i', <num> is a decimal integer (positive, fits in+ * an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding+ * characters, no newline or whitespace).+ * The "keyid" is a binary identifier for a key (up to 8 bytes);+ * "data" is associated data (up to 32 bytes). When the 'keyid' * (resp. the 'data') is empty, then it is ommitted from the output. * * The last two binary chunks (encoded in Base64) are, in that order,@@ -242,20 +244,19 @@ * The output length is always exactly 32 bytes. */ -/*- * Decode an Argon2i hash string into the provided structure 'ctx'.- * Returned value is 1 on success, 0 on error.- */ int decode_string(argon2_context *ctx, const char *str, argon2_type type) {++/* check for prefix */ #define CC(prefix) \ do { \ size_t cc_len = strlen(prefix); \ if (strncmp(str, prefix, cc_len) != 0) { \- return 0; \+ return ARGON2_DECODING_FAIL; \ } \ str += cc_len; \ } while ((void)0, 0) +/* prefix checking with supplied code */ #define CC_opt(prefix, code) \ do { \ size_t cc_len = strlen(prefix); \@@ -265,12 +266,13 @@ } \ } while ((void)0, 0) +/* Decoding prefix into decimal */ #define DECIMAL(x) \ do { \ unsigned long dec_x; \ str = decode_decimal(str, &dec_x); \ if (str == NULL) { \- return 0; \+ return ARGON2_DECODING_FAIL; \ } \ (x) = dec_x; \ } while ((void)0, 0)@@ -280,7 +282,7 @@ size_t bin_len = (max_len); \ str = from_base64(buf, &bin_len, str); \ if (str == NULL || bin_len > UINT32_MAX) { \- return 0; \+ return ARGON2_DECODING_FAIL; \ } \ (len) = (uint32_t)bin_len; \ } while ((void)0, 0)@@ -288,16 +290,22 @@ size_t maxadlen = ctx->adlen; size_t maxsaltlen = ctx->saltlen; size_t maxoutlen = ctx->outlen;+ int validation_result; ctx->adlen = 0; ctx->saltlen = 0; ctx->outlen = 0;+ ctx->pwdlen = 0;+ if (type == Argon2_i) CC("$argon2i"); else if (type == Argon2_d) CC("$argon2d"); else- return 0;+ return ARGON2_INCORRECT_TYPE;+ ctx->version = ARGON2_VERSION_10;+ /* Reading the version number if the default is suppressed */+ CC_opt("$v=", DECIMAL(ctx->version)); CC("$m="); DECIMAL(ctx->m_cost); CC(",t=");@@ -306,75 +314,39 @@ DECIMAL(ctx->lanes); ctx->threads = ctx->lanes; - /*- * Both m and t must be no more than 2^32-1. The tests below- * use a shift by 30 bits to avoid a direct comparison with- * 0xFFFFFFFF, which may trigger a spurious compiler warning- * on machines where 'unsigned long' is a 32-bit type.- */- if (ctx->m_cost < 1 || (ctx->m_cost >> 30) > 3) {- return 0;- }- if (ctx->t_cost < 1 || (ctx->t_cost >> 30) > 3) {- return 0;- }-- /*- * The parallelism p must be between 1 and 255. The memory cost- * parameter, expressed in kilobytes, must be at least 8 times- * the value of p.- */- if (ctx->lanes < 1 || ctx->lanes > 255) {- return 0;- }- if (ctx->m_cost < (ctx->lanes << 3)) {- return 0;- }- CC_opt(",data=", BIN(ctx->ad, maxadlen, ctx->adlen)); if (*str == 0) {- return 1;+ return ARGON2_OK; } CC("$"); BIN(ctx->salt, maxsaltlen, ctx->saltlen);- if (ctx->saltlen < 8) {- return 0;- } if (*str == 0) {- return 1;+ return ARGON2_OK; } CC("$"); BIN(ctx->out, maxoutlen, ctx->outlen);- if (ctx->outlen < 12) {- return 0;+ validation_result = validate_inputs(ctx);+ if (validation_result != ARGON2_OK) {+ return validation_result; }- return *str == 0;-+ if (*str == 0) {+ return ARGON2_OK;+ } else {+ return ARGON2_DECODING_FAIL;+ } #undef CC #undef CC_opt #undef DECIMAL #undef BIN } -/*- * encode an argon2i hash string into the provided buffer. 'dst_len'- * contains the size, in characters, of the 'dst' buffer; if 'dst_len'- * is less than the number of required characters (including the- * terminating 0), then this function returns 0.- *- * if pp->output_len is 0, then the hash string will be a salt string- * (no output). if pp->salt_len is also 0, then the string will be a- * parameter-only string (no salt and no output).- *- * on success, 1 is returned.- */ int encode_string(char *dst, size_t dst_len, argon2_context *ctx, argon2_type type) { #define SS(str) \ do { \ size_t pp_len = strlen(str); \ if (pp_len >= dst_len) { \- return 0; \+ return ARGON2_ENCODING_FAIL; \ } \ memcpy(dst, str, pp_len + 1); \ dst += pp_len; \@@ -392,18 +364,24 @@ do { \ size_t sb_len = to_base64(dst, dst_len, buf, len); \ if (sb_len == (size_t)-1) { \- return 0; \+ return ARGON2_ENCODING_FAIL; \ } \ dst += sb_len; \ dst_len -= sb_len; \ } while ((void)0, 0) if (type == Argon2_i)- SS("$argon2i$m=");+ SS("$argon2i$v="); else if (type == Argon2_d)- SS("$argon2d$m=");+ SS("$argon2d$v="); else- return 0;+ return ARGON2_ENCODING_FAIL;++ if (validate_inputs(ctx) != ARGON2_OK) {+ return validate_inputs(ctx);+ }+ SX(ctx->version);+ SS("$m="); SX(ctx->m_cost); SS(",t="); SX(ctx->t_cost);@@ -416,19 +394,44 @@ } if (ctx->saltlen == 0)- return 1;+ return ARGON2_OK; SS("$"); SB(ctx->salt, ctx->saltlen); if (ctx->outlen == 0)- return 1;+ return ARGON2_OK; SS("$"); SB(ctx->out, ctx->outlen);- return 1;+ return ARGON2_OK; #undef SS #undef SX #undef SB }++size_t b64len(uint32_t len) {+ size_t olen = ((size_t)len / 3) << 2;++ switch (len % 3) {+ case 2:+ olen++;+ /* fall through */+ case 1:+ olen += 2;+ break;+ }++ return olen;+}++size_t numlen(uint32_t num) {+ size_t len = 1;+ while (num >= 10) {+ ++len;+ num = num / 10;+ }+ return len;+}+
+ phc-winner-argon2/src/encoding.h view
@@ -0,0 +1,40 @@+#ifndef ENCODING_H+#define ENCODING_H+#include "argon2.h"++#define ARGON2_MAX_DECODED_LANES UINT32_C(255)+#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)+#define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12)++/*+* encode an Argon2 hash string into the provided buffer. 'dst_len'+* contains the size, in characters, of the 'dst' buffer; if 'dst_len'+* is less than the number of required characters (including the+* terminating 0), then this function returns ARGON2_ENCODING_ERROR.+*+* if ctx->outlen is 0, then the hash string will be a salt string+* (no output). if ctx->saltlen is also 0, then the string will be a+* parameter-only string (no salt and no output).+*+* on success, ARGON2_OK is returned.+*+* No other parameters are checked+*/+int encode_string(char *dst, size_t dst_len, argon2_context *ctx,+ argon2_type type);++/*+* Decodes an Argon2 hash string into the provided structure 'ctx'.+* The fields ctx.saltlen, ctx.adlen, ctx.outlen set the maximal salt, ad, out+* length values that are allowed; invalid input string causes an error.+* Returned value is ARGON2_OK on success, other ARGON2_ codes on error.+*/+int decode_string(argon2_context *ctx, const char *str, argon2_type type);++/* Returns the length of the encoded byte stream with length len */+size_t b64len(uint32_t len);++/* Returns the length of the encoded number num */+size_t numlen(uint32_t num);++#endif
phc-winner-argon2/src/ref.c view
@@ -22,15 +22,55 @@ #include "blake2/blake2-impl.h" #include "blake2/blake2.h" + void fill_block(const block *prev_block, const block *ref_block,- block *next_block) {+ block *next_block) { 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 bloc_tmp = ref_block + prev_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);+}+++void fill_block_with_xor(const block *prev_block, const block *ref_block,+ block *next_block) {+ block blockR, block_tmp;+ unsigned i;++ copy_block(&blockR, ref_block);+ xor_block(&blockR, prev_block);+ copy_block(&block_tmp, &blockR);+ xor_block(&block_tmp, next_block); /*Saving the next block contents for XOR over*/+ /*Now blockR = ref_block + prev_block and bloc_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) {@@ -62,12 +102,11 @@ void generate_addresses(const argon2_instance_t *instance, const argon2_position_t *position, uint64_t *pseudo_rands) {- block zero_block, input_block, address_block;+ block zero_block, input_block, address_block,tmp_block; uint32_t i; init_block_value(&zero_block, 0); init_block_value(&input_block, 0);- init_block_value(&address_block, 0); if (instance != NULL && position != NULL) { input_block.v[0] = position->pass;@@ -80,8 +119,10 @@ for (i = 0; i < instance->segment_length; ++i) { if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { input_block.v[6]++;- fill_block(&zero_block, &input_block, &address_block);- fill_block(&zero_block, &address_block, &address_block);+ init_block_value(&tmp_block, 0);+ init_block_value(&address_block, 0);+ fill_block_with_xor(&zero_block, &input_block, &tmp_block);+ fill_block_with_xor(&zero_block, &tmp_block, &address_block); } pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];@@ -169,7 +210,18 @@ ref_block = instance->memory + instance->lane_length * ref_lane + ref_index; curr_block = instance->memory + curr_offset;- fill_block(instance->memory + prev_offset, ref_block, curr_block);+ 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);+ } else {+ if(0 == position.pass) {+ fill_block(instance->memory + prev_offset, ref_block,+ curr_block);+ } else {+ fill_block_with_xor(instance->memory + prev_offset, ref_block,+ curr_block);+ }+ } } free(pseudo_rands);
+ phc-winner-argon2/src/ref.h view
@@ -0,0 +1,51 @@+/*+ * Argon2 source code package+ *+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015+ *+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.+ *+ * You should have received a copy of the CC0 Public Domain Dedication along+ * with+ * this software. If not, see+ * <http://creativecommons.org/publicdomain/zero/1.0/>.+ */++#ifndef ARGON2_REF_H+#define ARGON2_REF_H++#include "core.h"++/*+ * Function fills a new memory block by XORing over @next_block. @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+ * @pre all block pointers must be valid+ */+void fill_block_with_xor(const block *prev_block, const block *ref_block,+ block *next_block);++/* LEGACY CODE: version 1.2.1 and earlier+* Function fills a new memory block by overwriting @next_block. +* @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+* @pre all block pointers must be valid+*/+void fill_block(const block *prev_block, const block *ref_block,+ block *next_block);++/*+ * Generate pseudo-random values to reference blocks in the segment and puts+ * them into the array+ * @param instance Pointer to the current instance+ * @param position Pointer to the current position+ * @param pseudo_rands Pointer to the array of 64-bit values+ * @pre pseudo_rands must point to @a instance->segment_length allocated values+ */+void generate_addresses(const argon2_instance_t *instance,+ const argon2_position_t *position,+ uint64_t *pseudo_rands);++#endif /* ARGON2_REF_H */
phc-winner-argon2/src/thread.c view
@@ -1,6 +1,6 @@ #include "thread.h" #if defined(_WIN32)-#include <Windows.h>+#include <windows.h> #endif int argon2_thread_create(argon2_thread_handle_t *handle,
+ phc-winner-argon2/src/thread.h view
@@ -0,0 +1,46 @@+#ifndef ARGON2_THREAD_H+#define ARGON2_THREAD_H+/*+ Here we implement an abstraction layer for the simpĺe requirements+ of the Argon2 code. We only require 3 primitives---thread creation,+ joining, and termination---so full emulation of the pthreads API+ is unwarranted. Currently we wrap pthreads and Win32 threads.++ The API defines 2 types: the function pointer type,+ argon2_thread_func_t,+ and the type of the thread handle---argon2_thread_handle_t.+*/+#if defined(_WIN32)+#include <process.h>+typedef unsigned(__stdcall *argon2_thread_func_t)(void *);+typedef uintptr_t argon2_thread_handle_t;+#else+#include <pthread.h>+typedef void *(*argon2_thread_func_t)(void *);+typedef pthread_t argon2_thread_handle_t;+#endif++/* Creates a thread+ * @param handle pointer to a thread handle, which is the output of this+ * function. Must not be NULL.+ * @param func A function pointer for the thread's entry point. Must not be+ * NULL.+ * @param args Pointer that is passed as an argument to @func. May be NULL.+ * @return 0 if @handle and @func are valid pointers and a thread is successfuly+ * created.+ */+int argon2_thread_create(argon2_thread_handle_t *handle,+ argon2_thread_func_t func, void *args);++/* Waits for a thread to terminate+ * @param handle Handle to a thread created with argon2_thread_create.+ * @return 0 if @handle is a valid handle, and joining completed successfully.+*/+int argon2_thread_join(argon2_thread_handle_t handle);++/* Terminate the current thread. Must be run inside a thread created by+ * argon2_thread_create.+*/+void argon2_thread_exit(void);++#endif
src/Crypto/Argon2.hs view
@@ -117,9 +117,9 @@ -- will be throw. data Argon2Exception = -- | The length of the supplied password is outside the range supported by @libargon2@.- Argon2PasswordLengthOutOfRange !Word64 -- ^ The erroneous length.+ Argon2PasswordLengthOutOfRange !CSize -- ^ The erroneous length. | -- | The length of the supplied salt is outside the range supported by @libargon2@.- Argon2SaltLengthOutOfRange !Word64 -- ^ The erroneous length.+ Argon2SaltLengthOutOfRange !CSize -- ^ The erroneous length. | -- | Either too much or too little memory was requested via 'hashMemory'. Argon2MemoryUseOutOfRange !Word32 -- ^ The erroneous 'hashMemory' value. | -- | Either too few or too many iterations were requested via 'hashIterations'.@@ -132,7 +132,7 @@ instance Exception Argon2Exception -type Argon2Encoded = Word32 -> Word32 -> Word32 -> CString -> Word64 -> CString -> Word64 -> Word64 -> CString -> Word64 -> IO Int32+type Argon2Encoded = Word32 -> Word32 -> Word32 -> CString -> CSize -> CString -> CSize -> CSize -> CString -> CSize -> IO Int32 hashEncoded' :: HashOptions -> BS.ByteString@@ -143,10 +143,12 @@ hashEncoded' options@HashOptions{..} password salt argon2i argon2d = do let saltLen = fromIntegral (BS.length salt) passwordLen = fromIntegral (BS.length password)- outLen =- (BS.length salt * 4 + 32 * 4 +- length ("$argon2x$m=,t=,p=$$" :: String) +- 3 * 3)+ outLen <- fmap fromIntegral $ FFI.argon2_encodedlen+ hashIterations+ hashMemory+ hashParallelism+ saltLen+ hashlen out <- mallocBytes outLen res <- BS.useAsCString password $@@ -159,15 +161,16 @@ password' passwordLen salt'- saltLen- 64+ (fromIntegral saltLen)+ (fromIntegral hashlen) out (fromIntegral outLen) handleSuccessCode res options password salt fmap T.decodeUtf8 (BS.packCString out) where argon2 = variant argon2i argon2d hashVariant+ hashlen = 64 -type Argon2Unencoded = Word32 -> Word32 -> Word32 -> CString -> Word64 -> CString -> Word64 -> CString -> Word64 -> IO Int32+type Argon2Unencoded = Word32 -> Word32 -> Word32 -> CString -> CSize -> CString -> CSize -> CString -> CSize -> IO Int32 hash' :: HashOptions -> BS.ByteString@@ -195,7 +198,7 @@ out (fromIntegral outLen) handleSuccessCode res options password salt- BS.packCString out+ BS.packCStringLen (out, outLen) where argon2 = variant argon2i argon2d hashVariant handleSuccessCode :: Int32
src/Crypto/Argon2/FFI.hsc view
@@ -9,17 +9,19 @@ import Foreign import Foreign.C -foreign import ccall unsafe "argon2.h argon2i_hash_encoded" argon2i_hash_encoded :: (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> Ptr a -> (#type const size_t) -> Ptr b -> (# type const size_t) -> (#type const size_t) -> CString -> (#type const size_t) -> IO (#type int)+foreign import ccall unsafe "argon2.h argon2i_hash_encoded" argon2i_hash_encoded :: (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> Ptr a -> CSize -> Ptr b -> CSize -> CSize -> CString -> CSize -> IO (#type int) -foreign import ccall unsafe "argon2.h argon2i_hash_raw" argon2i_hash_raw :: (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> Ptr a -> (#type const size_t) -> Ptr b -> (#type size_t) -> Ptr c -> (#type const size_t) -> IO (#type int)+foreign import ccall unsafe "argon2.h argon2i_hash_raw" argon2i_hash_raw :: (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> Ptr a -> CSize -> Ptr b -> CSize -> Ptr c -> CSize -> IO (#type int) -foreign import ccall unsafe "argon2.h argon2d_hash_encoded" argon2d_hash_encoded :: (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> Ptr a -> (#type const size_t) -> Ptr b -> (# type const size_t) -> (#type const size_t) -> CString -> (#type const size_t) -> IO (#type int)+foreign import ccall unsafe "argon2.h argon2d_hash_encoded" argon2d_hash_encoded :: (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> Ptr a -> CSize -> Ptr b -> CSize -> CSize -> CString -> CSize -> IO (#type int) -foreign import ccall unsafe "argon2.h argon2d_hash_raw" argon2d_hash_raw :: (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> Ptr a -> (#type const size_t) -> Ptr b -> (#type size_t) -> Ptr c -> (#type const size_t) -> IO (#type int)+foreign import ccall unsafe "argon2.h argon2d_hash_raw" argon2d_hash_raw :: (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> Ptr a -> CSize -> Ptr b -> CSize -> Ptr c -> CSize -> IO (#type int) -foreign import ccall unsafe "argon2.h argon2i_verify" argon2i_verify :: CString -> Ptr a -> (#type const size_t) -> IO (#type int)+foreign import ccall unsafe "argon2.h argon2i_verify" argon2i_verify :: CString -> Ptr a -> CSize -> IO (#type int) -foreign import ccall unsafe "argon2.h argon2d_verify" argon2d_verify :: CString -> Ptr a -> (#type const size_t) -> IO (#type int)+foreign import ccall unsafe "argon2.h argon2d_verify" argon2d_verify :: CString -> Ptr a -> CSize -> IO (#type int)++foreign import ccall unsafe "argon2.h argon2_encodedlen" argon2_encodedlen :: (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> (#type const uint32_t) -> IO CSize pattern ARGON2_OK = (#const ARGON2_OK) pattern ARGON2_OUTPUT_PTR_NULL = (#const ARGON2_OUTPUT_PTR_NULL)