summaryrefslogtreecommitdiff
path: root/libs/libsodium/src/crypto_pwhash
diff options
context:
space:
mode:
authoraunsane <aunsane@gmail.com>2017-12-15 01:05:56 +0300
committeraunsane <aunsane@gmail.com>2017-12-15 01:05:56 +0300
commite124aa3611f38573898aa79c6eabe77bc874e58f (patch)
tree819464260f758bbc002b23c0c8a77f93751dcb42 /libs/libsodium/src/crypto_pwhash
parentbbd9647d47f20d10b39570def918a0ac68c305c9 (diff)
preparing to build tox from sources
Diffstat (limited to 'libs/libsodium/src/crypto_pwhash')
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-core.c549
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-core.h297
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.c305
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.h33
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx2.c239
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx512f.c244
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ref.c233
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ssse3.c238
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2.c277
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2.h305
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.c79
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.h8
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx2.h150
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx512f.h145
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ref.h40
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ssse3.h120
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2i.c290
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2id.c234
-rw-r--r--libs/libsodium/src/crypto_pwhash/crypto_pwhash.c211
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c263
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h98
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c375
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c95
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h45
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c285
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c108
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c400
27 files changed, 5666 insertions, 0 deletions
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.c
new file mode 100644
index 0000000000..b52b04d36d
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.c
@@ -0,0 +1,549 @@
+/*
+ * 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/>.
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+#include "crypto_generichash_blake2b.h"
+#include "private/common.h"
+#include "private/implementations.h"
+#include "runtime.h"
+#include "utils.h"
+
+#include "argon2-core.h"
+#include "blake2b-long.h"
+
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+#endif
+#ifndef MAP_NOCORE
+# define MAP_NOCORE 0
+#endif
+#ifndef MAP_POPULATE
+# define MAP_POPULATE 0
+#endif
+
+static fill_segment_fn fill_segment = fill_segment_ref;
+
+static void
+load_block(block *dst, const void *input)
+{
+ unsigned i;
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+ dst->v[i] = LOAD64_LE((const uint8_t *) input + i * sizeof(dst->v[i]));
+ }
+}
+
+static void
+store_block(void *output, const block *src)
+{
+ unsigned i;
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+ STORE64_LE((uint8_t *) output + i * sizeof(src->v[i]), src->v[i]);
+ }
+}
+
+/***************Memory allocators*****************/
+/* 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
+ */
+static int allocate_memory(block_region **memory, uint32_t m_cost);
+
+static int
+allocate_memory(block_region **region, uint32_t m_cost)
+{
+ void * base;
+ block *memory;
+ size_t memory_size;
+
+ if (region == NULL) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
+ }
+ memory_size = sizeof(block) * m_cost;
+ if (m_cost == 0 ||
+ memory_size / m_cost !=
+ sizeof(block)) { /*1. Check for multiplication overflow*/
+ return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
+ }
+ *region = (block_region *) malloc(
+ sizeof(block_region)); /*2. Try to allocate region*/
+ if (!*region) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
+ }
+ (*region)->base = (*region)->memory = NULL;
+
+#if defined(MAP_ANON) && defined(HAVE_MMAP)
+ if ((base = mmap(NULL, memory_size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE | MAP_POPULATE,
+ -1, 0)) == MAP_FAILED) {
+ base = NULL; /* LCOV_EXCL_LINE */
+ } /* LCOV_EXCL_LINE */
+ memcpy(&memory, &base, sizeof memory);
+#elif defined(HAVE_POSIX_MEMALIGN)
+ if ((errno = posix_memalign((void **) &base, 64, memory_size)) != 0) {
+ base = NULL;
+ }
+ memcpy(&memory, &base, sizeof memory);
+#else
+ memory = NULL;
+ if (memory_size + 63 < memory_size) {
+ base = NULL;
+ errno = ENOMEM;
+ } else if ((base = malloc(memory_size + 63)) != NULL) {
+ uint8_t *aligned = ((uint8_t *) base) + 63;
+ aligned -= (uintptr_t) aligned & 63;
+ memcpy(&memory, &aligned, sizeof memory);
+ }
+#endif
+ if (base == NULL) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
+ }
+ (*region)->base = base;
+ (*region)->memory = memory;
+ (*region)->size = memory_size;
+
+ return ARGON2_OK;
+}
+
+/*********Memory functions*/
+
+/* Clears memory
+ * @param instance pointer to the current instance
+ * @param clear_memory indicates if we clear the memory with zeros.
+ */
+static void clear_memory(argon2_instance_t *instance, int clear);
+
+static void
+clear_memory(argon2_instance_t *instance, int clear)
+{
+ /* LCOV_EXCL_START */
+ if (clear) {
+ if (instance->region != NULL) {
+ sodium_memzero(instance->region->memory,
+ sizeof(block) * instance->memory_blocks);
+ }
+ if (instance->pseudo_rands != NULL) {
+ sodium_memzero(instance->pseudo_rands,
+ sizeof(uint64_t) * instance->segment_length);
+ }
+ }
+ /* LCOV_EXCL_STOP */
+}
+
+/* Deallocates memory
+ * @param memory pointer to the blocks
+ */
+static void free_memory(block_region *memory);
+
+static void
+free_memory(block_region *region)
+{
+ if (region && region->base) {
+#if defined(MAP_ANON) && defined(HAVE_MMAP)
+ if (munmap(region->base, region->size)) {
+ return; /* LCOV_EXCL_LINE */
+ }
+#else
+ free(region->base);
+#endif
+ }
+ free(region);
+}
+
+void
+free_instance(argon2_instance_t *instance, int flags)
+{
+ /* Clear memory */
+ clear_memory(instance, flags & ARGON2_FLAG_CLEAR_MEMORY);
+
+ /* Deallocate the memory */
+ free(instance->pseudo_rands);
+ instance->pseudo_rands = NULL;
+ free_memory(instance->region);
+ instance->region = NULL;
+}
+
+void
+finalize(const argon2_context *context, argon2_instance_t *instance)
+{
+ if (context != NULL && instance != NULL) {
+ block blockhash;
+ uint32_t l;
+
+ copy_block(&blockhash,
+ instance->region->memory + instance->lane_length - 1);
+
+ /* XOR the last blocks */
+ for (l = 1; l < instance->lanes; ++l) {
+ uint32_t last_block_in_lane =
+ l * instance->lane_length + (instance->lane_length - 1);
+ xor_block(&blockhash,
+ instance->region->memory + last_block_in_lane);
+ }
+
+ /* Hash the result */
+ {
+ uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
+ store_block(blockhash_bytes, &blockhash);
+ blake2b_long(context->out, context->outlen, blockhash_bytes,
+ ARGON2_BLOCK_SIZE);
+ sodium_memzero(blockhash.v,
+ ARGON2_BLOCK_SIZE); /* clear blockhash */
+ sodium_memzero(blockhash_bytes,
+ ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */
+ }
+
+ free_instance(instance, context->flags);
+ }
+}
+
+void
+fill_memory_blocks(argon2_instance_t *instance, uint32_t pass)
+{
+ argon2_position_t position;
+ uint32_t l;
+ uint32_t s;
+
+ if (instance == NULL || instance->lanes == 0) {
+ return; /* LCOV_EXCL_LINE */
+ }
+
+ position.pass = pass;
+ for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
+ position.slice = (uint8_t) s;
+ for (l = 0; l < instance->lanes; ++l) {
+ position.lane = l;
+ position.index = 0;
+ fill_segment(instance, position);
+ }
+ }
+}
+
+int
+validate_inputs(const argon2_context *context)
+{
+ /* LCOV_EXCL_START */
+ if (NULL == context) {
+ return ARGON2_INCORRECT_PARAMETER;
+ }
+
+ if (NULL == context->out) {
+ return ARGON2_OUTPUT_PTR_NULL;
+ }
+
+ /* Validate output length */
+ if (ARGON2_MIN_OUTLEN > context->outlen) {
+ return ARGON2_OUTPUT_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_OUTLEN < context->outlen) {
+ return ARGON2_OUTPUT_TOO_LONG;
+ }
+
+ /* Validate password (required param) */
+ if (NULL == context->pwd) {
+ if (0 != context->pwdlen) {
+ return ARGON2_PWD_PTR_MISMATCH;
+ }
+ }
+
+ if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
+ return ARGON2_PWD_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
+ return ARGON2_PWD_TOO_LONG;
+ }
+
+ /* Validate salt (required param) */
+ if (NULL == context->salt) {
+ if (0 != context->saltlen) {
+ return ARGON2_SALT_PTR_MISMATCH;
+ }
+ }
+
+ if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
+ return ARGON2_SALT_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
+ return ARGON2_SALT_TOO_LONG;
+ }
+
+ /* Validate secret (optional param) */
+ if (NULL == context->secret) {
+ if (0 != context->secretlen) {
+ return ARGON2_SECRET_PTR_MISMATCH;
+ }
+ } else {
+ if (ARGON2_MIN_SECRET > context->secretlen) {
+ return ARGON2_SECRET_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_SECRET < context->secretlen) {
+ return ARGON2_SECRET_TOO_LONG;
+ }
+ }
+
+ /* Validate associated data (optional param) */
+ if (NULL == context->ad) {
+ if (0 != context->adlen) {
+ return ARGON2_AD_PTR_MISMATCH;
+ }
+ } else {
+ if (ARGON2_MIN_AD_LENGTH > context->adlen) {
+ return ARGON2_AD_TOO_SHORT;
+ }
+
+ 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 (ARGON2_MAX_MEMORY < context->m_cost) {
+ return ARGON2_MEMORY_TOO_MUCH;
+ }
+
+ 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;
+ }
+ /* LCOV_EXCL_STOP */
+
+ return ARGON2_OK;
+}
+
+void
+fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance)
+{
+ uint32_t l;
+ /* Make the first and second block in each lane as G(H0||i||0) or
+ G(H0||i||1) */
+ uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
+ for (l = 0; l < instance->lanes; ++l) {
+ STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
+ STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
+ blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
+ ARGON2_PREHASH_SEED_LENGTH);
+ load_block(&instance->region->memory[l * instance->lane_length + 0],
+ blockhash_bytes);
+
+ STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
+ blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
+ ARGON2_PREHASH_SEED_LENGTH);
+ load_block(&instance->region->memory[l * instance->lane_length + 1],
+ blockhash_bytes);
+ }
+ sodium_memzero(blockhash_bytes, ARGON2_BLOCK_SIZE);
+}
+
+void
+initial_hash(uint8_t *blockhash, argon2_context *context, argon2_type type)
+{
+ crypto_generichash_blake2b_state BlakeHash;
+ uint8_t value[4U /* sizeof(uint32_t) */];
+
+ if (NULL == context || NULL == blockhash) {
+ return; /* LCOV_EXCL_LINE */
+ }
+
+ crypto_generichash_blake2b_init(&BlakeHash, NULL, 0U,
+ ARGON2_PREHASH_DIGEST_LENGTH);
+
+ STORE32_LE(value, context->lanes);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, context->outlen);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, context->m_cost);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, context->t_cost);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, ARGON2_VERSION_NUMBER);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, (uint32_t) type);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, context->pwdlen);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ if (context->pwd != NULL) {
+ crypto_generichash_blake2b_update(
+ &BlakeHash, (const uint8_t *) context->pwd, context->pwdlen);
+
+ /* LCOV_EXCL_START */
+ if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
+ sodium_memzero(context->pwd, context->pwdlen);
+ context->pwdlen = 0;
+ }
+ /* LCOV_EXCL_STOP */
+ }
+
+ STORE32_LE(value, context->saltlen);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ if (context->salt != NULL) {
+ crypto_generichash_blake2b_update(
+ &BlakeHash, (const uint8_t *) context->salt, context->saltlen);
+ }
+
+ STORE32_LE(value, context->secretlen);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ /* LCOV_EXCL_START */
+ if (context->secret != NULL) {
+ crypto_generichash_blake2b_update(
+ &BlakeHash, (const uint8_t *) context->secret, context->secretlen);
+
+ if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
+ sodium_memzero(context->secret, context->secretlen);
+ context->secretlen = 0;
+ }
+ }
+ /* LCOV_EXCL_STOP */
+
+ STORE32_LE(value, context->adlen);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ /* LCOV_EXCL_START */
+ if (context->ad != NULL) {
+ crypto_generichash_blake2b_update(
+ &BlakeHash, (const uint8_t *) context->ad, context->adlen);
+ }
+ /* LCOV_EXCL_STOP */
+
+ crypto_generichash_blake2b_final(&BlakeHash, blockhash,
+ ARGON2_PREHASH_DIGEST_LENGTH);
+}
+
+int
+initialize(argon2_instance_t *instance, argon2_context *context)
+{
+ uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
+ int result = ARGON2_OK;
+
+ if (instance == NULL || context == NULL) {
+ return ARGON2_INCORRECT_PARAMETER;
+ }
+
+ /* 1. Memory allocation */
+
+ if ((instance->pseudo_rands = (uint64_t *)
+ malloc(sizeof(uint64_t) * instance->segment_length)) == NULL) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+
+ result = allocate_memory(&(instance->region), instance->memory_blocks);
+ if (ARGON2_OK != result) {
+ free_instance(instance, context->flags);
+ return result;
+ }
+
+ /* 2. Initial hashing */
+ /* H_0 + 8 extra bytes to produce the first blocks */
+ /* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
+ /* Hashing all inputs */
+ initial_hash(blockhash, context, instance->type);
+ /* Zeroing 8 extra bytes */
+ sodium_memzero(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
+ ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH);
+
+ /* 3. Creating first blocks, we always have at least two blocks in a slice
+ */
+ fill_first_blocks(blockhash, instance);
+ /* Clearing the hash */
+ sodium_memzero(blockhash, ARGON2_PREHASH_SEED_LENGTH);
+
+ return ARGON2_OK;
+}
+
+int
+argon2_pick_best_implementation(void)
+{
+/* LCOV_EXCL_START */
+#if defined(HAVE_AVX512FINTRIN_H) && defined(HAVE_AVX2INTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+ if (sodium_runtime_has_avx512f()) {
+ fill_segment = fill_segment_avx512f;
+ return 0;
+ }
+#endif
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_TMMINTRIN_H) && \
+ defined(HAVE_SMMINTRIN_H)
+ if (sodium_runtime_has_avx2()) {
+ fill_segment = fill_segment_avx2;
+ return 0;
+ }
+#endif
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+ if (sodium_runtime_has_ssse3()) {
+ fill_segment = fill_segment_ssse3;
+ return 0;
+ }
+#endif
+ fill_segment = fill_segment_ref;
+
+ return 0;
+ /* LCOV_EXCL_STOP */
+}
+
+int
+_crypto_pwhash_argon2_pick_best_implementation(void)
+{
+ return argon2_pick_best_implementation();
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.h b/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.h
new file mode 100644
index 0000000000..caab103891
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.h
@@ -0,0 +1,297 @@
+/*
+ * 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 <string.h>
+
+#include "argon2.h"
+
+/*************************Argon2 internal
+ * constants**************************************************/
+
+enum argon2_ctx_constants {
+ /* Version of the algorithm */
+ ARGON2_VERSION_NUMBER = 0x13,
+
+ /* Memory block size in bytes */
+ ARGON2_BLOCK_SIZE = 1024,
+ ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
+ ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
+ ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
+ ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64,
+
+ /* Number of pseudo-random values generated by one call to Blake in Argon2i
+ to
+ generate reference block positions */
+ ARGON2_ADDRESSES_IN_BLOCK = 128,
+
+ /* Pre-hashing digest length and its extension*/
+ ARGON2_PREHASH_DIGEST_LENGTH = 64,
+ ARGON2_PREHASH_SEED_LENGTH = 72
+};
+
+/*************************Argon2 internal data
+ * types**************************************************/
+
+/*
+ * Structure for the (1KB) memory block implemented as 128 64-bit words.
+ * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
+ * bounds checking).
+ */
+typedef struct block_ {
+ uint64_t v[ARGON2_QWORDS_IN_BLOCK];
+} block;
+
+typedef struct block_region_ {
+ void * base;
+ block *memory;
+ size_t size;
+} block_region;
+
+/*****************Functions that work with the block******************/
+
+/* Initialize each byte of the block with @in */
+static inline void
+init_block_value(block *b, uint8_t in)
+{
+ memset(b->v, in, sizeof(b->v));
+}
+
+/* Copy block @src to block @dst */
+static inline void
+copy_block(block *dst, const block *src)
+{
+ memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
+}
+
+/* XOR @src onto @dst bytewise */
+static inline void
+xor_block(block *dst, const block *src)
+{
+ int i;
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+ dst->v[i] ^= src->v[i];
+ }
+}
+
+/*
+ * 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_region *region; /* Memory region pointer */
+ uint64_t *pseudo_rands;
+ uint32_t passes; /* Number of passes */
+ uint32_t current_pass;
+ 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**************************************************/
+
+/*
+ * 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
+ */
+static uint32_t index_alpha(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint32_t pseudo_rand,
+ int same_lane)
+{
+ /*
+ * Pass 0:
+ * This lane : all already finished segments plus already constructed
+ * blocks in this segment
+ * Other lanes : all already finished segments
+ * Pass 1+:
+ * This lane : (SYNC_POINTS - 1) last segments plus already constructed
+ * blocks in this segment
+ * Other lanes : (SYNC_POINTS - 1) last segments
+ */
+ uint32_t reference_area_size;
+ uint64_t relative_position;
+ uint32_t start_position, absolute_position;
+
+ if (position->pass == 0) {
+ /* First pass */
+ if (position->slice == 0) {
+ /* First slice */
+ reference_area_size =
+ position->index - 1; /* all but the previous */
+ } else {
+ if (same_lane) {
+ /* The same lane => add current segment */
+ reference_area_size =
+ position->slice * instance->segment_length +
+ position->index - 1;
+ } else {
+ reference_area_size =
+ position->slice * instance->segment_length +
+ ((position->index == 0) ? (-1) : 0);
+ }
+ }
+ } else {
+ /* Second pass */
+ if (same_lane) {
+ reference_area_size = instance->lane_length -
+ instance->segment_length + position->index -
+ 1;
+ } else {
+ reference_area_size = instance->lane_length -
+ instance->segment_length +
+ ((position->index == 0) ? (-1) : 0);
+ }
+ }
+
+ /* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
+ * relative position */
+ relative_position = pseudo_rand;
+ relative_position = relative_position * relative_position >> 32;
+ relative_position = reference_area_size - 1 -
+ (reference_area_size * relative_position >> 32);
+
+ /* 1.2.5 Computing starting position */
+ start_position = 0;
+
+ if (position->pass != 0) {
+ start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
+ ? 0
+ : (position->slice + 1) * instance->segment_length;
+ }
+
+ /* 1.2.6. Computing absolute position */
+ absolute_position = (start_position + relative_position) %
+ instance->lane_length; /* absolute position */
+ return absolute_position;
+}
+
+/*
+ * 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);
+
+/*
+ * Deallocates memory. Used on error path.
+ */
+void free_instance(argon2_instance_t *instance, int flags);
+
+/*
+ * 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
+ */
+typedef void (*fill_segment_fn)(const argon2_instance_t *instance,
+ argon2_position_t position);
+int argon2_pick_best_implementation(void);
+void fill_segment_avx512f(const argon2_instance_t *instance,
+ argon2_position_t position);
+void fill_segment_avx2(const argon2_instance_t *instance,
+ argon2_position_t position);
+void fill_segment_ssse3(const argon2_instance_t *instance,
+ argon2_position_t position);
+void fill_segment_ref(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 Zero if successful, -1 if memory failed to allocate
+ */
+void fill_memory_blocks(argon2_instance_t *instance, uint32_t pass);
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.c
new file mode 100644
index 0000000000..a08acdda80
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.c
@@ -0,0 +1,305 @@
+#include "argon2-encoding.h"
+#include "argon2-core.h"
+#include "utils.h"
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Example code for a decoder and encoder of "hash strings", with Argon2
+ * parameters.
+ *
+ * The code was originally written by Thomas Pornin <pornin@bolet.org>,
+ * to whom comments and remarks may be sent. It is released under what
+ * should amount to Public Domain or its closest equivalent; the
+ * following mantra is supposed to incarnate that fact with all the
+ * proper legal rituals:
+ *
+ * ---------------------------------------------------------------------
+ * This file is provided under the terms of Creative Commons CC0 1.0
+ * Public Domain Dedication. To the extent possible under law, the
+ * author (Thomas Pornin) has waived all copyright and related or
+ * neighboring rights to this file. This work is published from: Canada.
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2015 Thomas Pornin
+ */
+
+/* ==================================================================== */
+
+/*
+ * Decode decimal integer from 'str'; the value is written in '*v'.
+ * Returned value is a pointer to the next non-decimal character in the
+ * string. If there is no digit at all, or the value encoding is not
+ * minimal (extra leading zeros), or the value does not fit in an
+ * 'unsigned long', then NULL is returned.
+ */
+static const char *
+decode_decimal(const char *str, unsigned long *v)
+{
+ const char *orig;
+ unsigned long acc;
+
+ acc = 0;
+ for (orig = str;; str++) {
+ int c;
+
+ c = *str;
+ if (c < '0' || c > '9') {
+ break;
+ }
+ c -= '0';
+ if (acc > (ULONG_MAX / 10)) {
+ return NULL;
+ }
+ acc *= 10;
+ if ((unsigned long) c > (ULONG_MAX - acc)) {
+ return NULL;
+ }
+ acc += (unsigned long) c;
+ }
+ if (str == orig || (*orig == '0' && str != (orig + 1))) {
+ return NULL;
+ }
+ *v = acc;
+ return str;
+}
+
+/* ==================================================================== */
+/*
+ * Code specific to Argon2.
+ *
+ * The code below applies the following format:
+ *
+ * $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
+ *
+ * where <T> is either '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 last two binary chunks (encoded in Base64) are, in that order,
+ * the salt and the output. Both are required. The binary salt length and the
+ * output length must be in the allowed ranges defined in argon2.h.
+ *
+ * The ctx struct must contain buffers large enough to hold the salt and pwd
+ * when it is fed into decode_string.
+ */
+
+/*
+ * Decode an Argon2i hash string into the provided structure 'ctx'.
+ * Returned value is ARGON2_OK on success.
+ */
+int
+decode_string(argon2_context *ctx, const char *str, argon2_type type)
+{
+/* Prefix checking */
+#define CC(prefix) \
+ do { \
+ size_t cc_len = strlen(prefix); \
+ if (strncmp(str, prefix, cc_len) != 0) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ str += cc_len; \
+ } while ((void) 0, 0)
+
+/* Optional prefix checking with supplied code */
+#define CC_opt(prefix, code) \
+ do { \
+ size_t cc_len = strlen(prefix); \
+ if (strncmp(str, prefix, cc_len) == 0) { \
+ str += cc_len; \
+ { \
+ code; \
+ } \
+ } \
+ } 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 ARGON2_DECODING_FAIL; \
+ } \
+ (x) = dec_x; \
+ } while ((void) 0, 0)
+
+/* Decoding prefix into uint32_t decimal */
+#define DECIMAL_U32(x) \
+ do { \
+ unsigned long dec_x; \
+ str = decode_decimal(str, &dec_x); \
+ if (str == NULL || dec_x > UINT32_MAX) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ (x) = (uint32_t)dec_x; \
+ } while ((void)0, 0)
+
+/* Decoding base64 into a binary buffer */
+#define BIN(buf, max_len, len) \
+ do { \
+ size_t bin_len = (max_len); \
+ const char *str_end; \
+ if (sodium_base642bin((buf), (max_len), str, strlen(str), NULL, \
+ &bin_len, &str_end, \
+ sodium_base64_VARIANT_ORIGINAL_NO_PADDING) != 0 || \
+ bin_len > UINT32_MAX) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ (len) = (uint32_t) bin_len; \
+ str = str_end; \
+ } while ((void) 0, 0)
+
+ size_t maxsaltlen = ctx->saltlen;
+ size_t maxoutlen = ctx->outlen;
+ int validation_result;
+ uint32_t version = 0;
+
+ ctx->saltlen = 0;
+ ctx->outlen = 0;
+
+ if (type == Argon2_id) {
+ CC("$argon2id");
+ } else if (type == Argon2_i) {
+ CC("$argon2i");
+ } else {
+ return ARGON2_INCORRECT_TYPE;
+ }
+ CC("$v=");
+ DECIMAL_U32(version);
+ if (version != ARGON2_VERSION_NUMBER) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+ CC("$m=");
+ DECIMAL_U32(ctx->m_cost);
+ if (ctx->m_cost > UINT32_MAX) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+ CC(",t=");
+ DECIMAL_U32(ctx->t_cost);
+ if (ctx->t_cost > UINT32_MAX) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+ CC(",p=");
+ DECIMAL_U32(ctx->lanes);
+ if (ctx->lanes > UINT32_MAX) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+ ctx->threads = ctx->lanes;
+
+ CC("$");
+ BIN(ctx->salt, maxsaltlen, ctx->saltlen);
+ CC("$");
+ BIN(ctx->out, maxoutlen, ctx->outlen);
+ validation_result = validate_inputs(ctx);
+ if (validation_result != ARGON2_OK) {
+ return validation_result;
+ }
+ if (*str == 0) {
+ return ARGON2_OK;
+ }
+ return ARGON2_DECODING_FAIL;
+
+#undef CC
+#undef CC_opt
+#undef DECIMAL
+#undef BIN
+}
+
+#define U32_STR_MAXSIZE 11U
+
+static void
+u32_to_string(char *str, uint32_t x)
+{
+ char tmp[U32_STR_MAXSIZE - 1U];
+ size_t i;
+
+ i = sizeof tmp;
+ do {
+ tmp[--i] = (x % (uint32_t) 10U) + '0';
+ x /= (uint32_t) 10U;
+ } while (x != 0U && i != 0U);
+ memcpy(str, &tmp[i], (sizeof tmp) - i);
+ str[(sizeof tmp) - i] = 0;
+}
+
+/*
+ * 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, ARGON2_OK 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 ARGON2_ENCODING_FAIL; \
+ } \
+ memcpy(dst, str, pp_len + 1); \
+ dst += pp_len; \
+ dst_len -= pp_len; \
+ } while ((void) 0, 0)
+
+#define SX(x) \
+ do { \
+ char tmp[U32_STR_MAXSIZE]; \
+ u32_to_string(tmp, x); \
+ SS(tmp); \
+ } while ((void) 0, 0)
+
+#define SB(buf, len) \
+ do { \
+ size_t sb_len; \
+ if (sodium_bin2base64(dst, dst_len, (buf), (len), \
+ sodium_base64_VARIANT_ORIGINAL_NO_PADDING) == NULL) { \
+ return ARGON2_ENCODING_FAIL; \
+ } \
+ sb_len = strlen(dst); \
+ dst += sb_len; \
+ dst_len -= sb_len; \
+ } while ((void) 0, 0)
+
+ int validation_result;
+
+ switch (type) {
+ case Argon2_id:
+ SS("$argon2id$v="); break;
+ case Argon2_i:
+ SS("$argon2i$v="); break;
+ default:
+ return ARGON2_ENCODING_FAIL;
+ }
+ validation_result = validate_inputs(ctx);
+ if (validation_result != ARGON2_OK) {
+ return validation_result;
+ }
+ SX(ARGON2_VERSION_NUMBER);
+ SS("$m=");
+ SX(ctx->m_cost);
+ SS(",t=");
+ SX(ctx->t_cost);
+ SS(",p=");
+ SX(ctx->lanes);
+
+ SS("$");
+ SB(ctx->salt, ctx->saltlen);
+
+ SS("$");
+ SB(ctx->out, ctx->outlen);
+ return ARGON2_OK;
+
+#undef SS
+#undef SX
+#undef SB
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.h b/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.h
new file mode 100644
index 0000000000..e929b31dc3
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.h
@@ -0,0 +1,33 @@
+#ifndef argon2_encoding_H
+#define argon2_encoding_H
+
+#include "argon2.h"
+
+/*
+ * 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 0.
+ *
+ * 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.
+ */
+int decode_string(argon2_context *ctx, const char *str, argon2_type type);
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx2.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx2.c
new file mode 100644
index 0000000000..8acb42ca4d
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx2.c
@@ -0,0 +1,239 @@
+/*
+ * 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/>.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# pragma GCC target("sse4.1")
+# pragma GCC target("avx2")
+# endif
+
+# ifdef _MSC_VER
+# include <intrin.h> /* for _mm_set_epi64x */
+# endif
+#include <emmintrin.h>
+#include <immintrin.h>
+#include <smmintrin.h>
+#include <tmmintrin.h>
+
+# include "blamka-round-avx2.h"
+
+static void
+fill_block(__m256i *state, const uint8_t *ref_block, uint8_t *next_block)
+{
+ __m256i block_XY[ARGON2_HWORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ block_XY[i] = state[i] = _mm256_xor_si256(
+ state[i], _mm256_loadu_si256((__m256i const *) (&ref_block[32 * i])));
+ }
+
+ for (i = 0; i < 4; ++i) {
+ BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5],
+ state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 4; ++i) {
+ BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i],
+ state[16 + i], state[20 + i], state[24 + i], state[28 + i]);
+ }
+
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ state[i] = _mm256_xor_si256(state[i], block_XY[i]);
+ _mm256_storeu_si256((__m256i *) (&next_block[32 * i]), state[i]);
+ }
+}
+
+static void
+fill_block_with_xor(__m256i *state, const uint8_t *ref_block,
+ uint8_t *next_block)
+{
+ __m256i block_XY[ARGON2_HWORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ state[i] = _mm256_xor_si256(
+ state[i], _mm256_loadu_si256((__m256i const *) (&ref_block[32 * i])));
+ block_XY[i] = _mm256_xor_si256(
+ state[i], _mm256_loadu_si256((__m256i const *) (&next_block[32 * i])));
+ }
+
+ for (i = 0; i < 4; ++i) {
+ BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5],
+ state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 4; ++i) {
+ BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i],
+ state[16 + i], state[20 + i], state[24 + i], state[28 + i]);
+ }
+
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ state[i] = _mm256_xor_si256(state[i], block_XY[i]);
+ _mm256_storeu_si256((__m256i *) (&next_block[32 * i]), state[i]);
+ }
+}
+
+static void
+generate_addresses(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint64_t *pseudo_rands)
+{
+ block address_block, input_block, tmp_block;
+ uint32_t i;
+
+ init_block_value(&address_block, 0);
+ init_block_value(&input_block, 0);
+
+ if (instance != NULL && position != NULL) {
+ input_block.v[0] = position->pass;
+ input_block.v[1] = position->lane;
+ input_block.v[2] = position->slice;
+ input_block.v[3] = instance->memory_blocks;
+ input_block.v[4] = instance->passes;
+ input_block.v[5] = instance->type;
+
+ for (i = 0; i < instance->segment_length; ++i) {
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ /* Temporary zero-initialized blocks */
+ __m256i zero_block[ARGON2_HWORDS_IN_BLOCK];
+ __m256i zero2_block[ARGON2_HWORDS_IN_BLOCK];
+
+ memset(zero_block, 0, sizeof(zero_block));
+ memset(zero2_block, 0, sizeof(zero2_block));
+ init_block_value(&address_block, 0);
+ init_block_value(&tmp_block, 0);
+ /* Increasing index counter */
+ input_block.v[6]++;
+ /* First iteration of G */
+ fill_block_with_xor(zero_block, (uint8_t *) &input_block.v,
+ (uint8_t *) &tmp_block.v);
+ /* Second iteration of G */
+ fill_block_with_xor(zero2_block, (uint8_t *) &tmp_block.v,
+ (uint8_t *) &address_block.v);
+ }
+
+ pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
+ }
+ }
+}
+
+void
+fill_segment_avx2(const argon2_instance_t *instance,
+ argon2_position_t position)
+{
+ block *ref_block = NULL, *curr_block = NULL;
+ uint64_t pseudo_rand, ref_index, ref_lane;
+ uint32_t prev_offset, curr_offset;
+ uint32_t starting_index, i;
+ __m256i state[ARGON2_HWORDS_IN_BLOCK];
+ int data_independent_addressing = 1;
+
+ /* Pseudo-random values that determine the reference block position */
+ uint64_t *pseudo_rands = NULL;
+
+ if (instance == NULL) {
+ return;
+ }
+
+ if (instance->type == Argon2_id &&
+ (position.pass != 0 || position.slice >= ARGON2_SYNC_POINTS / 2)) {
+ data_independent_addressing = 0;
+ }
+
+ pseudo_rands = instance->pseudo_rands;
+
+ if (data_independent_addressing) {
+ generate_addresses(instance, &position, pseudo_rands);
+ }
+
+ starting_index = 0;
+
+ if ((0 == position.pass) && (0 == position.slice)) {
+ starting_index = 2; /* we have already generated the first two blocks */
+ }
+
+ /* Offset of the current block */
+ curr_offset = position.lane * instance->lane_length +
+ position.slice * instance->segment_length + starting_index;
+
+ if (0 == curr_offset % instance->lane_length) {
+ /* Last block in this lane */
+ prev_offset = curr_offset + instance->lane_length - 1;
+ } else {
+ /* Previous block */
+ prev_offset = curr_offset - 1;
+ }
+
+ memcpy(state, ((instance->region->memory + prev_offset)->v),
+ ARGON2_BLOCK_SIZE);
+
+ for (i = starting_index; i < instance->segment_length;
+ ++i, ++curr_offset, ++prev_offset) {
+ /*1.1 Rotating prev_offset if needed */
+ if (curr_offset % instance->lane_length == 1) {
+ prev_offset = curr_offset - 1;
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ if (data_independent_addressing) {
+#pragma warning(push)
+#pragma warning(disable : 6385)
+ pseudo_rand = pseudo_rands[i];
+#pragma warning(pop)
+ } else {
+ pseudo_rand = instance->region->memory[prev_offset].v[0];
+ }
+
+ /* 1.2.2 Computing the lane of the reference block */
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ ref_lane = position.lane;
+ }
+
+ /* 1.2.3 Computing the number of possible reference block within the
+ * lane.
+ */
+ position.index = i;
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+ ref_lane == position.lane);
+
+ /* 2 Creating a new block */
+ ref_block = instance->region->memory +
+ instance->lane_length * ref_lane + ref_index;
+ curr_block = instance->region->memory + curr_offset;
+ if (position.pass != 0) {
+ fill_block_with_xor(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ } else {
+ fill_block(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ }
+ }
+}
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx512f.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx512f.c
new file mode 100644
index 0000000000..1f1ec8b3b4
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx512f.c
@@ -0,0 +1,244 @@
+/*
+ * 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/>.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_AVX512FINTRIN_H) && defined(HAVE_AVX2INTRIN_H) && \
+ defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# pragma GCC target("sse4.1")
+# pragma GCC target("avx2")
+# pragma GCC target("avx512f")
+# endif
+
+# ifdef _MSC_VER
+# include <intrin.h> /* for _mm_set_epi64x */
+# endif
+#include <emmintrin.h>
+#include <immintrin.h>
+#include <smmintrin.h>
+#include <tmmintrin.h>
+
+# include "blamka-round-avx512f.h"
+
+static void
+fill_block(__m512i *state, const uint8_t *ref_block, uint8_t *next_block)
+{
+ __m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ block_XY[i] = state[i] = _mm512_xor_si512(
+ state[i], _mm512_loadu_si512((__m512i const *) (&ref_block[64 * i])));
+ }
+
+ for (i = 0; i < 2; ++i) {
+ BLAKE2_ROUND_1(
+ state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3],
+ state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ BLAKE2_ROUND_2(
+ state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i],
+ state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]);
+ }
+
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ state[i] = _mm512_xor_si512(state[i], block_XY[i]);
+ _mm512_storeu_si512((__m512i *) (&next_block[64 * i]), state[i]);
+ }
+}
+
+static void
+fill_block_with_xor(__m512i *state, const uint8_t *ref_block,
+ uint8_t *next_block)
+{
+ __m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ state[i] = _mm512_xor_si512(
+ state[i], _mm512_loadu_si512((__m512i const *) (&ref_block[64 * i])));
+ block_XY[i] = _mm512_xor_si512(
+ state[i], _mm512_loadu_si512((__m512i const *) (&next_block[64 * i])));
+ }
+
+ for (i = 0; i < 2; ++i) {
+ BLAKE2_ROUND_1(
+ state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3],
+ state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ BLAKE2_ROUND_2(
+ state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i],
+ state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]);
+ }
+
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ state[i] = _mm512_xor_si512(state[i], block_XY[i]);
+ _mm512_storeu_si512((__m512i *) (&next_block[64 * i]), state[i]);
+ }
+}
+
+static void
+generate_addresses(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint64_t *pseudo_rands)
+{
+ block address_block, input_block, tmp_block;
+ uint32_t i;
+
+ init_block_value(&address_block, 0);
+ init_block_value(&input_block, 0);
+
+ if (instance != NULL && position != NULL) {
+ input_block.v[0] = position->pass;
+ input_block.v[1] = position->lane;
+ input_block.v[2] = position->slice;
+ input_block.v[3] = instance->memory_blocks;
+ input_block.v[4] = instance->passes;
+ input_block.v[5] = instance->type;
+
+ for (i = 0; i < instance->segment_length; ++i) {
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ /* Temporary zero-initialized blocks */
+ __m512i zero_block[ARGON2_512BIT_WORDS_IN_BLOCK];
+ __m512i zero2_block[ARGON2_512BIT_WORDS_IN_BLOCK];
+
+ memset(zero_block, 0, sizeof(zero_block));
+ memset(zero2_block, 0, sizeof(zero2_block));
+ init_block_value(&address_block, 0);
+ init_block_value(&tmp_block, 0);
+ /* Increasing index counter */
+ input_block.v[6]++;
+ /* First iteration of G */
+ fill_block_with_xor(zero_block, (uint8_t *) &input_block.v,
+ (uint8_t *) &tmp_block.v);
+ /* Second iteration of G */
+ fill_block_with_xor(zero2_block, (uint8_t *) &tmp_block.v,
+ (uint8_t *) &address_block.v);
+ }
+
+ pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
+ }
+ }
+}
+
+void
+fill_segment_avx512f(const argon2_instance_t *instance,
+ argon2_position_t position)
+{
+ block *ref_block = NULL, *curr_block = NULL;
+ uint64_t pseudo_rand, ref_index, ref_lane;
+ uint32_t prev_offset, curr_offset;
+ uint32_t starting_index, i;
+ __m512i state[ARGON2_512BIT_WORDS_IN_BLOCK];
+ int data_independent_addressing = 1;
+
+ /* Pseudo-random values that determine the reference block position */
+ uint64_t *pseudo_rands = NULL;
+
+ if (instance == NULL) {
+ return;
+ }
+
+ if (instance->type == Argon2_id &&
+ (position.pass != 0 || position.slice >= ARGON2_SYNC_POINTS / 2)) {
+ data_independent_addressing = 0;
+ }
+
+ pseudo_rands = instance->pseudo_rands;
+
+ if (data_independent_addressing) {
+ generate_addresses(instance, &position, pseudo_rands);
+ }
+
+ starting_index = 0;
+
+ if ((0 == position.pass) && (0 == position.slice)) {
+ starting_index = 2; /* we have already generated the first two blocks */
+ }
+
+ /* Offset of the current block */
+ curr_offset = position.lane * instance->lane_length +
+ position.slice * instance->segment_length + starting_index;
+
+ if (0 == curr_offset % instance->lane_length) {
+ /* Last block in this lane */
+ prev_offset = curr_offset + instance->lane_length - 1;
+ } else {
+ /* Previous block */
+ prev_offset = curr_offset - 1;
+ }
+
+ memcpy(state, ((instance->region->memory + prev_offset)->v),
+ ARGON2_BLOCK_SIZE);
+
+ for (i = starting_index; i < instance->segment_length;
+ ++i, ++curr_offset, ++prev_offset) {
+ /*1.1 Rotating prev_offset if needed */
+ if (curr_offset % instance->lane_length == 1) {
+ prev_offset = curr_offset - 1;
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ if (data_independent_addressing) {
+#pragma warning(push)
+#pragma warning(disable : 6385)
+ pseudo_rand = pseudo_rands[i];
+#pragma warning(pop)
+ } else {
+ pseudo_rand = instance->region->memory[prev_offset].v[0];
+ }
+
+ /* 1.2.2 Computing the lane of the reference block */
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ ref_lane = position.lane;
+ }
+
+ /* 1.2.3 Computing the number of possible reference block within the
+ * lane.
+ */
+ position.index = i;
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+ ref_lane == position.lane);
+
+ /* 2 Creating a new block */
+ ref_block = instance->region->memory +
+ instance->lane_length * ref_lane + ref_index;
+ curr_block = instance->region->memory + curr_offset;
+ if (position.pass != 0) {
+ fill_block_with_xor(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ } else {
+ fill_block(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ }
+ }
+}
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ref.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ref.c
new file mode 100644
index 0000000000..75e8d8f5ea
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ref.c
@@ -0,0 +1,233 @@
+/*
+ * 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/>.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2.h"
+#include "blamka-round-ref.h"
+#include "private/common.h"
+
+static void
+fill_block(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);
+ /* 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);
+}
+
+static 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) {
+ 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);
+}
+
+/*
+ * 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
+ */
+static void
+generate_addresses(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint64_t *pseudo_rands)
+{
+ block zero_block, input_block, address_block, tmp_block;
+ uint32_t i;
+
+ init_block_value(&zero_block, 0);
+ init_block_value(&input_block, 0);
+
+ if (instance != NULL && position != NULL) {
+ input_block.v[0] = position->pass;
+ input_block.v[1] = position->lane;
+ input_block.v[2] = position->slice;
+ input_block.v[3] = instance->memory_blocks;
+ input_block.v[4] = instance->passes;
+ input_block.v[5] = instance->type;
+
+ for (i = 0; i < instance->segment_length; ++i) {
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ input_block.v[6]++;
+ 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];
+ }
+ }
+}
+
+void
+fill_segment_ref(const argon2_instance_t *instance, argon2_position_t position)
+{
+ block *ref_block = NULL, *curr_block = NULL;
+ /* Pseudo-random values that determine the reference block position */
+ uint64_t *pseudo_rands = NULL;
+ uint64_t pseudo_rand, ref_index, ref_lane;
+ uint32_t prev_offset, curr_offset;
+ uint32_t starting_index;
+ uint32_t i;
+ int data_independent_addressing = 1;
+
+ if (instance == NULL) {
+ return;
+ }
+
+ if (instance->type == Argon2_id &&
+ (position.pass != 0 || position.slice >= ARGON2_SYNC_POINTS / 2)) {
+ data_independent_addressing = 0;
+ }
+
+ pseudo_rands = instance->pseudo_rands;
+
+ if (data_independent_addressing) {
+ generate_addresses(instance, &position, pseudo_rands);
+ }
+
+ starting_index = 0;
+
+ if ((0 == position.pass) && (0 == position.slice)) {
+ starting_index = 2; /* we have already generated the first two blocks */
+ }
+
+ /* Offset of the current block */
+ curr_offset = position.lane * instance->lane_length +
+ position.slice * instance->segment_length + starting_index;
+
+ if (0 == curr_offset % instance->lane_length) {
+ /* Last block in this lane */
+ prev_offset = curr_offset + instance->lane_length - 1;
+ } else {
+ /* Previous block */
+ prev_offset = curr_offset - 1;
+ }
+
+ for (i = starting_index; i < instance->segment_length;
+ ++i, ++curr_offset, ++prev_offset) {
+ /*1.1 Rotating prev_offset if needed */
+ if (curr_offset % instance->lane_length == 1) {
+ prev_offset = curr_offset - 1;
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ if (data_independent_addressing) {
+#pragma warning(push)
+#pragma warning(disable : 6385)
+ pseudo_rand = pseudo_rands[i];
+#pragma warning(pop)
+ } else {
+ pseudo_rand = instance->region->memory[prev_offset].v[0];
+ }
+
+ /* 1.2.2 Computing the lane of the reference block */
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ ref_lane = position.lane;
+ }
+
+ /* 1.2.3 Computing the number of possible reference block within the
+ * lane.
+ */
+ position.index = i;
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+ ref_lane == position.lane);
+
+ /* 2 Creating a new block */
+ ref_block = instance->region->memory +
+ instance->lane_length * ref_lane + ref_index;
+ curr_block = instance->region->memory + curr_offset;
+ if (position.pass != 0) {
+ fill_block_with_xor(instance->region->memory + prev_offset,
+ ref_block, curr_block);
+ } else {
+ fill_block(instance->region->memory + prev_offset, ref_block,
+ curr_block);
+ }
+ }
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ssse3.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ssse3.c
new file mode 100644
index 0000000000..796c445560
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ssse3.c
@@ -0,0 +1,238 @@
+/*
+ * 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/>.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# endif
+
+# ifdef _MSC_VER
+# include <intrin.h> /* for _mm_set_epi64x */
+# endif
+# include <emmintrin.h>
+# include <tmmintrin.h>
+
+# include "blamka-round-ssse3.h"
+
+static void
+fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block)
+{
+ __m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ block_XY[i] = state[i] = _mm_xor_si128(
+ state[i], _mm_loadu_si128((__m128i const *) (&ref_block[16 * i])));
+ }
+
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
+ state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
+ state[8 * i + 6], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
+ state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
+ state[8 * 6 + i], state[8 * 7 + i]);
+ }
+
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ state[i] = _mm_xor_si128(state[i], block_XY[i]);
+ _mm_storeu_si128((__m128i *) (&next_block[16 * i]), state[i]);
+ }
+}
+
+static void
+fill_block_with_xor(__m128i *state, const uint8_t *ref_block,
+ uint8_t *next_block)
+{
+ __m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ state[i] = _mm_xor_si128(
+ state[i], _mm_loadu_si128((__m128i const *) (&ref_block[16 * i])));
+ block_XY[i] = _mm_xor_si128(
+ state[i], _mm_loadu_si128((__m128i const *) (&next_block[16 * i])));
+ }
+
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
+ state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
+ state[8 * i + 6], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
+ state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
+ state[8 * 6 + i], state[8 * 7 + i]);
+ }
+
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ state[i] = _mm_xor_si128(state[i], block_XY[i]);
+ _mm_storeu_si128((__m128i *) (&next_block[16 * i]), state[i]);
+ }
+}
+
+static void
+generate_addresses(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint64_t *pseudo_rands)
+{
+ block address_block, input_block, tmp_block;
+ uint32_t i;
+
+ init_block_value(&address_block, 0);
+ init_block_value(&input_block, 0);
+
+ if (instance != NULL && position != NULL) {
+ input_block.v[0] = position->pass;
+ input_block.v[1] = position->lane;
+ input_block.v[2] = position->slice;
+ input_block.v[3] = instance->memory_blocks;
+ input_block.v[4] = instance->passes;
+ input_block.v[5] = instance->type;
+
+ for (i = 0; i < instance->segment_length; ++i) {
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ /* Temporary zero-initialized blocks */
+ __m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
+ __m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
+
+ memset(zero_block, 0, sizeof(zero_block));
+ memset(zero2_block, 0, sizeof(zero2_block));
+ init_block_value(&address_block, 0);
+ init_block_value(&tmp_block, 0);
+ /* Increasing index counter */
+ input_block.v[6]++;
+ /* First iteration of G */
+ fill_block_with_xor(zero_block, (uint8_t *) &input_block.v,
+ (uint8_t *) &tmp_block.v);
+ /* Second iteration of G */
+ fill_block_with_xor(zero2_block, (uint8_t *) &tmp_block.v,
+ (uint8_t *) &address_block.v);
+ }
+
+ pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
+ }
+ }
+}
+
+void
+fill_segment_ssse3(const argon2_instance_t *instance,
+ argon2_position_t position)
+{
+ block *ref_block = NULL, *curr_block = NULL;
+ uint64_t pseudo_rand, ref_index, ref_lane;
+ uint32_t prev_offset, curr_offset;
+ uint32_t starting_index, i;
+ __m128i state[ARGON2_OWORDS_IN_BLOCK];
+ int data_independent_addressing = 1;
+
+ /* Pseudo-random values that determine the reference block position */
+ uint64_t *pseudo_rands = NULL;
+
+ if (instance == NULL) {
+ return;
+ }
+
+ if (instance->type == Argon2_id &&
+ (position.pass != 0 || position.slice >= ARGON2_SYNC_POINTS / 2)) {
+ data_independent_addressing = 0;
+ }
+
+ pseudo_rands = instance->pseudo_rands;
+
+ if (data_independent_addressing) {
+ generate_addresses(instance, &position, pseudo_rands);
+ }
+
+ starting_index = 0;
+
+ if ((0 == position.pass) && (0 == position.slice)) {
+ starting_index = 2; /* we have already generated the first two blocks */
+ }
+
+ /* Offset of the current block */
+ curr_offset = position.lane * instance->lane_length +
+ position.slice * instance->segment_length + starting_index;
+
+ if (0 == curr_offset % instance->lane_length) {
+ /* Last block in this lane */
+ prev_offset = curr_offset + instance->lane_length - 1;
+ } else {
+ /* Previous block */
+ prev_offset = curr_offset - 1;
+ }
+
+ memcpy(state, ((instance->region->memory + prev_offset)->v),
+ ARGON2_BLOCK_SIZE);
+
+ for (i = starting_index; i < instance->segment_length;
+ ++i, ++curr_offset, ++prev_offset) {
+ /*1.1 Rotating prev_offset if needed */
+ if (curr_offset % instance->lane_length == 1) {
+ prev_offset = curr_offset - 1;
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ if (data_independent_addressing) {
+#pragma warning(push)
+#pragma warning(disable : 6385)
+ pseudo_rand = pseudo_rands[i];
+#pragma warning(pop)
+ } else {
+ pseudo_rand = instance->region->memory[prev_offset].v[0];
+ }
+
+ /* 1.2.2 Computing the lane of the reference block */
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ ref_lane = position.lane;
+ }
+
+ /* 1.2.3 Computing the number of possible reference block within the
+ * lane.
+ */
+ position.index = i;
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+ ref_lane == position.lane);
+
+ /* 2 Creating a new block */
+ ref_block = instance->region->memory +
+ instance->lane_length * ref_lane + ref_index;
+ curr_block = instance->region->memory + curr_offset;
+ if (position.pass != 0) {
+ fill_block_with_xor(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ } else {
+ fill_block(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ }
+ }
+}
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2.c
new file mode 100644
index 0000000000..ac1628c991
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2.c
@@ -0,0 +1,277 @@
+/*
+ * 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/>.
+ */
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.h"
+
+#include "argon2-core.h"
+#include "argon2-encoding.h"
+#include "argon2.h"
+
+int
+argon2_ctx(argon2_context *context, argon2_type type)
+{
+ /* 1. Validate all inputs */
+ int result = validate_inputs(context);
+ uint32_t memory_blocks, segment_length;
+ uint32_t pass;
+ argon2_instance_t instance;
+
+ if (ARGON2_OK != result) {
+ return result;
+ }
+
+ if (type != Argon2_id && type != Argon2_i) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+
+ /* 2. Align memory size */
+ /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
+ memory_blocks = context->m_cost;
+
+ if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
+ memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
+ }
+
+ segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
+ /* Ensure that all segments have equal length */
+ memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
+
+ instance.region = NULL;
+ instance.passes = context->t_cost;
+ instance.current_pass = ~ 0U;
+ instance.memory_blocks = memory_blocks;
+ instance.segment_length = segment_length;
+ instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
+ instance.lanes = context->lanes;
+ instance.threads = context->threads;
+ instance.type = type;
+
+ /* 3. Initialization: Hashing inputs, allocating memory, filling first
+ * blocks
+ */
+ result = initialize(&instance, context);
+
+ if (ARGON2_OK != result) {
+ return result;
+ }
+
+ /* 4. Filling memory */
+ for (pass = 0; pass < instance.passes; pass++) {
+ fill_memory_blocks(&instance, pass);
+ }
+
+ /* 5. Finalization */
+ finalize(context, &instance);
+
+ 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)
+{
+ argon2_context context;
+ int result;
+ uint8_t *out;
+
+ if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
+ return ARGON2_PWD_TOO_LONG;
+ }
+
+ if (hashlen > ARGON2_MAX_OUTLEN) {
+ return ARGON2_OUTPUT_TOO_LONG;
+ }
+
+ if (saltlen > ARGON2_MAX_SALT_LENGTH) {
+ return ARGON2_SALT_TOO_LONG;
+ }
+
+ out = (uint8_t *) malloc(hashlen);
+ if (!out) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+
+ context.out = (uint8_t *) out;
+ context.outlen = (uint32_t) hashlen;
+ context.pwd = (uint8_t *) pwd;
+ context.pwdlen = (uint32_t) pwdlen;
+ context.salt = (uint8_t *) salt;
+ context.saltlen = (uint32_t) saltlen;
+ context.secret = NULL;
+ context.secretlen = 0;
+ context.ad = NULL;
+ context.adlen = 0;
+ context.t_cost = t_cost;
+ context.m_cost = m_cost;
+ context.lanes = parallelism;
+ context.threads = parallelism;
+ context.flags = ARGON2_DEFAULT_FLAGS;
+
+ result = argon2_ctx(&context, type);
+
+ if (result != ARGON2_OK) {
+ sodium_memzero(out, hashlen);
+ free(out);
+ return result;
+ }
+
+ /* if raw hash requested, write it */
+ if (hash) {
+ memcpy(hash, out, hashlen);
+ }
+
+ /* if encoding requested, write it */
+ if (encoded && encodedlen) {
+ if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
+ sodium_memzero(out, hashlen);
+ sodium_memzero(encoded, encodedlen);
+ free(out);
+ return ARGON2_ENCODING_FAIL;
+ }
+ }
+
+ sodium_memzero(out, hashlen);
+ free(out);
+
+ return ARGON2_OK;
+}
+
+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)
+{
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ NULL, hashlen, encoded, encodedlen, Argon2_i);
+}
+
+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)
+{
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ hash, hashlen, NULL, 0, Argon2_i);
+}
+
+int
+argon2id_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)
+{
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ NULL, hashlen, encoded, encodedlen, Argon2_id);
+}
+
+int
+argon2id_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)
+{
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ hash, hashlen, NULL, 0, Argon2_id);
+}
+
+int
+argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
+ argon2_type type)
+{
+ argon2_context ctx;
+ uint8_t *out;
+ int decode_result;
+ int ret;
+ size_t encoded_len;
+
+ memset(&ctx, 0, sizeof ctx);
+
+ ctx.pwd = NULL;
+ ctx.pwdlen = 0;
+ ctx.secret = NULL;
+ ctx.secretlen = 0;
+
+ /* max values, to be updated in decode_string */
+ encoded_len = strlen(encoded);
+ if (encoded_len > UINT32_MAX) {
+ return ARGON2_DECODING_LENGTH_FAIL;
+ }
+ ctx.adlen = (uint32_t) encoded_len;
+ ctx.saltlen = (uint32_t) encoded_len;
+ ctx.outlen = (uint32_t) encoded_len;
+
+ ctx.ad = (uint8_t *) malloc(ctx.adlen);
+ ctx.salt = (uint8_t *) malloc(ctx.saltlen);
+ ctx.out = (uint8_t *) malloc(ctx.outlen);
+ if (!ctx.out || !ctx.salt || !ctx.ad) {
+ free(ctx.ad);
+ free(ctx.salt);
+ free(ctx.out);
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+ out = (uint8_t *) malloc(ctx.outlen);
+ if (!out) {
+ free(ctx.ad);
+ free(ctx.salt);
+ free(ctx.out);
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+
+ decode_result = decode_string(&ctx, encoded, type);
+ if (decode_result != ARGON2_OK) {
+ free(ctx.ad);
+ free(ctx.salt);
+ free(ctx.out);
+ free(out);
+ 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);
+
+ free(ctx.ad);
+ free(ctx.salt);
+
+ if (ret != ARGON2_OK || sodium_memcmp(out, ctx.out, ctx.outlen) != 0) {
+ ret = ARGON2_VERIFY_MISMATCH;
+ }
+ free(out);
+ free(ctx.out);
+
+ return ret;
+}
+
+int
+argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen)
+{
+ return argon2_verify(encoded, pwd, pwdlen, Argon2_i);
+}
+
+int
+argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen)
+{
+ return argon2_verify(encoded, pwd, pwdlen, Argon2_id);
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2.h b/libs/libsodium/src/crypto_pwhash/argon2/argon2.h
new file mode 100644
index 0000000000..85ca4dd373
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2.h
@@ -0,0 +1,305 @@
+/*
+ * 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 <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * 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(16)
+#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 half the addressing space, 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 (UINT32_C(0))
+
+/* 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;
+
+/* 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 Argon2 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 flags; /* array of bool options */
+} argon2_context;
+
+/* Argon2 primitive type */
+typedef enum Argon2_type { Argon2_i = 1, Argon2_id = 2 } argon2_type;
+
+/*
+ * 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
+ */
+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
+ */
+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 Argon2id, 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
+ */
+int argon2id_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
+ * @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
+ * @param hashlen Desired length of the hash in bytes
+ * @pre Different parallelism levels will give different results
+ * @pre Returns ARGON2_OK if successful
+ */
+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);
+
+/**
+ * Hashes a password with Argon2id, producing a raw 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
+ * @param hashlen Desired length of the hash in bytes
+ * @pre Different parallelism levels will give different results
+ * @pre Returns ARGON2_OK if successful
+ */
+int argon2id_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 */
+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);
+
+/**
+ * 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
+ */
+int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen);
+
+/**
+ * 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
+ */
+int argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen);
+
+/* generic function underlying the above ones */
+int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
+ argon2_type type);
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.c b/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.c
new file mode 100644
index 0000000000..f0364aca87
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.c
@@ -0,0 +1,79 @@
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crypto_generichash_blake2b.h"
+#include "private/common.h"
+#include "utils.h"
+
+#include "blake2b-long.h"
+
+int
+blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen)
+{
+ uint8_t *out = (uint8_t *) pout;
+ crypto_generichash_blake2b_state blake_state;
+ uint8_t outlen_bytes[4 /* sizeof(uint32_t) */] = { 0 };
+ int ret = -1;
+
+ if (outlen > UINT32_MAX) {
+ goto fail; /* LCOV_EXCL_LINE */
+ }
+
+ /* Ensure little-endian byte order! */
+ STORE32_LE(outlen_bytes, (uint32_t) outlen);
+
+#define TRY(statement) \
+ do { \
+ ret = statement; \
+ if (ret < 0) { \
+ goto fail; \
+ } \
+ } while ((void) 0, 0)
+
+ if (outlen <= crypto_generichash_blake2b_BYTES_MAX) {
+ TRY(crypto_generichash_blake2b_init(&blake_state, NULL, 0U, outlen));
+ TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes,
+ sizeof(outlen_bytes)));
+ TRY(crypto_generichash_blake2b_update(
+ &blake_state, (const unsigned char *) in, inlen));
+ TRY(crypto_generichash_blake2b_final(&blake_state, out, outlen));
+ } else {
+ uint32_t toproduce;
+ uint8_t out_buffer[crypto_generichash_blake2b_BYTES_MAX];
+ uint8_t in_buffer[crypto_generichash_blake2b_BYTES_MAX];
+ TRY(crypto_generichash_blake2b_init(
+ &blake_state, NULL, 0U, crypto_generichash_blake2b_BYTES_MAX));
+ TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes,
+ sizeof(outlen_bytes)));
+ TRY(crypto_generichash_blake2b_update(
+ &blake_state, (const unsigned char *) in, inlen));
+ TRY(crypto_generichash_blake2b_final(
+ &blake_state, out_buffer, crypto_generichash_blake2b_BYTES_MAX));
+ memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2);
+ out += crypto_generichash_blake2b_BYTES_MAX / 2;
+ toproduce =
+ (uint32_t) outlen - crypto_generichash_blake2b_BYTES_MAX / 2;
+
+ while (toproduce > crypto_generichash_blake2b_BYTES_MAX) {
+ memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX);
+ TRY(crypto_generichash_blake2b(
+ out_buffer, crypto_generichash_blake2b_BYTES_MAX, in_buffer,
+ crypto_generichash_blake2b_BYTES_MAX, NULL, 0U));
+ memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2);
+ out += crypto_generichash_blake2b_BYTES_MAX / 2;
+ toproduce -= crypto_generichash_blake2b_BYTES_MAX / 2;
+ }
+
+ memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX);
+ TRY(crypto_generichash_blake2b(out_buffer, toproduce, in_buffer,
+ crypto_generichash_blake2b_BYTES_MAX,
+ NULL, 0U));
+ memcpy(out, out_buffer, toproduce);
+ }
+fail:
+ sodium_memzero(&blake_state, sizeof(blake_state));
+ return ret;
+#undef TRY
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.h b/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.h
new file mode 100644
index 0000000000..3d6d775521
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.h
@@ -0,0 +1,8 @@
+#ifndef blake2b_long_H
+#define blake2b_long_H
+
+#include <stddef.h>
+
+int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen);
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx2.h b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx2.h
new file mode 100644
index 0000000000..f3dfa0f506
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx2.h
@@ -0,0 +1,150 @@
+#ifndef blamka_round_avx2_H
+#define blamka_round_avx2_H
+
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#define rotr32(x) _mm256_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1))
+#define rotr24(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
+#define rotr16(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
+#define rotr63(x) _mm256_xor_si256(_mm256_srli_epi64((x), 63), _mm256_add_epi64((x), (x)))
+
+#define G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i ml = _mm256_mul_epu32(A0, B0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
+ D0 = _mm256_xor_si256(D0, A0); \
+ D0 = rotr32(D0); \
+ \
+ ml = _mm256_mul_epu32(C0, D0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
+ \
+ B0 = _mm256_xor_si256(B0, C0); \
+ B0 = rotr24(B0); \
+ \
+ ml = _mm256_mul_epu32(A1, B1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
+ D1 = _mm256_xor_si256(D1, A1); \
+ D1 = rotr32(D1); \
+ \
+ ml = _mm256_mul_epu32(C1, D1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
+ \
+ B1 = _mm256_xor_si256(B1, C1); \
+ B1 = rotr24(B1); \
+ } while((void)0, 0);
+
+#define G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i ml = _mm256_mul_epu32(A0, B0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
+ D0 = _mm256_xor_si256(D0, A0); \
+ D0 = rotr16(D0); \
+ \
+ ml = _mm256_mul_epu32(C0, D0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
+ B0 = _mm256_xor_si256(B0, C0); \
+ B0 = rotr63(B0); \
+ \
+ ml = _mm256_mul_epu32(A1, B1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
+ D1 = _mm256_xor_si256(D1, A1); \
+ D1 = rotr16(D1); \
+ \
+ ml = _mm256_mul_epu32(C1, D1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
+ B1 = _mm256_xor_si256(B1, C1); \
+ B1 = rotr63(B1); \
+ } while((void)0, 0);
+
+#define DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ \
+ B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ } while((void)0, 0);
+
+#define DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
+ __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
+ B1 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ B0 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ \
+ tmp1 = C0; \
+ C0 = C1; \
+ C1 = tmp1; \
+ \
+ tmp1 = _mm256_blend_epi32(D0, D1, 0xCC); \
+ tmp2 = _mm256_blend_epi32(D0, D1, 0x33); \
+ D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ } while(0);
+
+#define UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ \
+ B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ } while((void)0, 0);
+
+#define UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
+ __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
+ B0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ B1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ \
+ tmp1 = C0; \
+ C0 = C1; \
+ C1 = tmp1; \
+ \
+ tmp1 = _mm256_blend_epi32(D0, D1, 0x33); \
+ tmp2 = _mm256_blend_epi32(D0, D1, 0xCC); \
+ D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ } while((void)0, 0);
+
+#define BLAKE2_ROUND_1(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do{ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ } while((void)0, 0);
+
+#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do{ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ } while((void)0, 0);
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx512f.h b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx512f.h
new file mode 100644
index 0000000000..9a822402d8
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx512f.h
@@ -0,0 +1,145 @@
+#ifndef blamka_round_avx512f_H
+#define blamka_round_avx512f_H
+
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#define ror64(x, n) _mm512_ror_epi64((x), (n))
+
+static inline __m512i
+muladd(__m512i x, __m512i y)
+{
+ __m512i z = _mm512_mul_epu32(x, y);
+
+ return _mm512_add_epi64(_mm512_add_epi64(x, y), _mm512_add_epi64(z, z));
+}
+
+#define G1_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = muladd(A0, B0); \
+ A1 = muladd(A1, B1); \
+ \
+ D0 = _mm512_xor_si512(D0, A0); \
+ D1 = _mm512_xor_si512(D1, A1); \
+ \
+ D0 = ror64(D0, 32); \
+ D1 = ror64(D1, 32); \
+ \
+ C0 = muladd(C0, D0); \
+ C1 = muladd(C1, D1); \
+ \
+ B0 = _mm512_xor_si512(B0, C0); \
+ B1 = _mm512_xor_si512(B1, C1); \
+ \
+ B0 = ror64(B0, 24); \
+ B1 = ror64(B1, 24); \
+ } while ((void)0, 0)
+
+#define G2_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = muladd(A0, B0); \
+ A1 = muladd(A1, B1); \
+ \
+ D0 = _mm512_xor_si512(D0, A0); \
+ D1 = _mm512_xor_si512(D1, A1); \
+ \
+ D0 = ror64(D0, 16); \
+ D1 = ror64(D1, 16); \
+ \
+ C0 = muladd(C0, D0); \
+ C1 = muladd(C1, D1); \
+ \
+ B0 = _mm512_xor_si512(B0, C0); \
+ B1 = _mm512_xor_si512(B1, C1); \
+ \
+ B0 = ror64(B0, 63); \
+ B1 = ror64(B1, 63); \
+ } while ((void)0, 0)
+
+#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ \
+ C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+ \
+ D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ } while ((void)0, 0)
+
+#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ \
+ C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+ \
+ D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ } while ((void)0, 0)
+
+#define BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ G1_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ G1_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ } while ((void)0, 0)
+
+#define SWAP_HALVES(A0, A1) \
+ do { \
+ __m512i t0, t1; \
+ t0 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(1, 0, 1, 0)); \
+ t1 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(3, 2, 3, 2)); \
+ A0 = t0; \
+ A1 = t1; \
+ } while((void)0, 0)
+
+#define SWAP_QUARTERS(A0, A1) \
+ do { \
+ SWAP_HALVES(A0, A1); \
+ A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
+ A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
+ } while((void)0, 0)
+
+#define UNSWAP_QUARTERS(A0, A1) \
+ do { \
+ A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
+ A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
+ SWAP_HALVES(A0, A1); \
+ } while((void)0, 0)
+
+#define BLAKE2_ROUND_1(A0, C0, B0, D0, A1, C1, B1, D1) \
+ do { \
+ SWAP_HALVES(A0, B0); \
+ SWAP_HALVES(C0, D0); \
+ SWAP_HALVES(A1, B1); \
+ SWAP_HALVES(C1, D1); \
+ BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
+ SWAP_HALVES(A0, B0); \
+ SWAP_HALVES(C0, D0); \
+ SWAP_HALVES(A1, B1); \
+ SWAP_HALVES(C1, D1); \
+ } while ((void)0, 0)
+
+#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ SWAP_QUARTERS(A0, A1); \
+ SWAP_QUARTERS(B0, B1); \
+ SWAP_QUARTERS(C0, C1); \
+ SWAP_QUARTERS(D0, D1); \
+ BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
+ UNSWAP_QUARTERS(A0, A1); \
+ UNSWAP_QUARTERS(B0, B1); \
+ UNSWAP_QUARTERS(C0, C1); \
+ UNSWAP_QUARTERS(D0, D1); \
+ } while ((void)0, 0)
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ref.h b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ref.h
new file mode 100644
index 0000000000..7a2c6eb20e
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ref.h
@@ -0,0 +1,40 @@
+#ifndef blamka_round_ref_H
+#define blamka_round_ref_H
+
+#include "private/common.h"
+
+/*designed by the Lyra PHC team */
+static 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
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ssse3.h b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ssse3.h
new file mode 100644
index 0000000000..98a47b93f8
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ssse3.h
@@ -0,0 +1,120 @@
+#ifndef blamka_round_ssse3_H
+#define blamka_round_ssse3_H
+
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#define r16 \
+ (_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
+#define r24 \
+ (_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
+#define _mm_roti_epi64(x, c) \
+ (-(c) == 32) \
+ ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
+ : (-(c) == 24) \
+ ? _mm_shuffle_epi8((x), r24) \
+ : (-(c) == 16) \
+ ? _mm_shuffle_epi8((x), r16) \
+ : (-(c) == 63) \
+ ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+ _mm_add_epi64((x), (x))) \
+ : _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+ _mm_slli_epi64((x), 64 - (-(c))))
+
+static inline __m128i
+fBlaMka(__m128i x, __m128i y)
+{
+ const __m128i z = _mm_mul_epu32(x, y);
+ return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
+}
+
+#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = fBlaMka(A0, B0); \
+ A1 = fBlaMka(A1, B1); \
+ \
+ D0 = _mm_xor_si128(D0, A0); \
+ D1 = _mm_xor_si128(D1, A1); \
+ \
+ D0 = _mm_roti_epi64(D0, -32); \
+ D1 = _mm_roti_epi64(D1, -32); \
+ \
+ C0 = fBlaMka(C0, D0); \
+ C1 = fBlaMka(C1, D1); \
+ \
+ B0 = _mm_xor_si128(B0, C0); \
+ B1 = _mm_xor_si128(B1, C1); \
+ \
+ B0 = _mm_roti_epi64(B0, -24); \
+ B1 = _mm_roti_epi64(B1, -24); \
+ } while ((void) 0, 0)
+
+#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = fBlaMka(A0, B0); \
+ A1 = fBlaMka(A1, B1); \
+ \
+ D0 = _mm_xor_si128(D0, A0); \
+ D1 = _mm_xor_si128(D1, A1); \
+ \
+ D0 = _mm_roti_epi64(D0, -16); \
+ D1 = _mm_roti_epi64(D1, -16); \
+ \
+ C0 = fBlaMka(C0, D0); \
+ C1 = fBlaMka(C1, D1); \
+ \
+ B0 = _mm_xor_si128(B0, C0); \
+ B1 = _mm_xor_si128(B1, C1); \
+ \
+ B0 = _mm_roti_epi64(B0, -63); \
+ B1 = _mm_roti_epi64(B1, -63); \
+ } while ((void) 0, 0)
+
+#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ __m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
+ __m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
+ B0 = t0; \
+ B1 = t1; \
+ \
+ t0 = C0; \
+ C0 = C1; \
+ C1 = t0; \
+ \
+ t0 = _mm_alignr_epi8(D1, D0, 8); \
+ t1 = _mm_alignr_epi8(D0, D1, 8); \
+ D0 = t1; \
+ D1 = t0; \
+ } while ((void) 0, 0)
+
+#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ __m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
+ __m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
+ B0 = t0; \
+ B1 = t1; \
+ \
+ t0 = C0; \
+ C0 = C1; \
+ C1 = t0; \
+ \
+ t0 = _mm_alignr_epi8(D0, D1, 8); \
+ t1 = _mm_alignr_epi8(D1, D0, 8); \
+ D0 = t1; \
+ D1 = t0; \
+ } while ((void) 0, 0)
+
+#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ G1(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ G1(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ } while ((void) 0, 0)
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2i.c b/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2i.c
new file mode 100644
index 0000000000..0515bd6135
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2i.c
@@ -0,0 +1,290 @@
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2-encoding.h"
+#include "argon2.h"
+#include "crypto_pwhash.h"
+#include "crypto_pwhash_argon2i.h"
+#include "crypto_pwhash_argon2id.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#define STR_HASHBYTES 32U
+
+int
+crypto_pwhash_argon2i_alg_argon2i13(void)
+{
+ return crypto_pwhash_argon2i_ALG_ARGON2I13;
+}
+
+size_t
+crypto_pwhash_argon2i_bytes_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MIN >= ARGON2_MIN_OUTLEN);
+ return crypto_pwhash_argon2i_BYTES_MIN;
+}
+
+size_t
+crypto_pwhash_argon2i_bytes_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MAX <= ARGON2_MAX_OUTLEN);
+ return crypto_pwhash_argon2i_BYTES_MAX;
+}
+
+size_t
+crypto_pwhash_argon2i_passwd_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH);
+ return crypto_pwhash_argon2i_PASSWD_MIN;
+}
+
+size_t
+crypto_pwhash_argon2i_passwd_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH);
+ return crypto_pwhash_argon2i_PASSWD_MAX;
+}
+
+size_t
+crypto_pwhash_argon2i_saltbytes(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES >= ARGON2_MIN_SALT_LENGTH);
+ COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES <= ARGON2_MAX_SALT_LENGTH);
+ return crypto_pwhash_argon2i_SALTBYTES;
+}
+
+size_t
+crypto_pwhash_argon2i_strbytes(void)
+{
+ return crypto_pwhash_argon2i_STRBYTES;
+}
+
+const char*
+crypto_pwhash_argon2i_strprefix(void)
+{
+ return crypto_pwhash_argon2i_STRPREFIX;
+}
+
+size_t
+crypto_pwhash_argon2i_opslimit_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MIN >= ARGON2_MIN_TIME);
+ return crypto_pwhash_argon2i_OPSLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_argon2i_opslimit_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MAX <= ARGON2_MAX_TIME);
+ return crypto_pwhash_argon2i_OPSLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_argon2i_memlimit_min(void)
+{
+ COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY);
+ return crypto_pwhash_argon2i_MEMLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_argon2i_memlimit_max(void)
+{
+ COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY);
+ return crypto_pwhash_argon2i_MEMLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_argon2i_opslimit_interactive(void)
+{
+ return crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_argon2i_memlimit_interactive(void)
+{
+ return crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_argon2i_opslimit_moderate(void)
+{
+ return crypto_pwhash_argon2i_OPSLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_argon2i_memlimit_moderate(void)
+{
+ return crypto_pwhash_argon2i_MEMLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_argon2i_opslimit_sensitive(void)
+{
+ return crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE;
+}
+
+size_t
+crypto_pwhash_argon2i_memlimit_sensitive(void)
+{
+ return crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE;
+}
+
+int
+crypto_pwhash_argon2i(unsigned char *const out, unsigned long long outlen,
+ const char *const passwd, unsigned long long passwdlen,
+ const unsigned char *const salt,
+ unsigned long long opslimit, size_t memlimit, int alg)
+{
+ memset(out, 0, outlen);
+ if (outlen > crypto_pwhash_argon2i_BYTES_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (outlen < crypto_pwhash_argon2i_BYTES_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX ||
+ opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX ||
+ memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN ||
+ opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN ||
+ memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ switch (alg) {
+ case crypto_pwhash_argon2i_ALG_ARGON2I13:
+ if (argon2i_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
+ (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
+ (size_t) crypto_pwhash_argon2i_SALTBYTES, out,
+ (size_t) outlen) != ARGON2_OK) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+int
+crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
+ const char *const passwd,
+ unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+{
+ unsigned char salt[crypto_pwhash_argon2i_SALTBYTES];
+
+ memset(out, 0, crypto_pwhash_argon2i_STRBYTES);
+ if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX ||
+ opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX ||
+ memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN ||
+ opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN ||
+ memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ randombytes_buf(salt, sizeof salt);
+ if (argon2i_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
+ (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
+ sizeof salt, STR_HASHBYTES, out,
+ crypto_pwhash_argon2i_STRBYTES) != ARGON2_OK) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+}
+
+int
+crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES],
+ const char *const passwd,
+ unsigned long long passwdlen)
+{
+ int verify_ret;
+
+ if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ /* LCOV_EXCL_START */
+ if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ /* LCOV_EXCL_STOP */
+
+ verify_ret = argon2i_verify(str, passwd, (size_t) passwdlen);
+ if (verify_ret == ARGON2_OK) {
+ return 0;
+ }
+ if (verify_ret == ARGON2_VERIFY_MISMATCH) {
+ errno = EINVAL;
+ }
+ return -1;
+}
+
+static int
+_needs_rehash(const char *str, unsigned long long opslimit, size_t memlimit,
+ argon2_type type)
+{
+ unsigned char *fodder;
+ argon2_context ctx;
+ size_t fodder_len;
+ int ret = -1;
+
+ fodder_len = strlen(str);
+ memlimit /= 1024U;
+ if (opslimit > UINT32_MAX || memlimit > UINT32_MAX ||
+ fodder_len >= crypto_pwhash_STRBYTES) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(&ctx, 0, sizeof ctx);
+ if ((fodder = (unsigned char *) calloc(fodder_len, 1U)) == NULL) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ ctx.out = ctx.pwd = ctx.salt = fodder;
+ ctx.outlen = ctx.pwdlen = ctx.saltlen = (uint32_t) fodder_len;
+ ctx.ad = ctx.secret = NULL;
+ ctx.adlen = ctx.secretlen = 0U;
+ if (decode_string(&ctx, str, type) != 0) {
+ errno = EINVAL;
+ ret = -1;
+ } else if (ctx.t_cost != (uint32_t) opslimit ||
+ ctx.m_cost != (uint32_t) memlimit) {
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ free(fodder);
+
+ return ret;
+}
+
+int
+crypto_pwhash_argon2i_str_needs_rehash(const char str[crypto_pwhash_argon2i_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+{
+ return _needs_rehash(str, opslimit, memlimit, Argon2_i);
+}
+
+int
+crypto_pwhash_argon2id_str_needs_rehash(const char str[crypto_pwhash_argon2id_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+{
+ return _needs_rehash(str, opslimit, memlimit, Argon2_id);
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2id.c b/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2id.c
new file mode 100644
index 0000000000..99d3e219bf
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2id.c
@@ -0,0 +1,234 @@
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2.h"
+#include "crypto_pwhash_argon2id.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#define STR_HASHBYTES 32U
+
+int
+crypto_pwhash_argon2id_alg_argon2id13(void)
+{
+ return crypto_pwhash_argon2id_ALG_ARGON2ID13;
+}
+
+size_t
+crypto_pwhash_argon2id_bytes_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MIN >= ARGON2_MIN_OUTLEN);
+ return crypto_pwhash_argon2id_BYTES_MIN;
+}
+
+size_t
+crypto_pwhash_argon2id_bytes_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MAX <= ARGON2_MAX_OUTLEN);
+ return crypto_pwhash_argon2id_BYTES_MAX;
+}
+
+size_t
+crypto_pwhash_argon2id_passwd_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH);
+ return crypto_pwhash_argon2id_PASSWD_MIN;
+}
+
+size_t
+crypto_pwhash_argon2id_passwd_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH);
+ return crypto_pwhash_argon2id_PASSWD_MAX;
+}
+
+size_t
+crypto_pwhash_argon2id_saltbytes(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES >= ARGON2_MIN_SALT_LENGTH);
+ COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES <= ARGON2_MAX_SALT_LENGTH);
+ return crypto_pwhash_argon2id_SALTBYTES;
+}
+
+size_t
+crypto_pwhash_argon2id_strbytes(void)
+{
+ return crypto_pwhash_argon2id_STRBYTES;
+}
+
+const char*
+crypto_pwhash_argon2id_strprefix(void)
+{
+ return crypto_pwhash_argon2id_STRPREFIX;
+}
+
+size_t
+crypto_pwhash_argon2id_opslimit_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MIN >= ARGON2_MIN_TIME);
+ return crypto_pwhash_argon2id_OPSLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_argon2id_opslimit_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MAX <= ARGON2_MAX_TIME);
+ return crypto_pwhash_argon2id_OPSLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_argon2id_memlimit_min(void)
+{
+ COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY);
+ return crypto_pwhash_argon2id_MEMLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_argon2id_memlimit_max(void)
+{
+ COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY);
+ return crypto_pwhash_argon2id_MEMLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_argon2id_opslimit_interactive(void)
+{
+ return crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_argon2id_memlimit_interactive(void)
+{
+ return crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_argon2id_opslimit_moderate(void)
+{
+ return crypto_pwhash_argon2id_OPSLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_argon2id_memlimit_moderate(void)
+{
+ return crypto_pwhash_argon2id_MEMLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_argon2id_opslimit_sensitive(void)
+{
+ return crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE;
+}
+
+size_t
+crypto_pwhash_argon2id_memlimit_sensitive(void)
+{
+ return crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE;
+}
+
+int
+crypto_pwhash_argon2id(unsigned char *const out, unsigned long long outlen,
+ const char *const passwd, unsigned long long passwdlen,
+ const unsigned char *const salt,
+ unsigned long long opslimit, size_t memlimit, int alg)
+{
+ memset(out, 0, outlen);
+ if (outlen > crypto_pwhash_argon2id_BYTES_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (outlen < crypto_pwhash_argon2id_BYTES_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
+ opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
+ memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
+ opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
+ memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ switch (alg) {
+ case crypto_pwhash_argon2id_ALG_ARGON2ID13:
+ if (argon2id_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
+ (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
+ (size_t) crypto_pwhash_argon2id_SALTBYTES, out,
+ (size_t) outlen) != ARGON2_OK) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+int
+crypto_pwhash_argon2id_str(char out[crypto_pwhash_argon2id_STRBYTES],
+ const char *const passwd,
+ unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+{
+ unsigned char salt[crypto_pwhash_argon2id_SALTBYTES];
+
+ memset(out, 0, crypto_pwhash_argon2id_STRBYTES);
+ if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
+ opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
+ memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
+ opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
+ memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ randombytes_buf(salt, sizeof salt);
+ if (argon2id_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
+ (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
+ sizeof salt, STR_HASHBYTES, out,
+ crypto_pwhash_argon2id_STRBYTES) != ARGON2_OK) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+}
+
+int
+crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRBYTES],
+ const char *const passwd,
+ unsigned long long passwdlen)
+{
+ int verify_ret;
+
+ if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ /* LCOV_EXCL_START */
+ if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ /* LCOV_EXCL_STOP */
+
+ verify_ret = argon2id_verify(str, passwd, (size_t) passwdlen);
+ if (verify_ret == ARGON2_OK) {
+ return 0;
+ }
+ if (verify_ret == ARGON2_VERIFY_MISMATCH) {
+ errno = EINVAL;
+ }
+ return -1;
+}
diff --git a/libs/libsodium/src/crypto_pwhash/crypto_pwhash.c b/libs/libsodium/src/crypto_pwhash/crypto_pwhash.c
new file mode 100644
index 0000000000..8168f96216
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/crypto_pwhash.c
@@ -0,0 +1,211 @@
+
+#include <errno.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_pwhash.h"
+
+int
+crypto_pwhash_alg_argon2i13(void)
+{
+ return crypto_pwhash_ALG_ARGON2I13;
+}
+
+int
+crypto_pwhash_alg_argon2id13(void)
+{
+ return crypto_pwhash_ALG_ARGON2ID13;
+}
+
+int
+crypto_pwhash_alg_default(void)
+{
+ return crypto_pwhash_ALG_DEFAULT;
+}
+
+size_t
+crypto_pwhash_bytes_min(void)
+{
+ return crypto_pwhash_BYTES_MIN;
+}
+
+size_t
+crypto_pwhash_bytes_max(void)
+{
+ return crypto_pwhash_BYTES_MAX;
+}
+
+size_t
+crypto_pwhash_passwd_min(void)
+{
+ return crypto_pwhash_PASSWD_MIN;
+}
+
+size_t
+crypto_pwhash_passwd_max(void)
+{
+ return crypto_pwhash_PASSWD_MAX;
+}
+
+size_t
+crypto_pwhash_saltbytes(void)
+{
+ return crypto_pwhash_SALTBYTES;
+}
+
+size_t
+crypto_pwhash_strbytes(void)
+{
+ return crypto_pwhash_STRBYTES;
+}
+
+const char *
+crypto_pwhash_strprefix(void)
+{
+ return crypto_pwhash_STRPREFIX;
+}
+
+size_t
+crypto_pwhash_opslimit_min(void)
+{
+ return crypto_pwhash_OPSLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_opslimit_max(void)
+{
+ return crypto_pwhash_OPSLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_memlimit_min(void)
+{
+ return crypto_pwhash_MEMLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_memlimit_max(void)
+{
+ return crypto_pwhash_MEMLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_opslimit_interactive(void)
+{
+ return crypto_pwhash_OPSLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_memlimit_interactive(void)
+{
+ return crypto_pwhash_MEMLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_opslimit_moderate(void)
+{
+ return crypto_pwhash_OPSLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_memlimit_moderate(void)
+{
+ return crypto_pwhash_MEMLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_opslimit_sensitive(void)
+{
+ return crypto_pwhash_OPSLIMIT_SENSITIVE;
+}
+
+size_t
+crypto_pwhash_memlimit_sensitive(void)
+{
+ return crypto_pwhash_MEMLIMIT_SENSITIVE;
+}
+
+int
+crypto_pwhash(unsigned char * const out, unsigned long long outlen,
+ const char * const passwd, unsigned long long passwdlen,
+ const unsigned char * const salt,
+ unsigned long long opslimit, size_t memlimit, int alg)
+{
+ switch (alg) {
+ case crypto_pwhash_ALG_ARGON2I13:
+ return crypto_pwhash_argon2i(out, outlen, passwd, passwdlen, salt,
+ opslimit, memlimit, alg);
+ case crypto_pwhash_ALG_ARGON2ID13:
+ return crypto_pwhash_argon2id(out, outlen, passwd, passwdlen, salt,
+ opslimit, memlimit, alg);
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+int
+crypto_pwhash_str(char out[crypto_pwhash_STRBYTES],
+ const char * const passwd, unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+{
+ return crypto_pwhash_argon2id_str(out, passwd, passwdlen,
+ opslimit, memlimit);
+}
+
+int
+crypto_pwhash_str_alg(char out[crypto_pwhash_STRBYTES],
+ const char * const passwd, unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit, int alg)
+{
+ switch (alg) {
+ case crypto_pwhash_ALG_ARGON2I13:
+ return crypto_pwhash_argon2i_str(out, passwd, passwdlen,
+ opslimit, memlimit);
+ case crypto_pwhash_ALG_ARGON2ID13:
+ return crypto_pwhash_argon2id_str(out, passwd, passwdlen,
+ opslimit, memlimit);
+ }
+ sodium_misuse();
+ /* NOTREACHED */
+}
+
+int
+crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen)
+{
+ if (strncmp(str, crypto_pwhash_argon2id_STRPREFIX,
+ sizeof crypto_pwhash_argon2id_STRPREFIX - 1) == 0) {
+ return crypto_pwhash_argon2id_str_verify(str, passwd, passwdlen);
+ }
+ if (strncmp(str, crypto_pwhash_argon2i_STRPREFIX,
+ sizeof crypto_pwhash_argon2i_STRPREFIX - 1) == 0) {
+ return crypto_pwhash_argon2i_str_verify(str, passwd, passwdlen);
+ }
+ errno = EINVAL;
+
+ return -1;
+}
+
+int
+crypto_pwhash_str_needs_rehash(const char str[crypto_pwhash_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+{
+ if (strncmp(str, crypto_pwhash_argon2id_STRPREFIX,
+ sizeof crypto_pwhash_argon2id_STRPREFIX - 1) == 0) {
+ return crypto_pwhash_argon2id_str_needs_rehash(str, opslimit, memlimit);
+ }
+ if (strncmp(str, crypto_pwhash_argon2i_STRPREFIX,
+ sizeof crypto_pwhash_argon2i_STRPREFIX - 1) == 0) {
+ return crypto_pwhash_argon2i_str_needs_rehash(str, opslimit, memlimit);
+ }
+ errno = EINVAL;
+
+ return -1;
+}
+
+const char *
+crypto_pwhash_primitive(void) {
+ return crypto_pwhash_PRIMITIVE;
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c
new file mode 100644
index 0000000000..e15e12b294
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c
@@ -0,0 +1,263 @@
+/*-
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_pwhash_scryptsalsa208sha256.h"
+#include "crypto_scrypt.h"
+#include "private/common.h"
+#include "runtime.h"
+#include "utils.h"
+
+static const char *const itoa64 =
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static uint8_t *
+encode64_uint32(uint8_t *dst, size_t dstlen, uint32_t src, uint32_t srcbits)
+{
+ uint32_t bit;
+
+ for (bit = 0; bit < srcbits; bit += 6) {
+ if (dstlen < 1) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ *dst++ = itoa64[src & 0x3f];
+ dstlen--;
+ src >>= 6;
+ }
+ return dst;
+}
+
+static uint8_t *
+encode64(uint8_t *dst, size_t dstlen, const uint8_t *src, size_t srclen)
+{
+ size_t i;
+
+ for (i = 0; i < srclen;) {
+ uint8_t *dnext;
+ uint32_t value = 0, bits = 0;
+
+ do {
+ value |= (uint32_t) src[i++] << bits;
+ bits += 8;
+ } while (bits < 24 && i < srclen);
+
+ dnext = encode64_uint32(dst, dstlen, value, bits);
+ if (!dnext) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ dstlen -= dnext - dst;
+ dst = dnext;
+ }
+ return dst;
+}
+
+static int
+decode64_one(uint32_t *dst, uint8_t src)
+{
+ const char *ptr = strchr(itoa64, src);
+
+ if (ptr) {
+ *dst = (uint32_t)(ptr - itoa64);
+ return 0;
+ }
+ *dst = 0;
+
+ return -1;
+}
+
+static const uint8_t *
+decode64_uint32(uint32_t *dst, uint32_t dstbits, const uint8_t *src)
+{
+ uint32_t bit;
+ uint32_t value;
+
+ value = 0;
+ for (bit = 0; bit < dstbits; bit += 6) {
+ uint32_t one;
+ if (decode64_one(&one, *src)) {
+ *dst = 0;
+ return NULL;
+ }
+ src++;
+ value |= one << bit;
+ }
+ *dst = value;
+
+ return src;
+}
+
+const uint8_t *
+escrypt_parse_setting(const uint8_t *setting,
+ uint32_t *N_log2_p, uint32_t *r_p, uint32_t *p_p)
+{
+ const uint8_t *src;
+
+ if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$') {
+ return NULL;
+ }
+ src = setting + 3;
+
+ if (decode64_one(N_log2_p, *src)) {
+ return NULL;
+ }
+ src++;
+
+ src = decode64_uint32(r_p, 30, src);
+ if (!src) {
+ return NULL;
+ }
+
+ src = decode64_uint32(p_p, 30, src);
+ if (!src) {
+ return NULL;
+ }
+ return src;
+}
+
+uint8_t *
+escrypt_r(escrypt_local_t *local, const uint8_t *passwd, size_t passwdlen,
+ const uint8_t *setting, uint8_t *buf, size_t buflen)
+{
+ uint8_t hash[crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES];
+ escrypt_kdf_t escrypt_kdf;
+ const uint8_t *src;
+ const uint8_t *salt;
+ uint8_t *dst;
+ size_t prefixlen;
+ size_t saltlen;
+ size_t need;
+ uint64_t N;
+ uint32_t N_log2;
+ uint32_t r;
+ uint32_t p;
+
+ src = escrypt_parse_setting(setting, &N_log2, &r, &p);
+ if (!src) {
+ return NULL;
+ }
+ N = (uint64_t) 1 << N_log2;
+ prefixlen = src - setting;
+
+ salt = src;
+ src = (uint8_t *) strrchr((char *) salt, '$');
+ if (src) {
+ saltlen = src - salt;
+ } else {
+ saltlen = strlen((char *) salt);
+ }
+ need = prefixlen + saltlen + 1 +
+ crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1;
+ if (need > buflen || need < saltlen) {
+ return NULL;
+ }
+#ifdef HAVE_EMMINTRIN_H
+ escrypt_kdf =
+ sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
+#else
+ escrypt_kdf = escrypt_kdf_nosse;
+#endif
+ if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen, N, r, p, hash,
+ sizeof(hash))) {
+ return NULL;
+ }
+ dst = buf;
+ memcpy(dst, setting, prefixlen + saltlen);
+ dst += prefixlen + saltlen;
+ *dst++ = '$';
+
+ dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash));
+ sodium_memzero(hash, sizeof hash);
+ if (!dst || dst >= buf + buflen) {
+ return NULL; /* Can't happen LCOV_EXCL_LINE */
+ }
+ *dst = 0; /* NUL termination */
+
+ return buf;
+}
+
+uint8_t *
+escrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p, const uint8_t *src,
+ size_t srclen, uint8_t *buf, size_t buflen)
+{
+ uint8_t *dst;
+ size_t prefixlen =
+ (sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */);
+ size_t saltlen = BYTES2CHARS(srclen);
+ size_t need;
+
+ need = prefixlen + saltlen + 1;
+ if (need > buflen || need < saltlen || saltlen < srclen) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ if (N_log2 > 63 || ((uint64_t) r * (uint64_t) p >= (1U << 30))) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ dst = buf;
+ *dst++ = '$';
+ *dst++ = '7';
+ *dst++ = '$';
+
+ *dst++ = itoa64[N_log2];
+
+ dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
+ if (!dst) {
+ return NULL; /* Can't happen LCOV_EXCL_LINE */
+ }
+ dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
+ if (!dst) {
+ return NULL; /* Can't happen LCOV_EXCL_LINE */
+ }
+ dst = encode64(dst, buflen - (dst - buf), src, srclen);
+ if (!dst || dst >= buf + buflen) {
+ return NULL; /* Can't happen LCOV_EXCL_LINE */
+ }
+ *dst = 0; /* NUL termination */
+
+ return buf;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t *passwd, size_t passwdlen,
+ const uint8_t *salt, size_t saltlen,
+ uint64_t N, uint32_t r, uint32_t p,
+ uint8_t *buf, size_t buflen)
+{
+ escrypt_kdf_t escrypt_kdf;
+ escrypt_local_t local;
+ int retval;
+
+ if (escrypt_init_local(&local)) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+#if defined(HAVE_EMMINTRIN_H)
+ escrypt_kdf =
+ sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
+#else
+ escrypt_kdf = escrypt_kdf_nosse;
+#endif
+ retval = escrypt_kdf(&local, passwd, passwdlen, salt, saltlen, N, r, p, buf,
+ buflen);
+ if (escrypt_free_local(&local)) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return retval;
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h
new file mode 100644
index 0000000000..83101967c3
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h
@@ -0,0 +1,98 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef crypto_scrypt_H
+#define crypto_scrypt_H
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#if SIZE_MAX > 0xffffffffULL
+#define ARCH_BITS 64
+#else
+#define ARCH_BITS 32
+#endif
+
+#define crypto_pwhash_scryptsalsa208sha256_STRPREFIXBYTES 14
+#define crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES 57
+#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES 32
+#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES_ENCODED 43
+#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES 32
+#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED 43
+
+#define BYTES2CHARS(bytes) ((((bytes) *8) + 5) / 6)
+
+typedef struct {
+ void * base, *aligned;
+ size_t size;
+} escrypt_region_t;
+
+typedef union {
+ uint64_t d[8];
+ uint32_t w[16];
+} escrypt_block_t;
+
+typedef escrypt_region_t escrypt_local_t;
+
+extern int escrypt_init_local(escrypt_local_t *__local);
+
+extern int escrypt_free_local(escrypt_local_t *__local);
+
+extern void *alloc_region(escrypt_region_t *region, size_t size);
+extern int free_region(escrypt_region_t *region);
+
+typedef int (*escrypt_kdf_t)(escrypt_local_t *__local, const uint8_t *__passwd,
+ size_t __passwdlen, const uint8_t *__salt,
+ size_t __saltlen, uint64_t __N, uint32_t __r,
+ uint32_t __p, uint8_t *__buf, size_t __buflen);
+
+extern int escrypt_kdf_nosse(escrypt_local_t *__local, const uint8_t *__passwd,
+ size_t __passwdlen, const uint8_t *__salt,
+ size_t __saltlen, uint64_t __N, uint32_t __r,
+ uint32_t __p, uint8_t *__buf, size_t __buflen);
+
+extern int escrypt_kdf_sse(escrypt_local_t *__local, const uint8_t *__passwd,
+ size_t __passwdlen, const uint8_t *__salt,
+ size_t __saltlen, uint64_t __N, uint32_t __r,
+ uint32_t __p, uint8_t *__buf, size_t __buflen);
+
+extern uint8_t *escrypt_r(escrypt_local_t *__local, const uint8_t *__passwd,
+ size_t __passwdlen, const uint8_t *__setting,
+ uint8_t *__buf, size_t __buflen);
+
+extern uint8_t *escrypt_gensalt_r(uint32_t __N_log2, uint32_t __r, uint32_t __p,
+ const uint8_t *__src, size_t __srclen,
+ uint8_t *__buf, size_t __buflen);
+
+extern const uint8_t *escrypt_parse_setting(const uint8_t *setting,
+ uint32_t *N_log2_p, uint32_t *r_p,
+ uint32_t *p_p);
+
+#endif /* !_CRYPTO_SCRYPT_H_ */
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
new file mode 100644
index 0000000000..9e31352dc2
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
@@ -0,0 +1,375 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../crypto_scrypt.h"
+#include "../pbkdf2-sha256.h"
+#include "private/common.h"
+
+static inline void
+blkcpy_64(escrypt_block_t *dest, const escrypt_block_t *src)
+{
+ int i;
+
+#if (ARCH_BITS == 32)
+ for (i = 0; i < 16; ++i) {
+ dest->w[i] = src->w[i];
+ }
+#else
+ for (i = 0; i < 8; ++i) {
+ dest->d[i] = src->d[i];
+ }
+#endif
+}
+
+static inline void
+blkxor_64(escrypt_block_t *dest, const escrypt_block_t *src)
+{
+ int i;
+
+#if (ARCH_BITS == 32)
+ for (i = 0; i < 16; ++i) {
+ dest->w[i] ^= src->w[i];
+ }
+#else
+ for (i = 0; i < 8; ++i) {
+ dest->d[i] ^= src->d[i];
+ }
+#endif
+}
+
+static inline void
+blkcpy(escrypt_block_t *dest, const escrypt_block_t *src, size_t len)
+{
+ size_t i, L;
+
+#if (ARCH_BITS == 32)
+ L = (len >> 2);
+ for (i = 0; i < L; ++i) {
+ dest->w[i] = src->w[i];
+ }
+#else
+ L = (len >> 3);
+ for (i = 0; i < L; ++i) {
+ dest->d[i] = src->d[i];
+ }
+#endif
+}
+
+static inline void
+blkxor(escrypt_block_t *dest, const escrypt_block_t *src, size_t len)
+{
+ size_t i, L;
+
+#if (ARCH_BITS == 32)
+ L = (len >> 2);
+ for (i = 0; i < L; ++i) {
+ dest->w[i] ^= src->w[i];
+ }
+#else
+ L = (len >> 3);
+ for (i = 0; i < L; ++i) {
+ dest->d[i] ^= src->d[i];
+ }
+#endif
+}
+
+/**
+ * salsa20_8(B):
+ * Apply the salsa20/8 core to the provided block.
+ */
+static void
+salsa20_8(uint32_t B[16])
+{
+ escrypt_block_t X;
+ uint32_t *x = X.w;
+ size_t i;
+
+ blkcpy_64(&X, (escrypt_block_t *) B);
+ for (i = 0; i < 8; i += 2) {
+#define R(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
+ /* Operate on columns. */
+ x[4] ^= R(x[0] + x[12], 7);
+ x[8] ^= R(x[4] + x[0], 9);
+ x[12] ^= R(x[8] + x[4], 13);
+ x[0] ^= R(x[12] + x[8], 18);
+
+ x[9] ^= R(x[5] + x[1], 7);
+ x[13] ^= R(x[9] + x[5], 9);
+ x[1] ^= R(x[13] + x[9], 13);
+ x[5] ^= R(x[1] + x[13], 18);
+
+ x[14] ^= R(x[10] + x[6], 7);
+ x[2] ^= R(x[14] + x[10], 9);
+ x[6] ^= R(x[2] + x[14], 13);
+ x[10] ^= R(x[6] + x[2], 18);
+
+ x[3] ^= R(x[15] + x[11], 7);
+ x[7] ^= R(x[3] + x[15], 9);
+ x[11] ^= R(x[7] + x[3], 13);
+ x[15] ^= R(x[11] + x[7], 18);
+
+ /* Operate on rows. */
+ x[1] ^= R(x[0] + x[3], 7);
+ x[2] ^= R(x[1] + x[0], 9);
+ x[3] ^= R(x[2] + x[1], 13);
+ x[0] ^= R(x[3] + x[2], 18);
+
+ x[6] ^= R(x[5] + x[4], 7);
+ x[7] ^= R(x[6] + x[5], 9);
+ x[4] ^= R(x[7] + x[6], 13);
+ x[5] ^= R(x[4] + x[7], 18);
+
+ x[11] ^= R(x[10] + x[9], 7);
+ x[8] ^= R(x[11] + x[10], 9);
+ x[9] ^= R(x[8] + x[11], 13);
+ x[10] ^= R(x[9] + x[8], 18);
+
+ x[12] ^= R(x[15] + x[14], 7);
+ x[13] ^= R(x[12] + x[15], 9);
+ x[14] ^= R(x[13] + x[12], 13);
+ x[15] ^= R(x[14] + x[13], 18);
+#undef R
+ }
+ for (i = 0; i < 16; i++)
+ B[i] += x[i];
+}
+
+/**
+ * blockmix_salsa8(Bin, Bout, X, r):
+ * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
+ * bytes in length; the output Bout must also be the same size. The
+ * temporary space X must be 64 bytes.
+ */
+static void
+blockmix_salsa8(const uint32_t *Bin, uint32_t *Bout, uint32_t *X, size_t r)
+{
+ size_t i;
+
+ /* 1: X <-- B_{2r - 1} */
+ blkcpy_64((escrypt_block_t *) X,
+ (escrypt_block_t *) &Bin[(2 * r - 1) * 16]);
+
+ /* 2: for i = 0 to 2r - 1 do */
+ for (i = 0; i < 2 * r; i += 2) {
+ /* 3: X <-- H(X \xor B_i) */
+ blkxor_64((escrypt_block_t *) X, (escrypt_block_t *) &Bin[i * 16]);
+ salsa20_8(X);
+
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ blkcpy_64((escrypt_block_t *) &Bout[i * 8], (escrypt_block_t *) X);
+
+ /* 3: X <-- H(X \xor B_i) */
+ blkxor_64((escrypt_block_t *) X, (escrypt_block_t *) &Bin[i * 16 + 16]);
+ salsa20_8(X);
+
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ blkcpy_64((escrypt_block_t *) &Bout[i * 8 + r * 16],
+ (escrypt_block_t *) X);
+ }
+}
+
+/**
+ * integerify(B, r):
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
+ */
+static inline uint64_t
+integerify(const void *B, size_t r)
+{
+ const uint32_t *X = (const uint32_t *) ((uintptr_t)(B) + (2 * r - 1) * 64);
+
+ return (((uint64_t)(X[1]) << 32) + X[0]);
+}
+
+/**
+ * smix(B, r, N, V, XY):
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
+ * the temporary storage V must be 128rN bytes in length; the temporary
+ * storage XY must be 256r + 64 bytes in length. The value N must be a
+ * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
+ * multiple of 64 bytes.
+ */
+static void
+smix(uint8_t *B, size_t r, uint64_t N, uint32_t *V, uint32_t *XY)
+{
+ uint32_t *X = XY;
+ uint32_t *Y = &XY[32 * r];
+ uint32_t *Z = &XY[64 * r];
+ uint64_t i;
+ uint64_t j;
+ size_t k;
+
+ /* 1: X <-- B */
+ for (k = 0; k < 32 * r; k++) {
+ X[k] = LOAD32_LE(&B[4 * k]);
+ }
+ /* 2: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ /* 3: V_i <-- X */
+ blkcpy((escrypt_block_t *) &V[i * (32 * r)], (escrypt_block_t *) X,
+ 128 * r);
+
+ /* 4: X <-- H(X) */
+ blockmix_salsa8(X, Y, Z, r);
+
+ /* 3: V_i <-- X */
+ blkcpy((escrypt_block_t *) &V[(i + 1) * (32 * r)],
+ (escrypt_block_t *) Y, 128 * r);
+
+ /* 4: X <-- H(X) */
+ blockmix_salsa8(Y, X, Z, r);
+ }
+
+ /* 6: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(X, r) & (N - 1);
+
+ /* 8: X <-- H(X \xor V_j) */
+ blkxor((escrypt_block_t *) X, (escrypt_block_t *) &V[j * (32 * r)],
+ 128 * r);
+ blockmix_salsa8(X, Y, Z, r);
+
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(Y, r) & (N - 1);
+
+ /* 8: X <-- H(X \xor V_j) */
+ blkxor((escrypt_block_t *) Y, (escrypt_block_t *) &V[j * (32 * r)],
+ 128 * r);
+ blockmix_salsa8(Y, X, Z, r);
+ }
+ /* 10: B' <-- X */
+ for (k = 0; k < 32 * r; k++) {
+ STORE32_LE(&B[4 * k], X[k]);
+ }
+}
+
+/**
+ * escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
+ * N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
+ * must be a power of 2 greater than 1.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int
+escrypt_kdf_nosse(escrypt_local_t *local, const uint8_t *passwd,
+ size_t passwdlen, const uint8_t *salt, size_t saltlen,
+ uint64_t N, uint32_t _r, uint32_t _p, uint8_t *buf,
+ size_t buflen)
+{
+ size_t B_size, V_size, XY_size, need;
+ uint8_t * B;
+ uint32_t *V, *XY;
+ size_t r = _r, p = _p;
+ uint32_t i;
+
+/* Sanity-check parameters. */
+#if SIZE_MAX > UINT32_MAX
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+ errno = EFBIG;
+ return -1;
+ }
+#endif
+ if ((uint64_t)(r) * (uint64_t)(p) >= ((uint64_t) 1 << 30)) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (N > UINT32_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (((N & (N - 1)) != 0) || (N < 2)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (r == 0 || p == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ if ((r > SIZE_MAX / 128 / p) ||
+#if SIZE_MAX / 256 <= UINT32_MAX
+ (r > SIZE_MAX / 256) ||
+#endif
+ (N > SIZE_MAX / 128 / r)) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Allocate memory. */
+ B_size = (size_t) 128 * r * p;
+ V_size = (size_t) 128 * r * (size_t) N;
+ need = B_size + V_size;
+ if (need < V_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+ XY_size = (size_t) 256 * r + 64;
+ need += XY_size;
+ if (need < XY_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+ if (local->size < need) {
+ if (free_region(local)) {
+ return -1;
+ }
+ if (!alloc_region(local, need)) {
+ return -1;
+ }
+ }
+ B = (uint8_t *) local->aligned;
+ V = (uint32_t *) ((uint8_t *) B + B_size);
+ XY = (uint32_t *) ((uint8_t *) V + V_size);
+
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
+ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
+
+ /* 2: for i = 0 to p - 1 do */
+ for (i = 0; i < p; i++) {
+ /* 3: B_i <-- MF(B_i, N) */
+ smix(&B[(size_t) 128 * i * r], r, N, V, XY);
+ }
+
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
+ PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
+
+ /* Success! */
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c
new file mode 100644
index 0000000000..42cab61fe2
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c
@@ -0,0 +1,95 @@
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include "core.h"
+#include "crypto_auth_hmacsha256.h"
+#include "crypto_pwhash_scryptsalsa208sha256.h"
+#include "pbkdf2-sha256.h"
+#include "private/common.h"
+#include "utils.h"
+
+/**
+ * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
+ */
+void
+PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen, const uint8_t *salt,
+ size_t saltlen, uint64_t c, uint8_t *buf, size_t dkLen)
+{
+ crypto_auth_hmacsha256_state PShctx, hctx;
+ size_t i;
+ uint8_t ivec[4];
+ uint8_t U[32];
+ uint8_t T[32];
+ uint64_t j;
+ int k;
+ size_t clen;
+
+#if SIZE_MAX > 0x1fffffffe0ULL
+ COMPILER_ASSERT(crypto_pwhash_scryptsalsa208sha256_BYTES_MAX
+ <= 0x1fffffffe0ULL);
+ if (dkLen > 0x1fffffffe0ULL) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+#endif
+ crypto_auth_hmacsha256_init(&PShctx, passwd, passwdlen);
+ crypto_auth_hmacsha256_update(&PShctx, salt, saltlen);
+
+ for (i = 0; i * 32 < dkLen; i++) {
+ STORE32_BE(ivec, (uint32_t)(i + 1));
+ memcpy(&hctx, &PShctx, sizeof(crypto_auth_hmacsha256_state));
+ crypto_auth_hmacsha256_update(&hctx, ivec, 4);
+ crypto_auth_hmacsha256_final(&hctx, U);
+
+ memcpy(T, U, 32);
+ /* LCOV_EXCL_START */
+ for (j = 2; j <= c; j++) {
+ crypto_auth_hmacsha256_init(&hctx, passwd, passwdlen);
+ crypto_auth_hmacsha256_update(&hctx, U, 32);
+ crypto_auth_hmacsha256_final(&hctx, U);
+
+ for (k = 0; k < 32; k++) {
+ T[k] ^= U[k];
+ }
+ }
+ /* LCOV_EXCL_STOP */
+
+ clen = dkLen - i * 32;
+ if (clen > 32) {
+ clen = 32;
+ }
+ memcpy(&buf[i * 32], T, clen);
+ }
+ sodium_memzero((void *) &PShctx, sizeof PShctx);
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h
new file mode 100644
index 0000000000..f9598c87aa
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef pbkdf2_sha256_H
+#define pbkdf2_sha256_H
+
+#include <stdint.h>
+
+#include <sys/types.h>
+
+#include "crypto_auth_hmacsha256.h"
+
+/**
+ * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
+ */
+void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t,
+ uint8_t *, size_t);
+
+#endif /* !_SHA256_H_ */
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
new file mode 100644
index 0000000000..d1afd91afe
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
@@ -0,0 +1,285 @@
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_pwhash_scryptsalsa208sha256.h"
+#include "crypto_scrypt.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#define SETTING_SIZE(saltbytes) \
+ ((sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + \
+ BYTES2CHARS(saltbytes))
+
+static int
+pickparams(unsigned long long opslimit, const size_t memlimit,
+ uint32_t *const N_log2, uint32_t *const p, uint32_t *const r)
+{
+ unsigned long long maxN;
+ unsigned long long maxrp;
+
+ if (opslimit < 32768) {
+ opslimit = 32768;
+ }
+ *r = 8;
+ if (opslimit < memlimit / 32) {
+ *p = 1;
+ maxN = opslimit / (*r * 4);
+ for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
+ if ((uint64_t)(1) << *N_log2 > maxN / 2) {
+ break;
+ }
+ }
+ } else {
+ maxN = memlimit / ((size_t) *r * 128);
+ for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
+ if ((uint64_t)(1) << *N_log2 > maxN / 2) {
+ break;
+ }
+ }
+ maxrp = (opslimit / 4) / ((uint64_t)(1) << *N_log2);
+ /* LCOV_EXCL_START */
+ if (maxrp > 0x3fffffff) {
+ maxrp = 0x3fffffff;
+ }
+ /* LCOV_EXCL_STOP */
+ *p = (uint32_t)(maxrp) / *r;
+ }
+ return 0;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_bytes_min(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_BYTES_MIN;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_bytes_max(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_BYTES_MAX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_passwd_min(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_passwd_max(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_saltbytes(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_strbytes(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_STRBYTES;
+}
+
+const char *
+crypto_pwhash_scryptsalsa208sha256_strprefix(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_STRPREFIX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_opslimit_min(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_opslimit_max(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_memlimit_min(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_memlimit_max(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256(unsigned char *const out,
+ unsigned long long outlen,
+ const char *const passwd,
+ unsigned long long passwdlen,
+ const unsigned char *const salt,
+ unsigned long long opslimit, size_t memlimit)
+{
+ uint32_t N_log2;
+ uint32_t p;
+ uint32_t r;
+
+ memset(out, 0, outlen);
+ if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX ||
+ outlen > crypto_pwhash_scryptsalsa208sha256_BYTES_MAX) {
+ errno = EFBIG; /* LCOV_EXCL_LINE */
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (outlen < crypto_pwhash_scryptsalsa208sha256_BYTES_MIN ||
+ pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
+ errno = EINVAL; /* LCOV_EXCL_LINE */
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return crypto_pwhash_scryptsalsa208sha256_ll(
+ (const uint8_t *) passwd, (size_t) passwdlen, (const uint8_t *) salt,
+ crypto_pwhash_scryptsalsa208sha256_SALTBYTES, (uint64_t)(1) << N_log2,
+ r, p, out, (size_t) outlen);
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_str(
+ char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ const char *const passwd, unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+{
+ uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES];
+ char setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U];
+ escrypt_local_t escrypt_local;
+ uint32_t N_log2;
+ uint32_t p;
+ uint32_t r;
+
+ memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES);
+ if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX) {
+ errno = EFBIG; /* LCOV_EXCL_LINE */
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (passwdlen < crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN ||
+ pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
+ errno = EINVAL; /* LCOV_EXCL_LINE */
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ randombytes_buf(salt, sizeof salt);
+ if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt, (uint8_t *) setting,
+ sizeof setting) == NULL) {
+ errno = EINVAL; /* LCOV_EXCL_LINE */
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (escrypt_init_local(&escrypt_local) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
+ (const uint8_t *) setting, (uint8_t *) out,
+ crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) {
+ /* LCOV_EXCL_START */
+ escrypt_free_local(&escrypt_local);
+ errno = EINVAL;
+ return -1;
+ /* LCOV_EXCL_STOP */
+ }
+ escrypt_free_local(&escrypt_local);
+
+ COMPILER_ASSERT(
+ SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES) ==
+ crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES);
+ COMPILER_ASSERT(
+ crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U +
+ crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U ==
+ crypto_pwhash_scryptsalsa208sha256_STRBYTES);
+
+ return 0;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_str_verify(
+ const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ const char *const passwd, unsigned long long passwdlen)
+{
+ char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES];
+ escrypt_local_t escrypt_local;
+ int ret = -1;
+
+ if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
+ &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) {
+ return -1;
+ }
+ if (escrypt_init_local(&escrypt_local) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ memset(wanted, 0, sizeof wanted);
+ if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
+ (const uint8_t *) str, (uint8_t *) wanted,
+ sizeof wanted) == NULL) {
+ escrypt_free_local(&escrypt_local);
+ return -1;
+ }
+ escrypt_free_local(&escrypt_local);
+ ret = sodium_memcmp(wanted, str, sizeof wanted);
+ sodium_memzero(wanted, sizeof wanted);
+
+ return ret;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
+ const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+{
+ uint32_t N_log2, N_log2_;
+ uint32_t p, p_;
+ uint32_t r, r_;
+
+ if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
+ &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (escrypt_parse_setting((const uint8_t *) str,
+ &N_log2_, &r_, &p_) == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (N_log2 != N_log2_ || r != r_ || p != p_) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c
new file mode 100644
index 0000000000..139a7df286
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c
@@ -0,0 +1,108 @@
+/*-
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+
+#include "crypto_scrypt.h"
+#include "runtime.h"
+
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+#endif
+#ifndef MAP_NOCORE
+# define MAP_NOCORE 0
+#endif
+#ifndef MAP_POPULATE
+# define MAP_POPULATE 0
+#endif
+
+void *
+alloc_region(escrypt_region_t *region, size_t size)
+{
+ uint8_t *base, *aligned;
+#if defined(MAP_ANON) && defined(HAVE_MMAP)
+ if ((base = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE | MAP_POPULATE,
+ -1, 0)) == MAP_FAILED) {
+ base = NULL; /* LCOV_EXCL_LINE */
+ } /* LCOV_EXCL_LINE */
+ aligned = base;
+#elif defined(HAVE_POSIX_MEMALIGN)
+ if ((errno = posix_memalign((void **) &base, 64, size)) != 0) {
+ base = NULL;
+ }
+ aligned = base;
+#else
+ base = aligned = NULL;
+ if (size + 63 < size)
+ errno = ENOMEM;
+ else if ((base = (uint8_t *) malloc(size + 63)) != NULL) {
+ aligned = base + 63;
+ aligned -= (uintptr_t) aligned & 63;
+ }
+#endif
+ region->base = base;
+ region->aligned = aligned;
+ region->size = base ? size : 0;
+
+ return aligned;
+}
+
+static inline void
+init_region(escrypt_region_t *region)
+{
+ region->base = region->aligned = NULL;
+ region->size = 0;
+}
+
+int
+free_region(escrypt_region_t *region)
+{
+ if (region->base) {
+#if defined(MAP_ANON) && defined(HAVE_MMAP)
+ if (munmap(region->base, region->size)) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+#else
+ free(region->base);
+#endif
+ }
+ init_region(region);
+
+ return 0;
+}
+
+int
+escrypt_init_local(escrypt_local_t *local)
+{
+ init_region(local);
+
+ return 0;
+}
+
+int
+escrypt_free_local(escrypt_local_t *local)
+{
+ return free_region(local);
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
new file mode 100644
index 0000000000..754a19fdb8
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
@@ -0,0 +1,400 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * Copyright 2012,2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#ifdef HAVE_EMMINTRIN_H
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# endif
+# include <emmintrin.h>
+# if defined(__XOP__) && defined(DISABLED)
+# include <x86intrin.h>
+# endif
+
+# include "../crypto_scrypt.h"
+# include "../pbkdf2-sha256.h"
+
+# if defined(__XOP__) && defined(DISABLED)
+# define ARX(out, in1, in2, s) \
+ out = _mm_xor_si128(out, _mm_roti_epi32(_mm_add_epi32(in1, in2), s));
+# else
+# define ARX(out, in1, in2, s) \
+ { \
+ __m128i T = _mm_add_epi32(in1, in2); \
+ out = _mm_xor_si128(out, _mm_slli_epi32(T, s)); \
+ out = _mm_xor_si128(out, _mm_srli_epi32(T, 32 - s)); \
+ }
+# endif
+
+# define SALSA20_2ROUNDS \
+ /* Operate on "columns". */ \
+ ARX(X1, X0, X3, 7) \
+ ARX(X2, X1, X0, 9) \
+ ARX(X3, X2, X1, 13) \
+ ARX(X0, X3, X2, 18) \
+ \
+ /* Rearrange data. */ \
+ X1 = _mm_shuffle_epi32(X1, 0x93); \
+ X2 = _mm_shuffle_epi32(X2, 0x4E); \
+ X3 = _mm_shuffle_epi32(X3, 0x39); \
+ \
+ /* Operate on "rows". */ \
+ ARX(X3, X0, X1, 7) \
+ ARX(X2, X3, X0, 9) \
+ ARX(X1, X2, X3, 13) \
+ ARX(X0, X1, X2, 18) \
+ \
+ /* Rearrange data. */ \
+ X1 = _mm_shuffle_epi32(X1, 0x39); \
+ X2 = _mm_shuffle_epi32(X2, 0x4E); \
+ X3 = _mm_shuffle_epi32(X3, 0x93);
+
+/**
+ * Apply the salsa20/8 core to the block provided in (X0 ... X3) ^ (Z0 ... Z3).
+ */
+# define SALSA20_8_XOR(in, out) \
+ { \
+ __m128i Y0 = X0 = _mm_xor_si128(X0, (in)[0]); \
+ __m128i Y1 = X1 = _mm_xor_si128(X1, (in)[1]); \
+ __m128i Y2 = X2 = _mm_xor_si128(X2, (in)[2]); \
+ __m128i Y3 = X3 = _mm_xor_si128(X3, (in)[3]); \
+ SALSA20_2ROUNDS \
+ SALSA20_2ROUNDS \
+ SALSA20_2ROUNDS \
+ SALSA20_2ROUNDS(out)[0] = X0 = _mm_add_epi32(X0, Y0); \
+ (out)[1] = X1 = _mm_add_epi32(X1, Y1); \
+ (out)[2] = X2 = _mm_add_epi32(X2, Y2); \
+ (out)[3] = X3 = _mm_add_epi32(X3, Y3); \
+ }
+
+/**
+ * blockmix_salsa8(Bin, Bout, r):
+ * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
+ * bytes in length; the output Bout must also be the same size.
+ */
+static inline void
+blockmix_salsa8(const __m128i *Bin, __m128i *Bout, size_t r)
+{
+ __m128i X0, X1, X2, X3;
+ size_t i;
+
+ /* 1: X <-- B_{2r - 1} */
+ X0 = Bin[8 * r - 4];
+ X1 = Bin[8 * r - 3];
+ X2 = Bin[8 * r - 2];
+ X3 = Bin[8 * r - 1];
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(Bin, Bout)
+
+ /* 2: for i = 0 to 2r - 1 do */
+ r--;
+ for (i = 0; i < r;) {
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+
+ i++;
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(&Bin[i * 8], &Bout[i * 4])
+ }
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+}
+
+# define XOR4(in) \
+ X0 = _mm_xor_si128(X0, (in)[0]); \
+ X1 = _mm_xor_si128(X1, (in)[1]); \
+ X2 = _mm_xor_si128(X2, (in)[2]); \
+ X3 = _mm_xor_si128(X3, (in)[3]);
+
+# define XOR4_2(in1, in2) \
+ X0 = _mm_xor_si128((in1)[0], (in2)[0]); \
+ X1 = _mm_xor_si128((in1)[1], (in2)[1]); \
+ X2 = _mm_xor_si128((in1)[2], (in2)[2]); \
+ X3 = _mm_xor_si128((in1)[3], (in2)[3]);
+
+static inline uint32_t
+blockmix_salsa8_xor(const __m128i *Bin1, const __m128i *Bin2, __m128i *Bout,
+ size_t r)
+{
+ __m128i X0, X1, X2, X3;
+ size_t i;
+
+ /* 1: X <-- B_{2r - 1} */
+ XOR4_2(&Bin1[8 * r - 4], &Bin2[8 * r - 4])
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(Bin1)
+ SALSA20_8_XOR(Bin2, Bout)
+
+ /* 2: for i = 0 to 2r - 1 do */
+ r--;
+ for (i = 0; i < r;) {
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(&Bin1[i * 8 + 4])
+ SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+
+ i++;
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(&Bin1[i * 8])
+ SALSA20_8_XOR(&Bin2[i * 8], &Bout[i * 4])
+ }
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(&Bin1[i * 8 + 4])
+ SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+
+ return _mm_cvtsi128_si32(X0);
+}
+
+# undef ARX
+# undef SALSA20_2ROUNDS
+# undef SALSA20_8_XOR
+# undef XOR4
+# undef XOR4_2
+
+/**
+ * integerify(B, r):
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
+ * Note that B's layout is permuted compared to the generic implementation.
+ */
+static inline uint32_t
+integerify(const void *B, size_t r)
+{
+ return *(const uint32_t *) ((uintptr_t)(B) + (2 * r - 1) * 64);
+}
+
+/**
+ * smix(B, r, N, V, XY):
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
+ * the temporary storage V must be 128rN bytes in length; the temporary
+ * storage XY must be 256r + 64 bytes in length. The value N must be a
+ * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
+ * multiple of 64 bytes.
+ */
+static void
+smix(uint8_t *B, size_t r, uint32_t N, void *V, void *XY)
+{
+ size_t s = 128 * r;
+ __m128i * X = (__m128i *) V, *Y;
+ uint32_t *X32 = (uint32_t *) V;
+ uint32_t i, j;
+ size_t k;
+
+ /* 1: X <-- B */
+ /* 3: V_i <-- X */
+ for (k = 0; k < 2 * r; k++) {
+ for (i = 0; i < 16; i++) {
+ X32[k * 16 + i] = LOAD32_LE(&B[(k * 16 + (i * 5 % 16)) * 4]);
+ }
+ }
+
+ /* 2: for i = 0 to N - 1 do */
+ for (i = 1; i < N - 1; i += 2) {
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ Y = (__m128i *) ((uintptr_t)(V) + i * s);
+ blockmix_salsa8(X, Y, r);
+
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ X = (__m128i *) ((uintptr_t)(V) + (i + 1) * s);
+ blockmix_salsa8(Y, X, r);
+ }
+
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ Y = (__m128i *) ((uintptr_t)(V) + i * s);
+ blockmix_salsa8(X, Y, r);
+
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ X = (__m128i *) XY;
+ blockmix_salsa8(Y, X, r);
+
+ X32 = (uint32_t *) XY;
+ Y = (__m128i *) ((uintptr_t)(XY) + s);
+
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(X, r) & (N - 1);
+
+ /* 6: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ __m128i *V_j = (__m128i *) ((uintptr_t)(V) + j * s);
+
+ /* 8: X <-- H(X \xor V_j) */
+ /* 7: j <-- Integerify(X) mod N */
+ j = blockmix_salsa8_xor(X, V_j, Y, r) & (N - 1);
+ V_j = (__m128i *) ((uintptr_t)(V) + j * s);
+
+ /* 8: X <-- H(X \xor V_j) */
+ /* 7: j <-- Integerify(X) mod N */
+ j = blockmix_salsa8_xor(Y, V_j, X, r) & (N - 1);
+ }
+
+ /* 10: B' <-- X */
+ for (k = 0; k < 2 * r; k++) {
+ for (i = 0; i < 16; i++) {
+ STORE32_LE(&B[(k * 16 + (i * 5 % 16)) * 4], X32[k * 16 + i]);
+ }
+ }
+}
+
+/**
+ * escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
+ * N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
+ * must be a power of 2 greater than 1.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int
+escrypt_kdf_sse(escrypt_local_t *local, const uint8_t *passwd, size_t passwdlen,
+ const uint8_t *salt, size_t saltlen, uint64_t N, uint32_t _r,
+ uint32_t _p, uint8_t *buf, size_t buflen)
+{
+ size_t B_size, V_size, XY_size, need;
+ uint8_t * B;
+ uint32_t *V, *XY;
+ size_t r = _r, p = _p;
+ uint32_t i;
+
+/* Sanity-check parameters. */
+# if SIZE_MAX > UINT32_MAX
+/* LCOV_EXCL_START */
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+ errno = EFBIG;
+ return -1;
+ }
+/* LCOV_EXCL_END */
+# endif
+ if ((uint64_t)(r) * (uint64_t)(p) >= ((uint64_t) 1 << 30)) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (N > UINT32_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (((N & (N - 1)) != 0) || (N < 2)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (r == 0 || p == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+/* LCOV_EXCL_START */
+ if ((r > SIZE_MAX / 128 / p) ||
+# if SIZE_MAX / 256 <= UINT32_MAX
+ (r > SIZE_MAX / 256) ||
+# endif
+ (N > SIZE_MAX / 128 / r)) {
+ errno = ENOMEM;
+ return -1;
+ }
+/* LCOV_EXCL_END */
+
+ /* Allocate memory. */
+ B_size = (size_t) 128 * r * p;
+ V_size = (size_t) 128 * r * N;
+ need = B_size + V_size;
+/* LCOV_EXCL_START */
+ if (need < V_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+/* LCOV_EXCL_END */
+ XY_size = (size_t) 256 * r + 64;
+ need += XY_size;
+/* LCOV_EXCL_START */
+ if (need < XY_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+/* LCOV_EXCL_END */
+ if (local->size < need) {
+ if (free_region(local)) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (!alloc_region(local, need)) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ }
+ B = (uint8_t *) local->aligned;
+ V = (uint32_t *) ((uint8_t *) B + B_size);
+ XY = (uint32_t *) ((uint8_t *) V + V_size);
+
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
+ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
+
+ /* 2: for i = 0 to p - 1 do */
+ for (i = 0; i < p; i++) {
+ /* 3: B_i <-- MF(B_i, N) */
+ smix(&B[(size_t) 128 * i * r], r, (uint32_t) N, V, XY);
+ }
+
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
+ PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
+
+ /* Success! */
+ return 0;
+}
+#endif