1187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root/*-
2187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * Copyright 2009 Colin Percival
3187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * All rights reserved.
4187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root *
5187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * Redistribution and use in source and binary forms, with or without
6187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * modification, are permitted provided that the following conditions
7187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * are met:
8187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * 1. Redistributions of source code must retain the above copyright
9187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root *    notice, this list of conditions and the following disclaimer.
10187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * 2. Redistributions in binary form must reproduce the above copyright
11187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root *    notice, this list of conditions and the following disclaimer in the
12187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root *    documentation and/or other materials provided with the distribution.
13187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root *
14187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * SUCH DAMAGE.
25187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root *
26187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * This file was originally written by Colin Percival as part of the Tarsnap
27187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * online backup system.
28187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root */
29187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include "scrypt_platform.h"
30187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
31187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include <machine/cpu-features.h>
32187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include <arm_neon.h>
33187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
34187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include <errno.h>
35187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include <stdint.h>
36187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include <limits.h>
37187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include <stdlib.h>
38187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include <string.h>
39187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
40187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#ifdef USE_OPENSSL_PBKDF2
41187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include <openssl/evp.h>
42187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#else
43187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include "sha256.h"
44187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
45187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include "sysendian.h"
46187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
47187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include "crypto_scrypt.h"
48187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
49187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#include "crypto_scrypt-neon-salsa208.h"
50187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
51187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootstatic void blkcpy(void *, void *, size_t);
52187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootstatic void blkxor(void *, void *, size_t);
53187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootvoid crypto_core_salsa208_armneon2(void *);
54187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootstatic void blockmix_salsa8(uint8x16_t *, uint8x16_t *, uint8x16_t *, size_t);
55187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootstatic uint64_t integerify(void *, size_t);
56187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootstatic void smix(uint8_t *, size_t, uint64_t, void *, void *);
57187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
58187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootstatic void
59187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootblkcpy(void * dest, void * src, size_t len)
60187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root{
61187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint8x16_t * D = dest;
62187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint8x16_t * S = src;
63187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	size_t L = len / 16;
64187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	size_t i;
65187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
66187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	for (i = 0; i < L; i++)
67187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		D[i] = S[i];
68187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root}
69187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
70187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootstatic void
71187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootblkxor(void * dest, void * src, size_t len)
72187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root{
73187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint8x16_t * D = dest;
74187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint8x16_t * S = src;
75187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	size_t L = len / 16;
76187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	size_t i;
77187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
78187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	for (i = 0; i < L; i++)
79187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		D[i] = veorq_u8(D[i], S[i]);
80187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root}
81187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
82187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root/**
83187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * blockmix_salsa8(B, Y, r):
84187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * Compute B = BlockMix_{salsa20/8, r}(B).  The input B must be 128r bytes in
85187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * length; the temporary space Y must also be the same size.
86187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root */
87187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootstatic void
88187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootblockmix_salsa8(uint8x16_t * Bin, uint8x16_t * Bout, uint8x16_t * X, size_t r)
89187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root{
90187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	size_t i;
91187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
92187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* 1: X <-- B_{2r - 1} */
93187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	blkcpy(X, &Bin[8 * r - 4], 64);
94187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
95187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* 2: for i = 0 to 2r - 1 do */
96187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	for (i = 0; i < r; i++) {
97187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 3: X <-- H(X \xor B_i) */
98187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blkxor(X, &Bin[i * 8], 64);
99187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root                salsa20_8_intrinsic((void *) X);
100187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
101187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 4: Y_i <-- X */
102187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
103187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blkcpy(&Bout[i * 4], X, 64);
104187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
105187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 3: X <-- H(X \xor B_i) */
106187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blkxor(X, &Bin[i * 8 + 4], 64);
107187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root                salsa20_8_intrinsic((void *) X);
108187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
109187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 4: Y_i <-- X */
110187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
111187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blkcpy(&Bout[(r + i) * 4], X, 64);
112187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	}
113187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root}
114187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
115187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root/**
116187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * integerify(B, r):
117187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * Return the result of parsing B_{2r-1} as a little-endian integer.
118187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root */
119187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootstatic uint64_t
120187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootintegerify(void * B, size_t r)
121187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root{
122187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint8_t * X = (void*)((uintptr_t)(B) + (2 * r - 1) * 64);
123187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
124187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	return (le64dec(X));
125187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root}
126187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
127187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root/**
128187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * smix(B, r, N, V, XY):
129187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length; the
130187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * temporary storage V must be 128rN bytes in length; the temporary storage
131187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * XY must be 256r bytes in length.  The value N must be a power of 2.
132187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root */
133187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootstatic void
134187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootsmix(uint8_t * B, size_t r, uint64_t N, void * V, void * XY)
135187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root{
136187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint8x16_t * X = XY;
137187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint8x16_t * Y = (void *)((uintptr_t)(XY) + 128 * r);
138187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root        uint8x16_t * Z = (void *)((uintptr_t)(XY) + 256 * r);
139187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root        uint32_t * X32 = (void *)X;
140187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint64_t i, j;
141187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root        size_t k;
142187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
143187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* 1: X <-- B */
144187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	blkcpy(X, B, 128 * r);
145187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
146187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* 2: for i = 0 to N - 1 do */
147187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	for (i = 0; i < N; i += 2) {
148187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 3: V_i <-- X */
149187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r);
150187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
151187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 4: X <-- H(X) */
152187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blockmix_salsa8(X, Y, Z, r);
153187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
154187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 3: V_i <-- X */
155187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r),
156187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		    Y, 128 * r);
157187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
158187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 4: X <-- H(X) */
159187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blockmix_salsa8(Y, X, Z, r);
160187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	}
161187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
162187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* 6: for i = 0 to N - 1 do */
163187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	for (i = 0; i < N; i += 2) {
164187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 7: j <-- Integerify(X) mod N */
165187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		j = integerify(X, r) & (N - 1);
166187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
167187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 8: X <-- H(X \xor V_j) */
168187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
169187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blockmix_salsa8(X, Y, Z, r);
170187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
171187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 7: j <-- Integerify(X) mod N */
172187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		j = integerify(Y, r) & (N - 1);
173187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
174187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 8: X <-- H(X \xor V_j) */
175187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
176187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		blockmix_salsa8(Y, X, Z, r);
177187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	}
178187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
179187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* 10: B' <-- X */
180187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	blkcpy(B, X, 128 * r);
181187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root}
182187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
183187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root/**
184187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
185187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
186187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * p, buflen) and write the result into buf.  The parameters r, p, and buflen
187187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N
188187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * must be a power of 2.
189187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root *
190187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root * Return 0 on success; or -1 on error.
191187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root */
192187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootint
193187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rootcrypto_scrypt(const uint8_t * passwd, size_t passwdlen,
194187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root    const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
195187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root    uint8_t * buf, size_t buflen)
196187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root{
197187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	void * B0, * V0, * XY0;
198187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint8_t * B;
199187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint32_t * V;
200187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint32_t * XY;
201187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	uint32_t i;
202187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
203187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* Sanity-check parameters. */
204187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#if SIZE_MAX > UINT32_MAX
205187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
206187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		errno = EFBIG;
207187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err0;
208187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	}
209187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
210187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
211187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		errno = EFBIG;
212187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err0;
213187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	}
214187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if (((N & (N - 1)) != 0) || (N == 0)) {
215187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		errno = EINVAL;
216187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err0;
217187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	}
218187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if ((r > SIZE_MAX / 128 / p) ||
219187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#if SIZE_MAX / 256 <= UINT32_MAX
220187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	    (r > SIZE_MAX / 256) ||
221187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
222187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	    (N > SIZE_MAX / 128 / r)) {
223187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		errno = ENOMEM;
224187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err0;
225187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	}
226187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
227187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* Allocate memory. */
228187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#ifdef HAVE_POSIX_MEMALIGN
229187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
230187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err0;
231187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	B = (uint8_t *)(B0);
232187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
233187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err1;
234187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	XY = (uint32_t *)(XY0);
235187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#ifndef MAP_ANON
236187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
237187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err2;
238187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	V = (uint32_t *)(V0);
239187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
240187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#else
241187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if ((B0 = malloc(128 * r * p + 63)) == NULL)
242187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err0;
243187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
244187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
245187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err1;
246187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
247187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#ifndef MAP_ANON
248187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if ((V0 = malloc(128 * r * N + 63)) == NULL)
249187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err2;
250187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
251187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
252187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
253187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#ifdef MAP_ANON
254187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
255187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#ifdef MAP_NOCORE
256187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	    MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
257187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#else
258187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	    MAP_ANON | MAP_PRIVATE,
259187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
260187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	    -1, 0)) == MAP_FAILED)
261187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err2;
262187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	V = (uint32_t *)(V0);
263187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
264187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
265187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
266187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#ifdef USE_OPENSSL_PBKDF2
267187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
268187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#else
269187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
270187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
271187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
272187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* 2: for i = 0 to p - 1 do */
273187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	for (i = 0; i < p; i++) {
274187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		/* 3: B_i <-- MF(B_i, N) */
275187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		smix(&B[i * 128 * r], r, N, V, XY);
276187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	}
277187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
278187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
279187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#ifdef USE_OPENSSL_PBKDF2
280187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
281187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#else
282187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
283187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
284187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
285187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* Free memory. */
286187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#ifdef MAP_ANON
287187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	if (munmap(V0, 128 * r * N))
288187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root		goto err2;
289187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#else
290187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	free(V0);
291187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root#endif
292187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	free(XY0);
293187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	free(B0);
294187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
295187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* Success! */
296187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	return (0);
297187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root
298187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rooterr2:
299187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	free(XY0);
300187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rooterr1:
301187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	free(B0);
302187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Rooterr0:
303187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	/* Failure! */
304187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root	return (-1);
305187f492d9d783d53893c3dea07c0b14841ba61f8Kenny Root}
306