2 * Copyright 2009 Colin Percival
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * This file was originally written by Colin Percival as part of the Tarsnap
27 * online backup system.
29 #include "scrypt_platform.h"
31 #include <sys/types.h>
39 #include "cpusupport.h"
43 #include "crypto_scrypt_smix.h"
44 #include "crypto_scrypt_smix_sse2.h"
46 #include "crypto_scrypt.h"
48 static void (*smix_func
)(uint8_t *, size_t, uint64_t, void *, void *) = NULL
;
51 * _crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen, smix):
52 * Perform the requested scrypt computation, using ${smix} as the smix routine.
55 _crypto_scrypt(const uint8_t * passwd
, size_t passwdlen
,
56 const uint8_t * salt
, size_t saltlen
, uint64_t N
, uint32_t _r
, uint32_t _p
,
57 uint8_t * buf
, size_t buflen
,
58 void (*smix
)(uint8_t *, size_t, uint64_t, void *, void *))
60 void * B0
, * V0
, * XY0
;
64 size_t r
= _r
, p
= _p
;
67 /* Sanity-check parameters. */
68 #if SIZE_MAX > UINT32_MAX
69 if (buflen
> (((uint64_t)(1) << 32) - 1) * 32) {
74 if ((uint64_t)(r
) * (uint64_t)(p
) >= (1 << 30)) {
78 if (((N
& (N
- 1)) != 0) || (N
< 2)) {
82 if ((r
> SIZE_MAX
/ 128 / p
) ||
83 #if SIZE_MAX / 256 <= UINT32_MAX
84 (r
> (SIZE_MAX
- 64) / 256) ||
86 (N
> SIZE_MAX
/ 128 / r
)) {
91 /* Allocate memory. */
92 #ifdef HAVE_POSIX_MEMALIGN
93 if ((errno
= posix_memalign(&B0
, 64, 128 * r
* p
)) != 0)
96 if ((errno
= posix_memalign(&XY0
, 64, 256 * r
+ 64)) != 0)
98 XY
= (uint32_t *)(XY0
);
99 #if !defined(MAP_ANON) || !defined(HAVE_MMAP)
100 if ((errno
= posix_memalign(&V0
, 64, (size_t)(128 * r
* N
))) != 0)
102 V
= (uint32_t *)(V0
);
105 if ((B0
= malloc(128 * r
* p
+ 63)) == NULL
)
107 B
= (uint8_t *)(((uintptr_t)(B0
) + 63) & ~ (uintptr_t)(63));
108 if ((XY0
= malloc(256 * r
+ 64 + 63)) == NULL
)
110 XY
= (uint32_t *)(((uintptr_t)(XY0
) + 63) & ~ (uintptr_t)(63));
111 #if !defined(MAP_ANON) || !defined(HAVE_MMAP)
112 if ((V0
= malloc(128 * r
* N
+ 63)) == NULL
)
114 V
= (uint32_t *)(((uintptr_t)(V0
) + 63) & ~ (uintptr_t)(63));
117 #if defined(MAP_ANON) && defined(HAVE_MMAP)
118 if ((V0
= mmap(NULL
, 128 * r
* N
, PROT_READ
| PROT_WRITE
,
120 MAP_ANON
| MAP_PRIVATE
| MAP_NOCORE
,
122 MAP_ANON
| MAP_PRIVATE
,
124 -1, 0)) == MAP_FAILED
)
126 V
= (uint32_t *)(V0
);
129 /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
130 PBKDF2_SHA256(passwd
, passwdlen
, salt
, saltlen
, 1, B
, p
* 128 * r
);
132 /* 2: for i = 0 to p - 1 do */
133 for (i
= 0; i
< p
; i
++) {
134 /* 3: B_i <-- MF(B_i, N) */
135 (smix
)(&B
[i
* 128 * r
], r
, N
, V
, XY
);
138 /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
139 PBKDF2_SHA256(passwd
, passwdlen
, B
, p
* 128 * r
, 1, buf
, buflen
);
142 #if defined(MAP_ANON) && defined(HAVE_MMAP)
143 if (munmap(V0
, 128 * r
* N
))
164 static struct scrypt_test
{
170 uint8_t result
[TESTLEN
];
172 .passwd
= "pleaseletmein",
173 .salt
= "SodiumChloride",
178 0x25, 0xa9, 0xfa, 0x20, 0x7f, 0x87, 0xca, 0x09,
179 0xa4, 0xef, 0x8b, 0x9f, 0x77, 0x7a, 0xca, 0x16,
180 0xbe, 0xb7, 0x84, 0xae, 0x18, 0x30, 0xbf, 0xbf,
181 0xd3, 0x83, 0x25, 0xaa, 0xbb, 0x93, 0x77, 0xdf,
182 0x1b, 0xa7, 0x84, 0xd7, 0x46, 0xea, 0x27, 0x3b,
183 0xf5, 0x16, 0xa4, 0x6f, 0xbf, 0xac, 0xf5, 0x11,
184 0xc5, 0xbe, 0xba, 0x4c, 0x4a, 0xb3, 0xac, 0xc7,
185 0xfa, 0x6f, 0x46, 0x0b, 0x6c, 0x0f, 0x47, 0x7b,
190 testsmix(void (*smix
)(uint8_t *, size_t, uint64_t, void *, void *))
192 uint8_t hbuf
[TESTLEN
];
194 /* Perform the computation. */
196 (const uint8_t *)testcase
.passwd
, strlen(testcase
.passwd
),
197 (const uint8_t *)testcase
.salt
, strlen(testcase
.salt
),
198 testcase
.N
, testcase
.r
, testcase
.p
, hbuf
, TESTLEN
, smix
))
202 return (memcmp(testcase
.result
, hbuf
, TESTLEN
));
209 #ifdef CPUSUPPORT_X86_SSE2
210 /* If we're running on an SSE2-capable CPU, try that code. */
211 if (cpusupport_x86_sse2()) {
212 /* If SSE2ized smix works, use it. */
213 if (!testsmix(crypto_scrypt_smix_sse2
)) {
214 smix_func
= crypto_scrypt_smix_sse2
;
217 warn0("Disabling broken SSE2 scrypt support - please report bug!");
221 /* If generic smix works, use it. */
222 if (!testsmix(crypto_scrypt_smix
)) {
223 smix_func
= crypto_scrypt_smix
;
226 warn0("Generic scrypt code is broken - please report bug!");
228 /* If we get here, something really bad happened. */
233 * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
234 * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
235 * p, buflen) and write the result into buf. The parameters r, p, and buflen
236 * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
237 * must be a power of 2 greater than 1.
239 * Return 0 on success; or -1 on error.
242 crypto_scrypt(const uint8_t * passwd
, size_t passwdlen
,
243 const uint8_t * salt
, size_t saltlen
, uint64_t N
, uint32_t _r
, uint32_t _p
,
244 uint8_t * buf
, size_t buflen
)
247 if (smix_func
== NULL
)
250 return (_crypto_scrypt(passwd
, passwdlen
, salt
, saltlen
, N
, _r
, _p
,
251 buf
, buflen
, smix_func
));
This page took 0.030479 seconds and 4 git commands to generate.