scrypty 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ ext/*.o
19
+ ext/*.so
20
+ ext/extconf.h
21
+ ext/mkmf.log
22
+ ext/Makefile
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in scrypty.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Jeremy Stephens
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # Scrypty
2
+
3
+ This is a Rubygem that uses the scrypt algorithm to encrypt/decrypt data.
4
+ The 'scrypt' gem only provides support for hashing passwords.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'scrypty'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install scrypty
19
+
20
+ ## Usage
21
+
22
+ The scrypt algorithm uses a few parameters to determine how to encrypt data:
23
+ * maxmem - use at most the specified number of bytes of RAM when computing the
24
+ derived encryption key (use 0 for unlimited)
25
+ * maxmemfrac - use at most the specified fraction of the available RAM for
26
+ computing the derived encryption key
27
+ * maxtime - spend at most maxtime seconds computing the derived encryption key
28
+ from the password
29
+
30
+ Example:
31
+
32
+ require 'scrypty'
33
+
34
+ data = "my data"
35
+ password = "secret"
36
+ maxmem = 0
37
+ maxmemfrac = 0.125
38
+ maxtime = 5.0
39
+
40
+ encrypted = Scrypty.encrypt(data, password, maxmem, maxmemfrac, maxtime)
41
+ puts "Encrypted data: #{encrypted.inspect}"
42
+ decrypted = Scrypty.decrypt(encrypted, password, maxmem, maxmemfrac, maxtime)
43
+ puts "Decrypted data: #{decrypted.inspect}"
44
+
45
+ ## Contributing
46
+
47
+ 1. Fork it
48
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
49
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
50
+ 4. Push to the branch (`git push origin my-new-feature`)
51
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,124 @@
1
+ /*-
2
+ * Copyright 2007-2009 Colin Percival
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions
7
+ * are met:
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.
13
+ *
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
24
+ * SUCH DAMAGE.
25
+ *
26
+ * This file was originally written by Colin Percival as part of the Tarsnap
27
+ * online backup system.
28
+ */
29
+ #include "scrypt_platform.h"
30
+
31
+ #include <stdint.h>
32
+ #include <stdlib.h>
33
+
34
+ #include <openssl/aes.h>
35
+
36
+ #include "sysendian.h"
37
+
38
+ #include "crypto_aesctr.h"
39
+
40
+ struct crypto_aesctr {
41
+ AES_KEY * key;
42
+ uint64_t nonce;
43
+ uint64_t bytectr;
44
+ uint8_t buf[16];
45
+ };
46
+
47
+ /**
48
+ * crypto_aesctr_init(key, nonce):
49
+ * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided
50
+ * expanded key and nonce. The key provided must remain valid for the
51
+ * lifetime of the stream.
52
+ */
53
+ struct crypto_aesctr *
54
+ crypto_aesctr_init(AES_KEY * key, uint64_t nonce)
55
+ {
56
+ struct crypto_aesctr * stream;
57
+
58
+ /* Allocate memory. */
59
+ if ((stream = malloc(sizeof(struct crypto_aesctr))) == NULL)
60
+ goto err0;
61
+
62
+ /* Initialize values. */
63
+ stream->key = key;
64
+ stream->nonce = nonce;
65
+ stream->bytectr = 0;
66
+
67
+ /* Success! */
68
+ return (stream);
69
+
70
+ err0:
71
+ /* Failure! */
72
+ return (NULL);
73
+ }
74
+
75
+ /**
76
+ * crypto_aesctr_stream(stream, inbuf, outbuf, buflen):
77
+ * Generate the next ${buflen} bytes of the AES-CTR stream and xor them with
78
+ * bytes from ${inbuf}, writing the result into ${outbuf}. If the buffers
79
+ * ${inbuf} and ${outbuf} overlap, they must be identical.
80
+ */
81
+ void
82
+ crypto_aesctr_stream(struct crypto_aesctr * stream, const uint8_t * inbuf,
83
+ uint8_t * outbuf, size_t buflen)
84
+ {
85
+ uint8_t pblk[16];
86
+ size_t pos;
87
+ int bytemod;
88
+
89
+ for (pos = 0; pos < buflen; pos++) {
90
+ /* How far through the buffer are we? */
91
+ bytemod = stream->bytectr % 16;
92
+
93
+ /* Generate a block of cipherstream if needed. */
94
+ if (bytemod == 0) {
95
+ be64enc(pblk, stream->nonce);
96
+ be64enc(pblk + 8, stream->bytectr / 16);
97
+ AES_encrypt(pblk, stream->buf, stream->key);
98
+ }
99
+
100
+ /* Encrypt a byte. */
101
+ outbuf[pos] = inbuf[pos] ^ stream->buf[bytemod];
102
+
103
+ /* Move to the next byte of cipherstream. */
104
+ stream->bytectr += 1;
105
+ }
106
+ }
107
+
108
+ /**
109
+ * crypto_aesctr_free(stream):
110
+ * Free the provided stream object.
111
+ */
112
+ void
113
+ crypto_aesctr_free(struct crypto_aesctr * stream)
114
+ {
115
+ int i;
116
+
117
+ /* Zero potentially sensitive information. */
118
+ for (i = 0; i < 16; i++)
119
+ stream->buf[i] = 0;
120
+ stream->bytectr = stream->nonce = 0;
121
+
122
+ /* Free the stream. */
123
+ free(stream);
124
+ }
@@ -0,0 +1,59 @@
1
+ /*-
2
+ * Copyright 2009 Colin Percival
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions
7
+ * are met:
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.
13
+ *
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
24
+ * SUCH DAMAGE.
25
+ *
26
+ * This file was originally written by Colin Percival as part of the Tarsnap
27
+ * online backup system.
28
+ */
29
+ #ifndef _CRYPTO_AESCTR_H_
30
+ #define _CRYPTO_AESCTR_H_
31
+
32
+ #include <stdint.h>
33
+
34
+ #include <openssl/aes.h>
35
+
36
+ /**
37
+ * crypto_aesctr_init(key, nonce):
38
+ * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided
39
+ * expanded key and nonce. The key provided must remain valid for the
40
+ * lifetime of the stream.
41
+ */
42
+ struct crypto_aesctr * crypto_aesctr_init(AES_KEY *, uint64_t);
43
+
44
+ /**
45
+ * crypto_aesctr_stream(stream, inbuf, outbuf, buflen):
46
+ * Generate the next ${buflen} bytes of the AES-CTR stream and xor them with
47
+ * bytes from ${inbuf}, writing the result into ${outbuf}. If the buffers
48
+ * ${inbuf} and ${outbuf} overlap, they must be identical.
49
+ */
50
+ void crypto_aesctr_stream(struct crypto_aesctr *, const uint8_t *,
51
+ uint8_t *, size_t);
52
+
53
+ /**
54
+ * crypto_aesctr_free(stream):
55
+ * Free the provided stream object.
56
+ */
57
+ void crypto_aesctr_free(struct crypto_aesctr *);
58
+
59
+ #endif /* !_CRYPTO_AESCTR_H_ */
@@ -0,0 +1,338 @@
1
+ /*-
2
+ * Copyright 2009 Colin Percival
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions
7
+ * are met:
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.
13
+ *
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
24
+ * SUCH DAMAGE.
25
+ *
26
+ * This file was originally written by Colin Percival as part of the Tarsnap
27
+ * online backup system.
28
+ */
29
+ #include "scrypt_platform.h"
30
+
31
+ #include <sys/types.h>
32
+ #include <sys/mman.h>
33
+
34
+ #include <errno.h>
35
+ #include <stdint.h>
36
+ #include <stdlib.h>
37
+ #include <string.h>
38
+
39
+ #include "sha256.h"
40
+ #include "sysendian.h"
41
+
42
+ #include "crypto_scrypt.h"
43
+
44
+ static void blkcpy(void *, void *, size_t);
45
+ static void blkxor(void *, void *, size_t);
46
+ static void salsa20_8(uint32_t[16]);
47
+ static void blockmix_salsa8(uint32_t *, uint32_t *, uint32_t *, size_t);
48
+ static uint64_t integerify(void *, size_t);
49
+ static void smix(uint8_t *, size_t, uint64_t, uint32_t *, uint32_t *);
50
+
51
+ static void
52
+ blkcpy(void * dest, void * src, size_t len)
53
+ {
54
+ size_t * D = dest;
55
+ size_t * S = src;
56
+ size_t L = len / sizeof(size_t);
57
+ size_t i;
58
+
59
+ for (i = 0; i < L; i++)
60
+ D[i] = S[i];
61
+ }
62
+
63
+ static void
64
+ blkxor(void * dest, void * src, size_t len)
65
+ {
66
+ size_t * D = dest;
67
+ size_t * S = src;
68
+ size_t L = len / sizeof(size_t);
69
+ size_t i;
70
+
71
+ for (i = 0; i < L; i++)
72
+ D[i] ^= S[i];
73
+ }
74
+
75
+ /**
76
+ * salsa20_8(B):
77
+ * Apply the salsa20/8 core to the provided block.
78
+ */
79
+ static void
80
+ salsa20_8(uint32_t B[16])
81
+ {
82
+ uint32_t x[16];
83
+ size_t i;
84
+
85
+ blkcpy(x, B, 64);
86
+ for (i = 0; i < 8; i += 2) {
87
+ #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
88
+ /* Operate on columns. */
89
+ x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
90
+ x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
91
+
92
+ x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
93
+ x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
94
+
95
+ x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
96
+ x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
97
+
98
+ x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
99
+ x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
100
+
101
+ /* Operate on rows. */
102
+ x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
103
+ x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
104
+
105
+ x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
106
+ x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
107
+
108
+ x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
109
+ x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
110
+
111
+ x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
112
+ x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
113
+ #undef R
114
+ }
115
+ for (i = 0; i < 16; i++)
116
+ B[i] += x[i];
117
+ }
118
+
119
+ /**
120
+ * blockmix_salsa8(Bin, Bout, X, r):
121
+ * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
122
+ * bytes in length; the output Bout must also be the same size. The
123
+ * temporary space X must be 64 bytes.
124
+ */
125
+ static void
126
+ blockmix_salsa8(uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)
127
+ {
128
+ size_t i;
129
+
130
+ /* 1: X <-- B_{2r - 1} */
131
+ blkcpy(X, &Bin[(2 * r - 1) * 16], 64);
132
+
133
+ /* 2: for i = 0 to 2r - 1 do */
134
+ for (i = 0; i < 2 * r; i += 2) {
135
+ /* 3: X <-- H(X \xor B_i) */
136
+ blkxor(X, &Bin[i * 16], 64);
137
+ salsa20_8(X);
138
+
139
+ /* 4: Y_i <-- X */
140
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
141
+ blkcpy(&Bout[i * 8], X, 64);
142
+
143
+ /* 3: X <-- H(X \xor B_i) */
144
+ blkxor(X, &Bin[i * 16 + 16], 64);
145
+ salsa20_8(X);
146
+
147
+ /* 4: Y_i <-- X */
148
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
149
+ blkcpy(&Bout[i * 8 + r * 16], X, 64);
150
+ }
151
+ }
152
+
153
+ /**
154
+ * integerify(B, r):
155
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
156
+ */
157
+ static uint64_t
158
+ integerify(void * B, size_t r)
159
+ {
160
+ uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64);
161
+
162
+ return (((uint64_t)(X[1]) << 32) + X[0]);
163
+ }
164
+
165
+ /**
166
+ * smix(B, r, N, V, XY):
167
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
168
+ * the temporary storage V must be 128rN bytes in length; the temporary
169
+ * storage XY must be 256r + 64 bytes in length. The value N must be a
170
+ * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
171
+ * multiple of 64 bytes.
172
+ */
173
+ static void
174
+ smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY)
175
+ {
176
+ uint32_t * X = XY;
177
+ uint32_t * Y = &XY[32 * r];
178
+ uint32_t * Z = &XY[64 * r];
179
+ uint64_t i;
180
+ uint64_t j;
181
+ size_t k;
182
+
183
+ /* 1: X <-- B */
184
+ for (k = 0; k < 32 * r; k++)
185
+ X[k] = le32dec(&B[4 * k]);
186
+
187
+ /* 2: for i = 0 to N - 1 do */
188
+ for (i = 0; i < N; i += 2) {
189
+ /* 3: V_i <-- X */
190
+ blkcpy(&V[i * (32 * r)], X, 128 * r);
191
+
192
+ /* 4: X <-- H(X) */
193
+ blockmix_salsa8(X, Y, Z, r);
194
+
195
+ /* 3: V_i <-- X */
196
+ blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r);
197
+
198
+ /* 4: X <-- H(X) */
199
+ blockmix_salsa8(Y, X, Z, r);
200
+ }
201
+
202
+ /* 6: for i = 0 to N - 1 do */
203
+ for (i = 0; i < N; i += 2) {
204
+ /* 7: j <-- Integerify(X) mod N */
205
+ j = integerify(X, r) & (N - 1);
206
+
207
+ /* 8: X <-- H(X \xor V_j) */
208
+ blkxor(X, &V[j * (32 * r)], 128 * r);
209
+ blockmix_salsa8(X, Y, Z, r);
210
+
211
+ /* 7: j <-- Integerify(X) mod N */
212
+ j = integerify(Y, r) & (N - 1);
213
+
214
+ /* 8: X <-- H(X \xor V_j) */
215
+ blkxor(Y, &V[j * (32 * r)], 128 * r);
216
+ blockmix_salsa8(Y, X, Z, r);
217
+ }
218
+
219
+ /* 10: B' <-- X */
220
+ for (k = 0; k < 32 * r; k++)
221
+ le32enc(&B[4 * k], X[k]);
222
+ }
223
+
224
+ /**
225
+ * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
226
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
227
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
228
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
229
+ * must be a power of 2 greater than 1.
230
+ *
231
+ * Return 0 on success; or -1 on error.
232
+ */
233
+ int
234
+ crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
235
+ const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
236
+ uint8_t * buf, size_t buflen)
237
+ {
238
+ void * B0, * V0, * XY0;
239
+ uint8_t * B;
240
+ uint32_t * V;
241
+ uint32_t * XY;
242
+ uint32_t i;
243
+
244
+ /* Sanity-check parameters. */
245
+ #if SIZE_MAX > UINT32_MAX
246
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
247
+ errno = EFBIG;
248
+ goto err0;
249
+ }
250
+ #endif
251
+ if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
252
+ errno = EFBIG;
253
+ goto err0;
254
+ }
255
+ if (((N & (N - 1)) != 0) || (N == 0)) {
256
+ errno = EINVAL;
257
+ goto err0;
258
+ }
259
+ if ((r > SIZE_MAX / 128 / p) ||
260
+ #if SIZE_MAX / 256 <= UINT32_MAX
261
+ (r > SIZE_MAX / 256) ||
262
+ #endif
263
+ (N > SIZE_MAX / 128 / r)) {
264
+ errno = ENOMEM;
265
+ goto err0;
266
+ }
267
+
268
+ /* Allocate memory. */
269
+ #ifdef HAVE_POSIX_MEMALIGN
270
+ if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
271
+ goto err0;
272
+ B = (uint8_t *)(B0);
273
+ if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
274
+ goto err1;
275
+ XY = (uint32_t *)(XY0);
276
+ #ifndef MAP_ANON
277
+ if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
278
+ goto err2;
279
+ V = (uint32_t *)(V0);
280
+ #endif
281
+ #else
282
+ if ((B0 = malloc(128 * r * p + 63)) == NULL)
283
+ goto err0;
284
+ B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
285
+ if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
286
+ goto err1;
287
+ XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
288
+ #ifndef MAP_ANON
289
+ if ((V0 = malloc(128 * r * N + 63)) == NULL)
290
+ goto err2;
291
+ V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
292
+ #endif
293
+ #endif
294
+ #ifdef MAP_ANON
295
+ if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
296
+ #ifdef MAP_NOCORE
297
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
298
+ #else
299
+ MAP_ANON | MAP_PRIVATE,
300
+ #endif
301
+ -1, 0)) == MAP_FAILED)
302
+ goto err2;
303
+ V = (uint32_t *)(V0);
304
+ #endif
305
+
306
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
307
+ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
308
+
309
+ /* 2: for i = 0 to p - 1 do */
310
+ for (i = 0; i < p; i++) {
311
+ /* 3: B_i <-- MF(B_i, N) */
312
+ smix(&B[i * 128 * r], r, N, V, XY);
313
+ }
314
+
315
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
316
+ PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
317
+
318
+ /* Free memory. */
319
+ #ifdef MAP_ANON
320
+ if (munmap(V0, 128 * r * N))
321
+ goto err2;
322
+ #else
323
+ free(V0);
324
+ #endif
325
+ free(XY0);
326
+ free(B0);
327
+
328
+ /* Success! */
329
+ return (0);
330
+
331
+ err2:
332
+ free(XY0);
333
+ err1:
334
+ free(B0);
335
+ err0:
336
+ /* Failure! */
337
+ return (-1);
338
+ }