summaryrefslogtreecommitdiff
path: root/src/libsodium/crypto_pwhash
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsodium/crypto_pwhash')
-rw-r--r--src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c250
-rw-r--r--src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h86
-rw-r--r--src/libsodium/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c302
-rw-r--r--src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c84
-rw-r--r--src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h45
-rw-r--r--src/libsodium/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c197
-rw-r--r--src/libsodium/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c100
-rw-r--r--src/libsodium/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c391
-rw-r--r--src/libsodium/crypto_pwhash/scryptsalsa208sha256/sysendian.h146
9 files changed, 1601 insertions, 0 deletions
diff --git a/src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c
new file mode 100644
index 0000000..837ce3f
--- /dev/null
+++ b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c
@@ -0,0 +1,250 @@
+/*-
+ * 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 "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;
+ }
+ *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;
+ }
+ 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 = 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;
+}
+
+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;
+
+ if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$') {
+ return NULL;
+ }
+ src = setting + 3;
+
+ if (decode64_one(&N_log2, *src)) {
+ return NULL;
+ }
+ src++;
+ N = (uint64_t)1 << N_log2;
+
+ src = decode64_uint32(&r, 30, src);
+ if (!src) {
+ return NULL;
+ }
+ src = decode64_uint32(&p, 30, src);
+ if (!src) {
+ return NULL;
+ }
+ 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;
+ }
+#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER)
+ 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) { /* Can't happen */
+ return NULL;
+ }
+ *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;
+ }
+ if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30))) {
+ return NULL;
+ }
+ dst = buf;
+ *dst++ = '$';
+ *dst++ = '7';
+ *dst++ = '$';
+
+ *dst++ = itoa64[N_log2];
+
+ dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
+ if (!dst) { /* Can't happen */
+ return NULL;
+ }
+ dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
+ if (!dst) { /* Can't happen */
+ return NULL;
+ }
+ dst = encode64(dst, buflen - (dst - buf), src, srclen);
+ if (!dst || dst >= buf + buflen) { /* Can't happen */
+ return NULL;
+ }
+ *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;
+ }
+#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER)
+ 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;
+ }
+ return retval;
+}
diff --git a/src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h
new file mode 100644
index 0000000..fbbf38b
--- /dev/null
+++ b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h
@@ -0,0 +1,86 @@
+/*-
+ * 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 <stdint.h>
+
+#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 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);
+
+#endif /* !_CRYPTO_SCRYPT_H_ */
diff --git a/src/libsodium/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
new file mode 100644
index 0000000..a9ab966
--- /dev/null
+++ b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
@@ -0,0 +1,302 @@
+/*-
+ * 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 "../pbkdf2-sha256.h"
+#include "../sysendian.h"
+#include "../crypto_scrypt.h"
+
+static inline void
+blkcpy(void * dest, const void * src, size_t len)
+{
+ size_t * D = (size_t *) dest;
+ const size_t * S = (const size_t *) src;
+ size_t L = len / sizeof(size_t);
+ size_t i;
+
+ for (i = 0; i < L; i++)
+ D[i] = S[i];
+}
+
+static inline void
+blkxor(void * dest, const void * src, size_t len)
+{
+ size_t * D = (size_t *) dest;
+ const size_t * S = (const size_t *) src;
+ size_t L = len / sizeof(size_t);
+ size_t i;
+
+ for (i = 0; i < L; i++)
+ D[i] ^= S[i];
+}
+
+/**
+ * salsa20_8(B):
+ * Apply the salsa20/8 core to the provided block.
+ */
+static void
+salsa20_8(uint32_t B[16])
+{
+ uint32_t x[16];
+ size_t i;
+
+ blkcpy(x, B, 64);
+ 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(X, &Bin[(2 * r - 1) * 16], 64);
+
+ /* 2: for i = 0 to 2r - 1 do */
+ for (i = 0; i < 2 * r; i += 2) {
+ /* 3: X <-- H(X \xor B_i) */
+ blkxor(X, &Bin[i * 16], 64);
+ salsa20_8(X);
+
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ blkcpy(&Bout[i * 8], X, 64);
+
+ /* 3: X <-- H(X \xor B_i) */
+ blkxor(X, &Bin[i * 16 + 16], 64);
+ salsa20_8(X);
+
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ blkcpy(&Bout[i * 8 + r * 16], X, 64);
+ }
+}
+
+/**
+ * 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] = le32dec(&B[4 * k]);
+
+ /* 2: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ /* 3: V_i <-- X */
+ blkcpy(&V[i * (32 * r)], X, 128 * r);
+
+ /* 4: X <-- H(X) */
+ blockmix_salsa8(X, Y, Z, r);
+
+ /* 3: V_i <-- X */
+ blkcpy(&V[(i + 1) * (32 * r)], 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(X, &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(Y, &V[j * (32 * r)], 128 * r);
+ blockmix_salsa8(Y, X, Z, r);
+ }
+ /* 10: B' <-- X */
+ for (k = 0; k < 32 * r; k++)
+ le32enc(&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) >= (1 << 30)) {
+ 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 * 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/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c
new file mode 100644
index 0000000..ac426d3
--- /dev/null
+++ b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c
@@ -0,0 +1,84 @@
+/*-
+ * 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 <sys/types.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crypto_auth_hmacsha256.h"
+#include "pbkdf2-sha256.h"
+#include "sysendian.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;
+
+ crypto_auth_hmacsha256_init(&PShctx, passwd, passwdlen);
+ crypto_auth_hmacsha256_update(&PShctx, salt, saltlen);
+
+ for (i = 0; i * 32 < dkLen; i++) {
+ be32enc(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);
+
+ 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];
+ }
+ }
+
+ clen = dkLen - i * 32;
+ if (clen > 32) {
+ clen = 32;
+ }
+ memcpy(&buf[i * 32], T, clen);
+ }
+ sodium_memzero((void *) &PShctx, sizeof PShctx);
+}
diff --git a/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h
new file mode 100644
index 0000000..81b2fcc
--- /dev/null
+++ b/src/libsodium/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 _SHA256_H_
+#define _SHA256_H_
+
+#include <sys/types.h>
+
+#include <stdint.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/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
new file mode 100644
index 0000000..b4e64a5
--- /dev/null
+++ b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
@@ -0,0 +1,197 @@
+
+#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 "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 / (*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);
+ if (maxrp > 0x3fffffff) {
+ maxrp = 0x3fffffff;
+ }
+ *p = (uint32_t) (maxrp) / *r;
+ }
+ return 0;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_saltbytes(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_strbytes(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_STRBYTES;
+}
+
+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 > SIZE_MAX || outlen > SIZE_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ 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 > SIZE_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ randombytes_buf(salt, sizeof salt);
+ if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt,
+ (uint8_t *) setting, sizeof setting) == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (escrypt_init_local(&escrypt_local) != 0) {
+ return -1;
+ }
+ if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
+ (const uint8_t *) setting, (uint8_t *) out,
+ crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) {
+ escrypt_free_local(&escrypt_local);
+ errno = EINVAL;
+ return -1;
+ }
+ escrypt_free_local(&escrypt_local);
+
+ (void) sizeof
+ (int[SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES)
+ == crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES ? 1 : -1]);
+ (void) sizeof
+ (int[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U +
+ crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U
+ == crypto_pwhash_scryptsalsa208sha256_STRBYTES ? 1 : -1]);
+
+ 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;
+ }
+ 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;
+}
diff --git a/src/libsodium/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c
new file mode 100644
index 0000000..cddf964
--- /dev/null
+++ b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c
@@ -0,0 +1,100 @@
+/*-
+ * 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
+
+void *
+alloc_region(escrypt_region_t * region, size_t size)
+{
+ uint8_t * base, * aligned;
+#ifdef MAP_ANON
+ if ((base = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE,
+#ifdef MAP_NOCORE
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
+#else
+ MAP_ANON | MAP_PRIVATE,
+#endif
+ -1, 0)) == MAP_FAILED)
+ base = NULL;
+ 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) {
+#ifdef MAP_ANON
+ if (munmap(region->base, region->size))
+ return -1;
+#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/src/libsodium/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
new file mode 100644
index 0000000..d340dd0
--- /dev/null
+++ b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
@@ -0,0 +1,391 @@
+/*-
+ * 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.
+ */
+
+#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER)
+#if __GNUC__
+# pragma GCC target("sse2")
+#endif
+#include <emmintrin.h>
+#if defined(__XOP__) && defined(DISABLED)
+# include <x86intrin.h>
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../pbkdf2-sha256.h"
+#include "../sysendian.h"
+#include "../crypto_scrypt.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.
+ */
+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] =
+ le32dec(&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++) {
+ le32enc(&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
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+ errno = EFBIG;
+ return -1;
+ }
+#endif
+ if ((uint64_t)(r) * (uint64_t)(p) >= (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 * 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;
+}
+#endif
diff --git a/src/libsodium/crypto_pwhash/scryptsalsa208sha256/sysendian.h b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/sysendian.h
new file mode 100644
index 0000000..2f2c96f
--- /dev/null
+++ b/src/libsodium/crypto_pwhash/scryptsalsa208sha256/sysendian.h
@@ -0,0 +1,146 @@
+#ifndef _SYSENDIAN_H_
+#define _SYSENDIAN_H_
+
+#include <stdint.h>
+
+/* Avoid namespace collisions with BSD <sys/endian.h>. */
+#define be16dec scrypt_be16dec
+#define be16enc scrypt_be16enc
+#define be32dec scrypt_be32dec
+#define be32enc scrypt_be32enc
+#define be64dec scrypt_be64dec
+#define be64enc scrypt_be64enc
+#define le16dec scrypt_le16dec
+#define le16enc scrypt_le16enc
+#define le32dec scrypt_le32dec
+#define le32enc scrypt_le32enc
+#define le64dec scrypt_le64dec
+#define le64enc scrypt_le64enc
+
+static inline uint16_t
+be16dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint16_t)(p[1]) + ((uint16_t)(p[0]) << 8));
+}
+
+static inline void
+be16enc(void *pp, uint16_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[1] = x & 0xff;
+ p[0] = (x >> 8) & 0xff;
+}
+
+static inline uint32_t
+be32dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
+ ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
+}
+
+static inline void
+be32enc(void *pp, uint32_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[3] = x & 0xff;
+ p[2] = (x >> 8) & 0xff;
+ p[1] = (x >> 16) & 0xff;
+ p[0] = (x >> 24) & 0xff;
+}
+
+static inline uint64_t
+be64dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
+ ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
+ ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
+ ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
+}
+
+static inline void
+be64enc(void *pp, uint64_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[7] = x & 0xff;
+ p[6] = (x >> 8) & 0xff;
+ p[5] = (x >> 16) & 0xff;
+ p[4] = (x >> 24) & 0xff;
+ p[3] = (x >> 32) & 0xff;
+ p[2] = (x >> 40) & 0xff;
+ p[1] = (x >> 48) & 0xff;
+ p[0] = (x >> 56) & 0xff;
+}
+
+static inline uint16_t
+le16dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint16_t)(p[0]) + ((uint16_t)(p[1]) << 8));
+}
+
+static inline void
+le16enc(void *pp, uint16_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[0] = x & 0xff;
+ p[1] = (x >> 8) & 0xff;
+}
+
+static inline uint32_t
+le32dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
+ ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
+}
+
+static inline void
+le32enc(void *pp, uint32_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[0] = x & 0xff;
+ p[1] = (x >> 8) & 0xff;
+ p[2] = (x >> 16) & 0xff;
+ p[3] = (x >> 24) & 0xff;
+}
+
+static inline uint64_t
+le64dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
+ ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
+ ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
+ ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
+}
+
+static inline void
+le64enc(void *pp, uint64_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[0] = x & 0xff;
+ p[1] = (x >> 8) & 0xff;
+ p[2] = (x >> 16) & 0xff;
+ p[3] = (x >> 24) & 0xff;
+ p[4] = (x >> 32) & 0xff;
+ p[5] = (x >> 40) & 0xff;
+ p[6] = (x >> 48) & 0xff;
+ p[7] = (x >> 56) & 0xff;
+}
+
+#endif /* !_SYSENDIAN_H_ */