15fd6d3161cc7407718c7e230f94db421543273b8Kenny Root/*- 25fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * Copyright 2009 Colin Percival 35fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * All rights reserved. 45fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * 55fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * Redistribution and use in source and binary forms, with or without 65fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * modification, are permitted provided that the following conditions 75fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * are met: 85fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * 1. Redistributions of source code must retain the above copyright 95fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * notice, this list of conditions and the following disclaimer. 105fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * 2. Redistributions in binary form must reproduce the above copyright 115fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * notice, this list of conditions and the following disclaimer in the 125fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * documentation and/or other materials provided with the distribution. 135fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * 145fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 155fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 165fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 175fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 185fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 195fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 205fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 215fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 225fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 235fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 245fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * SUCH DAMAGE. 255fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * 265fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * This file was originally written by Colin Percival as part of the Tarsnap 275fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * online backup system. 285fd6d3161cc7407718c7e230f94db421543273b8Kenny Root */ 295fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include "scrypt_platform.h" 305fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 315fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include <sys/types.h> 325fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include <sys/mman.h> 335fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 345fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include <emmintrin.h> 355fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include <errno.h> 365fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include <stdint.h> 375fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include <stdlib.h> 385fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include <string.h> 395fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 40e470637963d50a324984bd11da04a60fc6980c12Kenny Root#ifdef USE_OPENSSL_PBKDF2 41e470637963d50a324984bd11da04a60fc6980c12Kenny Root#include <openssl/evp.h> 42e470637963d50a324984bd11da04a60fc6980c12Kenny Root#else 435fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include "sha256.h" 44e470637963d50a324984bd11da04a60fc6980c12Kenny Root#endif 455fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include "sysendian.h" 465fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 475fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#include "crypto_scrypt.h" 485fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 495fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic void blkcpy(void *, void *, size_t); 505fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic void blkxor(void *, void *, size_t); 515fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic void salsa20_8(__m128i *); 525fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic void blockmix_salsa8(__m128i *, __m128i *, __m128i *, size_t); 535fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic uint64_t integerify(void *, size_t); 545fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic void smix(uint8_t *, size_t, uint64_t, void *, void *); 555fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 565fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic void 575fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootblkcpy(void * dest, void * src, size_t len) 585fd6d3161cc7407718c7e230f94db421543273b8Kenny Root{ 595fd6d3161cc7407718c7e230f94db421543273b8Kenny Root __m128i * D = dest; 605fd6d3161cc7407718c7e230f94db421543273b8Kenny Root __m128i * S = src; 615fd6d3161cc7407718c7e230f94db421543273b8Kenny Root size_t L = len / 16; 625fd6d3161cc7407718c7e230f94db421543273b8Kenny Root size_t i; 635fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 645fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (i = 0; i < L; i++) 655fd6d3161cc7407718c7e230f94db421543273b8Kenny Root D[i] = S[i]; 665fd6d3161cc7407718c7e230f94db421543273b8Kenny Root} 675fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 685fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic void 695fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootblkxor(void * dest, void * src, size_t len) 705fd6d3161cc7407718c7e230f94db421543273b8Kenny Root{ 715fd6d3161cc7407718c7e230f94db421543273b8Kenny Root __m128i * D = dest; 725fd6d3161cc7407718c7e230f94db421543273b8Kenny Root __m128i * S = src; 735fd6d3161cc7407718c7e230f94db421543273b8Kenny Root size_t L = len / 16; 745fd6d3161cc7407718c7e230f94db421543273b8Kenny Root size_t i; 755fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 765fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (i = 0; i < L; i++) 775fd6d3161cc7407718c7e230f94db421543273b8Kenny Root D[i] = _mm_xor_si128(D[i], S[i]); 785fd6d3161cc7407718c7e230f94db421543273b8Kenny Root} 795fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 805fd6d3161cc7407718c7e230f94db421543273b8Kenny Root/** 815fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * salsa20_8(B): 825fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * Apply the salsa20/8 core to the provided block. 835fd6d3161cc7407718c7e230f94db421543273b8Kenny Root */ 845fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic void 855fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootsalsa20_8(__m128i B[4]) 865fd6d3161cc7407718c7e230f94db421543273b8Kenny Root{ 875fd6d3161cc7407718c7e230f94db421543273b8Kenny Root __m128i X0, X1, X2, X3; 885fd6d3161cc7407718c7e230f94db421543273b8Kenny Root __m128i T; 895fd6d3161cc7407718c7e230f94db421543273b8Kenny Root size_t i; 905fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 915fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X0 = B[0]; 925fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X1 = B[1]; 935fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X2 = B[2]; 945fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X3 = B[3]; 955fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 965fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (i = 0; i < 8; i += 2) { 975fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* Operate on "columns". */ 985fd6d3161cc7407718c7e230f94db421543273b8Kenny Root T = _mm_add_epi32(X0, X3); 995fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 7)); 1005fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 25)); 1015fd6d3161cc7407718c7e230f94db421543273b8Kenny Root T = _mm_add_epi32(X1, X0); 1025fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9)); 1035fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23)); 1045fd6d3161cc7407718c7e230f94db421543273b8Kenny Root T = _mm_add_epi32(X2, X1); 1055fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 13)); 1065fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 19)); 1075fd6d3161cc7407718c7e230f94db421543273b8Kenny Root T = _mm_add_epi32(X3, X2); 1085fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18)); 1095fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14)); 1105fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1115fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* Rearrange data. */ 1125fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X1 = _mm_shuffle_epi32(X1, 0x93); 1135fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X2 = _mm_shuffle_epi32(X2, 0x4E); 1145fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X3 = _mm_shuffle_epi32(X3, 0x39); 1155fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1165fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* Operate on "rows". */ 1175fd6d3161cc7407718c7e230f94db421543273b8Kenny Root T = _mm_add_epi32(X0, X1); 1185fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 7)); 1195fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 25)); 1205fd6d3161cc7407718c7e230f94db421543273b8Kenny Root T = _mm_add_epi32(X3, X0); 1215fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9)); 1225fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23)); 1235fd6d3161cc7407718c7e230f94db421543273b8Kenny Root T = _mm_add_epi32(X2, X3); 1245fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 13)); 1255fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 19)); 1265fd6d3161cc7407718c7e230f94db421543273b8Kenny Root T = _mm_add_epi32(X1, X2); 1275fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18)); 1285fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14)); 1295fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1305fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* Rearrange data. */ 1315fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X1 = _mm_shuffle_epi32(X1, 0x39); 1325fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X2 = _mm_shuffle_epi32(X2, 0x4E); 1335fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X3 = _mm_shuffle_epi32(X3, 0x93); 1345fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 1355fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1365fd6d3161cc7407718c7e230f94db421543273b8Kenny Root B[0] = _mm_add_epi32(B[0], X0); 1375fd6d3161cc7407718c7e230f94db421543273b8Kenny Root B[1] = _mm_add_epi32(B[1], X1); 1385fd6d3161cc7407718c7e230f94db421543273b8Kenny Root B[2] = _mm_add_epi32(B[2], X2); 1395fd6d3161cc7407718c7e230f94db421543273b8Kenny Root B[3] = _mm_add_epi32(B[3], X3); 1405fd6d3161cc7407718c7e230f94db421543273b8Kenny Root} 1415fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1425fd6d3161cc7407718c7e230f94db421543273b8Kenny Root/** 1435fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * blockmix_salsa8(Bin, Bout, X, r): 1445fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r 1455fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * bytes in length; the output Bout must also be the same size. The 1465fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * temporary space X must be 64 bytes. 1475fd6d3161cc7407718c7e230f94db421543273b8Kenny Root */ 1485fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic void 1495fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootblockmix_salsa8(__m128i * Bin, __m128i * Bout, __m128i * X, size_t r) 1505fd6d3161cc7407718c7e230f94db421543273b8Kenny Root{ 1515fd6d3161cc7407718c7e230f94db421543273b8Kenny Root size_t i; 1525fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1535fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 1: X <-- B_{2r - 1} */ 1545fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blkcpy(X, &Bin[8 * r - 4], 64); 1555fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1565fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 2: for i = 0 to 2r - 1 do */ 1575fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (i = 0; i < r; i++) { 1585fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 3: X <-- H(X \xor B_i) */ 1595fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blkxor(X, &Bin[i * 8], 64); 1605fd6d3161cc7407718c7e230f94db421543273b8Kenny Root salsa20_8(X); 1615fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1625fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 4: Y_i <-- X */ 1635fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 1645fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blkcpy(&Bout[i * 4], X, 64); 1655fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1665fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 3: X <-- H(X \xor B_i) */ 1675fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blkxor(X, &Bin[i * 8 + 4], 64); 1685fd6d3161cc7407718c7e230f94db421543273b8Kenny Root salsa20_8(X); 1695fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1705fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 4: Y_i <-- X */ 1715fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 1725fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blkcpy(&Bout[(r + i) * 4], X, 64); 1735fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 1745fd6d3161cc7407718c7e230f94db421543273b8Kenny Root} 1755fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1765fd6d3161cc7407718c7e230f94db421543273b8Kenny Root/** 1775fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * integerify(B, r): 1785fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * Return the result of parsing B_{2r-1} as a little-endian integer. 1795fd6d3161cc7407718c7e230f94db421543273b8Kenny Root */ 1805fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic uint64_t 1815fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootintegerify(void * B, size_t r) 1825fd6d3161cc7407718c7e230f94db421543273b8Kenny Root{ 1835fd6d3161cc7407718c7e230f94db421543273b8Kenny Root uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64); 1845fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1855fd6d3161cc7407718c7e230f94db421543273b8Kenny Root return (((uint64_t)(X[13]) << 32) + X[0]); 1865fd6d3161cc7407718c7e230f94db421543273b8Kenny Root} 1875fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 1885fd6d3161cc7407718c7e230f94db421543273b8Kenny Root/** 1895fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * smix(B, r, N, V, XY): 1905fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; 1915fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * the temporary storage V must be 128rN bytes in length; the temporary 1925fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * storage XY must be 256r + 64 bytes in length. The value N must be a 1935fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a 1945fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * multiple of 64 bytes. 1955fd6d3161cc7407718c7e230f94db421543273b8Kenny Root */ 1965fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootstatic void 1975fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootsmix(uint8_t * B, size_t r, uint64_t N, void * V, void * XY) 1985fd6d3161cc7407718c7e230f94db421543273b8Kenny Root{ 1995fd6d3161cc7407718c7e230f94db421543273b8Kenny Root __m128i * X = XY; 2005fd6d3161cc7407718c7e230f94db421543273b8Kenny Root __m128i * Y = (void *)((uintptr_t)(XY) + 128 * r); 2015fd6d3161cc7407718c7e230f94db421543273b8Kenny Root __m128i * Z = (void *)((uintptr_t)(XY) + 256 * r); 2025fd6d3161cc7407718c7e230f94db421543273b8Kenny Root uint32_t * X32 = (void *)X; 2035fd6d3161cc7407718c7e230f94db421543273b8Kenny Root uint64_t i, j; 2045fd6d3161cc7407718c7e230f94db421543273b8Kenny Root size_t k; 2055fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2065fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 1: X <-- B */ 2075fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (k = 0; k < 2 * r; k++) { 2085fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (i = 0; i < 16; i++) { 2095fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X32[k * 16 + i] = 2105fd6d3161cc7407718c7e230f94db421543273b8Kenny Root le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]); 2115fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 2125fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 2135fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2145fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 2: for i = 0 to N - 1 do */ 2155fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (i = 0; i < N; i += 2) { 2165fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 3: V_i <-- X */ 2175fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r); 2185fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2195fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 4: X <-- H(X) */ 2205fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blockmix_salsa8(X, Y, Z, r); 2215fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2225fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 3: V_i <-- X */ 2235fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r), 2245fd6d3161cc7407718c7e230f94db421543273b8Kenny Root Y, 128 * r); 2255fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2265fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 4: X <-- H(X) */ 2275fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blockmix_salsa8(Y, X, Z, r); 2285fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 2295fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2305fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 6: for i = 0 to N - 1 do */ 2315fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (i = 0; i < N; i += 2) { 2325fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 7: j <-- Integerify(X) mod N */ 2335fd6d3161cc7407718c7e230f94db421543273b8Kenny Root j = integerify(X, r) & (N - 1); 2345fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2355fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 8: X <-- H(X \xor V_j) */ 2365fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r); 2375fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blockmix_salsa8(X, Y, Z, r); 2385fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2395fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 7: j <-- Integerify(X) mod N */ 2405fd6d3161cc7407718c7e230f94db421543273b8Kenny Root j = integerify(Y, r) & (N - 1); 2415fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2425fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 8: X <-- H(X \xor V_j) */ 2435fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r); 2445fd6d3161cc7407718c7e230f94db421543273b8Kenny Root blockmix_salsa8(Y, X, Z, r); 2455fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 2465fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2475fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 10: B' <-- X */ 2485fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (k = 0; k < 2 * r; k++) { 2495fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (i = 0; i < 16; i++) { 2505fd6d3161cc7407718c7e230f94db421543273b8Kenny Root le32enc(&B[(k * 16 + (i * 5 % 16)) * 4], 2515fd6d3161cc7407718c7e230f94db421543273b8Kenny Root X32[k * 16 + i]); 2525fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 2535fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 2545fd6d3161cc7407718c7e230f94db421543273b8Kenny Root} 2555fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2565fd6d3161cc7407718c7e230f94db421543273b8Kenny Root/** 2575fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 2585fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 2595fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * p, buflen) and write the result into buf. The parameters r, p, and buflen 2605fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 2615fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * must be a power of 2 greater than 1. 2625fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * 2635fd6d3161cc7407718c7e230f94db421543273b8Kenny Root * Return 0 on success; or -1 on error. 2645fd6d3161cc7407718c7e230f94db421543273b8Kenny Root */ 2655fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootint 2665fd6d3161cc7407718c7e230f94db421543273b8Kenny Rootcrypto_scrypt(const uint8_t * passwd, size_t passwdlen, 2675fd6d3161cc7407718c7e230f94db421543273b8Kenny Root const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p, 2685fd6d3161cc7407718c7e230f94db421543273b8Kenny Root uint8_t * buf, size_t buflen) 2695fd6d3161cc7407718c7e230f94db421543273b8Kenny Root{ 2705fd6d3161cc7407718c7e230f94db421543273b8Kenny Root void * B0, * V0, * XY0; 2715fd6d3161cc7407718c7e230f94db421543273b8Kenny Root uint8_t * B; 2725fd6d3161cc7407718c7e230f94db421543273b8Kenny Root uint32_t * V; 2735fd6d3161cc7407718c7e230f94db421543273b8Kenny Root uint32_t * XY; 2745fd6d3161cc7407718c7e230f94db421543273b8Kenny Root uint32_t i; 2755fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 2765fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* Sanity-check parameters. */ 2775fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#if SIZE_MAX > UINT32_MAX 2785fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { 2795fd6d3161cc7407718c7e230f94db421543273b8Kenny Root errno = EFBIG; 2805fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err0; 2815fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 2825fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#endif 2835fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { 2845fd6d3161cc7407718c7e230f94db421543273b8Kenny Root errno = EFBIG; 2855fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err0; 2865fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 2875fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if (((N & (N - 1)) != 0) || (N == 0)) { 2885fd6d3161cc7407718c7e230f94db421543273b8Kenny Root errno = EINVAL; 2895fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err0; 2905fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 2915fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if ((r > SIZE_MAX / 128 / p) || 2925fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#if SIZE_MAX / 256 <= UINT32_MAX 2935fd6d3161cc7407718c7e230f94db421543273b8Kenny Root (r > (SIZE_MAX - 64) / 256) || 2945fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#endif 2955fd6d3161cc7407718c7e230f94db421543273b8Kenny Root (N > SIZE_MAX / 128 / r)) { 2965fd6d3161cc7407718c7e230f94db421543273b8Kenny Root errno = ENOMEM; 2975fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err0; 2985fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 2995fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 3005fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* Allocate memory. */ 3015fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#ifdef HAVE_POSIX_MEMALIGN 3025fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0) 3035fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err0; 3045fd6d3161cc7407718c7e230f94db421543273b8Kenny Root B = (uint8_t *)(B0); 3055fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0) 3065fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err1; 3075fd6d3161cc7407718c7e230f94db421543273b8Kenny Root XY = (uint32_t *)(XY0); 3085fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#ifndef MAP_ANON 3095fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0) 3105fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err2; 3115fd6d3161cc7407718c7e230f94db421543273b8Kenny Root V = (uint32_t *)(V0); 3125fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#endif 3135fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#else 3145fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if ((B0 = malloc(128 * r * p + 63)) == NULL) 3155fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err0; 3165fd6d3161cc7407718c7e230f94db421543273b8Kenny Root B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63)); 3175fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if ((XY0 = malloc(256 * r + 64 + 63)) == NULL) 3185fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err1; 3195fd6d3161cc7407718c7e230f94db421543273b8Kenny Root XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63)); 3205fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#ifndef MAP_ANON 3215fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if ((V0 = malloc(128 * r * N + 63)) == NULL) 3225fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err2; 3235fd6d3161cc7407718c7e230f94db421543273b8Kenny Root V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63)); 3245fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#endif 3255fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#endif 3265fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#ifdef MAP_ANON 3275fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE, 3285fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#ifdef MAP_NOCORE 3295fd6d3161cc7407718c7e230f94db421543273b8Kenny Root MAP_ANON | MAP_PRIVATE | MAP_NOCORE, 3305fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#else 3315fd6d3161cc7407718c7e230f94db421543273b8Kenny Root MAP_ANON | MAP_PRIVATE, 3325fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#endif 3335fd6d3161cc7407718c7e230f94db421543273b8Kenny Root -1, 0)) == MAP_FAILED) 3345fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err2; 3355fd6d3161cc7407718c7e230f94db421543273b8Kenny Root V = (uint32_t *)(V0); 3365fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#endif 3375fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 3385fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ 339e470637963d50a324984bd11da04a60fc6980c12Kenny Root#ifdef USE_OPENSSL_PBKDF2 340e470637963d50a324984bd11da04a60fc6980c12Kenny Root PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B); 341e470637963d50a324984bd11da04a60fc6980c12Kenny Root#else 3425fd6d3161cc7407718c7e230f94db421543273b8Kenny Root PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); 343e470637963d50a324984bd11da04a60fc6980c12Kenny Root#endif 3445fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 3455fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 2: for i = 0 to p - 1 do */ 3465fd6d3161cc7407718c7e230f94db421543273b8Kenny Root for (i = 0; i < p; i++) { 3475fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 3: B_i <-- MF(B_i, N) */ 3485fd6d3161cc7407718c7e230f94db421543273b8Kenny Root smix(&B[i * 128 * r], r, N, V, XY); 3495fd6d3161cc7407718c7e230f94db421543273b8Kenny Root } 3505fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 3515fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ 352e470637963d50a324984bd11da04a60fc6980c12Kenny Root#ifdef USE_OPENSSL_PBKDF2 353e470637963d50a324984bd11da04a60fc6980c12Kenny Root PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf); 354e470637963d50a324984bd11da04a60fc6980c12Kenny Root#else 3555fd6d3161cc7407718c7e230f94db421543273b8Kenny Root PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); 356e470637963d50a324984bd11da04a60fc6980c12Kenny Root#endif 3575fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 3585fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* Free memory. */ 3595fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#ifdef MAP_ANON 3605fd6d3161cc7407718c7e230f94db421543273b8Kenny Root if (munmap(V0, 128 * r * N)) 3615fd6d3161cc7407718c7e230f94db421543273b8Kenny Root goto err2; 3625fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#else 3635fd6d3161cc7407718c7e230f94db421543273b8Kenny Root free(V0); 3645fd6d3161cc7407718c7e230f94db421543273b8Kenny Root#endif 3655fd6d3161cc7407718c7e230f94db421543273b8Kenny Root free(XY0); 3665fd6d3161cc7407718c7e230f94db421543273b8Kenny Root free(B0); 3675fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 3685fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* Success! */ 3695fd6d3161cc7407718c7e230f94db421543273b8Kenny Root return (0); 3705fd6d3161cc7407718c7e230f94db421543273b8Kenny Root 3715fd6d3161cc7407718c7e230f94db421543273b8Kenny Rooterr2: 3725fd6d3161cc7407718c7e230f94db421543273b8Kenny Root free(XY0); 3735fd6d3161cc7407718c7e230f94db421543273b8Kenny Rooterr1: 3745fd6d3161cc7407718c7e230f94db421543273b8Kenny Root free(B0); 3755fd6d3161cc7407718c7e230f94db421543273b8Kenny Rooterr0: 3765fd6d3161cc7407718c7e230f94db421543273b8Kenny Root /* Failure! */ 3775fd6d3161cc7407718c7e230f94db421543273b8Kenny Root return (-1); 3785fd6d3161cc7407718c7e230f94db421543273b8Kenny Root} 379