scrypt 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ *.o
5
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --backtrace
@@ -0,0 +1,3 @@
1
+ 1.0.0 December 15, 2010
2
+ - Initial release.
3
+
data/COPYING ADDED
@@ -0,0 +1,28 @@
1
+ Copyright 2010 Patrick Hogan <pbhogan@gmail.com>
2
+
3
+ Original implementation of scrypt by Colin Percival.
4
+ This product includes software developed by Coda Hale.
5
+
6
+ All rights reserved.
7
+
8
+ Redistribution and use in source and binary forms, with or without
9
+ modification, are permitted provided that the following conditions
10
+ are met:
11
+ 1. Redistributions of source code must retain the above copyright
12
+ notice, this list of conditions and the following disclaimer.
13
+ 2. Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in the
15
+ documentation and/or other materials provided with the distribution.
16
+ 3. The name of the author may not be used to endorse or promote products
17
+ derived from this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem "rspec"
5
+ end
6
+
7
+ # Specify your gem's dependencies in scrypt.gemspec
8
+ gemspec
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ scrypt (1.0.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.2)
10
+ rspec (2.2.0)
11
+ rspec-core (~> 2.2)
12
+ rspec-expectations (~> 2.2)
13
+ rspec-mocks (~> 2.2)
14
+ rspec-core (2.2.1)
15
+ rspec-expectations (2.2.0)
16
+ diff-lcs (~> 1.1.2)
17
+ rspec-mocks (2.2.0)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ rspec
24
+ scrypt!
data/README ADDED
@@ -0,0 +1,19 @@
1
+ = scrypt
2
+
3
+ The scrypt key derivation function is designed to be far more secure against hardware brute-force attacks than alternative functions such as PBKDF2 or bcrypt.
4
+
5
+ * http://www.tarsnap.com/scrypt.html
6
+ * http://github.com/pbhogan/scrypt
7
+
8
+ == Why you should use scrypt
9
+
10
+ Coming soon.
11
+
12
+ == How to install bcrypt
13
+
14
+ gem install scrypt
15
+
16
+ == How to use scrypt
17
+
18
+ Coming soon. It works pretty similarly to ruby-bcrypt.
19
+
@@ -0,0 +1,42 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake'
5
+ require 'rake/clean'
6
+ require 'rake/rdoctask'
7
+ require 'rspec/core/rake_task'
8
+
9
+ task :default => [:compile, :spec]
10
+
11
+
12
+ desc 'Generate RDoc'
13
+ rd = Rake::RDocTask.new do |rdoc|
14
+ rdoc.rdoc_dir = 'doc/rdoc'
15
+ rdoc.options << '--title' << 'scrypt-ruby' << '--line-numbers' << '--inline-source' << '--main' << 'README'
16
+ rdoc.template = ENV['TEMPLATE'] if ENV['TEMPLATE']
17
+ rdoc.rdoc_files.include('README', 'COPYING', 'CHANGELOG', 'lib/**/*.rb')
18
+ end
19
+
20
+
21
+ desc "Run all specs"
22
+ RSpec::Core::RakeTask.new do |t|
23
+ rspec_opts = ['--colour','--backtrace']
24
+ end
25
+
26
+
27
+ desc "Clean native extension build files."
28
+ task :clean do
29
+ Dir.chdir('ext/mri') do
30
+ ruby "extconf.rb"
31
+ sh "make clean"
32
+ end
33
+ end
34
+
35
+
36
+ desc "Compile the native extension."
37
+ task :compile do
38
+ Dir.chdir('ext/mri') do
39
+ ruby "extconf.rb"
40
+ sh "make"
41
+ end
42
+ end
@@ -0,0 +1,104 @@
1
+ gem "rspec"
2
+
3
+ require "rake"
4
+ require 'rake/gempackagetask'
5
+ require 'rake/contrib/rubyforgepublisher'
6
+ require 'rake/clean'
7
+ require 'rake/rdoctask'
8
+ require "benchmark"
9
+ require "rspec/core/rake_task"
10
+
11
+ PKG_NAME = "scrypt-ruby"
12
+ PKG_VERSION = "2.1.2"
13
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
14
+ PKG_FILES = FileList[
15
+ '[A-Z]*',
16
+ 'lib/**/*.rb',
17
+ 'spec/**/*.rb',
18
+ 'ext/mri/*.c',
19
+ 'ext/mri/*.h',
20
+ 'ext/mri/*.rb'
21
+ ]
22
+ CLEAN.include(
23
+ "ext/mri/*.o",
24
+ "ext/mri/*.bundle",
25
+ "ext/mri/*.so"
26
+ )
27
+ CLOBBER.include(
28
+ "ext/mri/Makefile",
29
+ "doc/coverage",
30
+ "pkg"
31
+ )
32
+
33
+ task :default => [:spec]
34
+
35
+ desc "Run all specs"
36
+ RSpec::Core::RakeTask.new do |t|
37
+ rspec_opts = ['--colour','--backtrace']
38
+ end
39
+
40
+ desc 'Generate RDoc'
41
+ rd = Rake::RDocTask.new do |rdoc|
42
+ rdoc.rdoc_dir = 'doc/rdoc'
43
+ rdoc.options << '--title' << 'scrypt-ruby' << '--line-numbers' << '--inline-source' << '--main' << 'README'
44
+ rdoc.template = ENV['TEMPLATE'] if ENV['TEMPLATE']
45
+ rdoc.rdoc_files.include('README', 'COPYING', 'CHANGELOG', 'lib/**/*.rb')
46
+ end
47
+
48
+ spec = Gem::Specification.new do |s|
49
+ s.name = PKG_NAME
50
+ s.version = PKG_VERSION
51
+ s.summary = "scrypt password hashing algorithm."
52
+ s.description = <<-EOF
53
+ The scrypt key derivation function was originally developed for
54
+ use in the Tarsnap online backup system and is designed to be far
55
+ more secure against hardware brute-force attacks than
56
+ alternative functions such as PBKDF2 or bcrypt.
57
+ EOF
58
+
59
+ s.files = PKG_FILES.to_a
60
+ s.require_path = 'lib'
61
+
62
+ s.has_rdoc = true
63
+ s.rdoc_options = rd.options
64
+ s.extra_rdoc_files = rd.rdoc_files.to_a
65
+
66
+ s.extensions = FileList["ext/mri/extconf.rb"].to_a
67
+
68
+ s.authors = ["Patrick Hogan"]
69
+ s.email = "pbhogan@gmail.com"
70
+ s.homepage = "http://scrypt-ruby.rubyforge.org"
71
+ end
72
+
73
+ Rake::GemPackageTask.new(spec) do |pkg|
74
+ pkg.need_zip = true
75
+ pkg.need_tar = true
76
+ end
77
+
78
+ desc "Clean, then compile the extension that's native to the current Ruby compiler."
79
+ task :compile => 'compile:mri'
80
+
81
+ namespace :compile do
82
+ desc "CLean, then compile all extensions"
83
+ task :all => [:mri]
84
+
85
+ desc "Clean, then compile the MRI extension"
86
+ task :mri => :clean do
87
+ Dir.chdir('ext/mri') do
88
+ ruby "extconf.rb"
89
+ sh "make"
90
+ end
91
+ end
92
+ end
93
+
94
+ desc "Run a set of benchmarks on the compiled extension."
95
+ task :benchmark do
96
+ TESTS = 100
97
+ TEST_PWD = "this is a test"
98
+ require File.expand_path(File.join(File.dirname(__FILE__), "lib", "scrypt"))
99
+ Benchmark.bmbm do |results|
100
+ 4.upto(10) do |n|
101
+ results.report("cost #{n}:") { TESTS.times { scrypt::Password.create(TEST_PWD, :cost => n) } }
102
+ end
103
+ end
104
+ end
@@ -0,0 +1 @@
1
+ Autotest.add_discovery { "rspec2" }
@@ -0,0 +1,157 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /Users/pbhogan/.rvm/rubies/ree-1.8.7-2010.02/lib/ruby/1.8/i686-darwin10.4.0
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ exec_prefix = $(prefix)
11
+ prefix = $(DESTDIR)/Users/pbhogan/.rvm/rubies/ree-1.8.7-2010.02
12
+ sharedstatedir = $(prefix)/com
13
+ mandir = $(datarootdir)/man
14
+ psdir = $(docdir)
15
+ oldincludedir = $(DESTDIR)/usr/include
16
+ localedir = $(datarootdir)/locale
17
+ bindir = $(exec_prefix)/bin
18
+ libexecdir = $(exec_prefix)/libexec
19
+ sitedir = $(libdir)/ruby/site_ruby
20
+ htmldir = $(docdir)
21
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
22
+ includedir = $(prefix)/include
23
+ infodir = $(datarootdir)/info
24
+ vendorlibdir = $(vendordir)/$(ruby_version)
25
+ sysconfdir = $(prefix)/etc
26
+ libdir = $(exec_prefix)/lib
27
+ sbindir = $(exec_prefix)/sbin
28
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
29
+ docdir = $(datarootdir)/doc/$(PACKAGE)
30
+ dvidir = $(docdir)
31
+ vendordir = $(libdir)/ruby/vendor_ruby
32
+ datarootdir = $(prefix)/share
33
+ pdfdir = $(docdir)
34
+ archdir = $(rubylibdir)/$(arch)
35
+ sitearchdir = $(sitelibdir)/$(sitearch)
36
+ datadir = $(datarootdir)
37
+ localstatedir = $(prefix)/var
38
+ sitelibdir = $(sitedir)/$(ruby_version)
39
+
40
+ CC = gcc -Wall
41
+ LIBRUBY = $(LIBRUBY_A)
42
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
43
+ LIBRUBYARG_SHARED =
44
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
45
+
46
+ RUBY_EXTCONF_H =
47
+ CFLAGS = -fno-common -g -O2 -pipe -fno-common $(cflags)
48
+ INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
49
+ DEFS =
50
+ CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
51
+ CXXFLAGS = $(CFLAGS)
52
+ ldflags = -L.
53
+ dldflags =
54
+ archflag =
55
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
56
+ LDSHARED = cc -dynamic -bundle -undefined suppress -flat_namespace
57
+ AR = ar
58
+ EXEEXT =
59
+
60
+ RUBY_INSTALL_NAME = ruby
61
+ RUBY_SO_NAME = ruby
62
+ arch = i686-darwin10.4.0
63
+ sitearch = i686-darwin10.4.0
64
+ ruby_version = 1.8
65
+ ruby = /Users/pbhogan/.rvm/rubies/ree-1.8.7-2010.02/bin/ruby
66
+ RUBY = $(ruby)
67
+ RM = rm -f
68
+ MAKEDIRS = mkdir -p
69
+ INSTALL = /usr/bin/install -c
70
+ INSTALL_PROG = $(INSTALL) -m 0755
71
+ INSTALL_DATA = $(INSTALL) -m 644
72
+ COPY = cp
73
+
74
+ #### End of system configuration section. ####
75
+
76
+ preload =
77
+
78
+ libpath = . $(libdir)
79
+ LIBPATH = -L. -L$(libdir)
80
+ DEFFILE =
81
+
82
+ CLEANFILES = mkmf.log
83
+ DISTCLEANFILES =
84
+
85
+ extout =
86
+ extout_prefix =
87
+ target_prefix =
88
+ LOCAL_LIBS =
89
+ LIBS = -ldl -lobjc
90
+ SRCS = crypto_scrypt-ref.c memlimit.c scrypt_calibrate.c scrypt_ext.c scryptenc_cpuperf.c sha256.c
91
+ OBJS = crypto_scrypt-ref.o memlimit.o scrypt_calibrate.o scrypt_ext.o scryptenc_cpuperf.o sha256.o
92
+ TARGET = scrypt_ext
93
+ DLLIB = $(TARGET).bundle
94
+ EXTSTATIC =
95
+ STATIC_LIB =
96
+
97
+ BINDIR = $(bindir)
98
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
99
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
100
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
101
+
102
+ TARGET_SO = $(DLLIB)
103
+ CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
104
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
105
+
106
+ all: $(DLLIB)
107
+ static: $(STATIC_LIB)
108
+
109
+ clean:
110
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
111
+
112
+ distclean: clean
113
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
114
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
115
+
116
+ realclean: distclean
117
+ install: install-so install-rb
118
+
119
+ install-so: $(RUBYARCHDIR)
120
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
121
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
122
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
123
+ install-rb: pre-install-rb install-rb-default
124
+ install-rb-default: pre-install-rb-default
125
+ pre-install-rb: Makefile
126
+ pre-install-rb-default: Makefile
127
+ $(RUBYARCHDIR):
128
+ $(MAKEDIRS) $@
129
+
130
+ site-install: site-install-so site-install-rb
131
+ site-install-so: install-so
132
+ site-install-rb: install-rb
133
+
134
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
135
+
136
+ .cc.o:
137
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
138
+
139
+ .cxx.o:
140
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
141
+
142
+ .cpp.o:
143
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
144
+
145
+ .C.o:
146
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
147
+
148
+ .c.o:
149
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
150
+
151
+ $(DLLIB): $(OBJS) Makefile
152
+ @-$(RM) $@
153
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
154
+
155
+
156
+
157
+ $(OBJS): ruby.h defines.h
@@ -0,0 +1,284 @@
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 <errno.h>
32
+ #include <stdint.h>
33
+ #include <stdlib.h>
34
+ #include <string.h>
35
+
36
+ #include "sha256.h"
37
+ #include "sysendian.h"
38
+
39
+ #include "crypto_scrypt.h"
40
+
41
+ static void blkcpy(uint8_t *, uint8_t *, size_t);
42
+ static void blkxor(uint8_t *, uint8_t *, size_t);
43
+ static void salsa20_8(uint8_t[64]);
44
+ static void blockmix_salsa8(uint8_t *, uint8_t *, size_t);
45
+ static uint64_t integerify(uint8_t *, size_t);
46
+ static void smix(uint8_t *, size_t, uint64_t, uint8_t *, uint8_t *);
47
+
48
+ static void
49
+ blkcpy(uint8_t * dest, uint8_t * src, size_t len)
50
+ {
51
+ size_t i;
52
+
53
+ for (i = 0; i < len; i++)
54
+ dest[i] = src[i];
55
+ }
56
+
57
+ static void
58
+ blkxor(uint8_t * dest, uint8_t * src, size_t len)
59
+ {
60
+ size_t i;
61
+
62
+ for (i = 0; i < len; i++)
63
+ dest[i] ^= src[i];
64
+ }
65
+
66
+ /**
67
+ * salsa20_8(B):
68
+ * Apply the salsa20/8 core to the provided block.
69
+ */
70
+ static void
71
+ salsa20_8(uint8_t B[64])
72
+ {
73
+ uint32_t B32[16];
74
+ uint32_t x[16];
75
+ size_t i;
76
+
77
+ /* Convert little-endian values in. */
78
+ for (i = 0; i < 16; i++)
79
+ B32[i] = le32dec(&B[i * 4]);
80
+
81
+ /* Compute x = doubleround^4(B32). */
82
+ for (i = 0; i < 16; i++)
83
+ x[i] = B32[i];
84
+ for (i = 0; i < 8; i += 2) {
85
+ #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
86
+ /* Operate on columns. */
87
+ x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
88
+ x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
89
+
90
+ x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
91
+ x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
92
+
93
+ x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
94
+ x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
95
+
96
+ x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
97
+ x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
98
+
99
+ /* Operate on rows. */
100
+ x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
101
+ x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
102
+
103
+ x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
104
+ x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
105
+
106
+ x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
107
+ x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
108
+
109
+ x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
110
+ x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
111
+ #undef R
112
+ }
113
+
114
+ /* Compute B32 = B32 + x. */
115
+ for (i = 0; i < 16; i++)
116
+ B32[i] += x[i];
117
+
118
+ /* Convert little-endian values out. */
119
+ for (i = 0; i < 16; i++)
120
+ le32enc(&B[4 * i], B32[i]);
121
+ }
122
+
123
+ /**
124
+ * blockmix_salsa8(B, Y, r):
125
+ * Compute B = BlockMix_{salsa20/8, r}(B). The input B must be 128r bytes in
126
+ * length; the temporary space Y must also be the same size.
127
+ */
128
+ static void
129
+ blockmix_salsa8(uint8_t * B, uint8_t * Y, size_t r)
130
+ {
131
+ uint8_t X[64];
132
+ size_t i;
133
+
134
+ /* 1: X <-- B_{2r - 1} */
135
+ blkcpy(X, &B[(2 * r - 1) * 64], 64);
136
+
137
+ /* 2: for i = 0 to 2r - 1 do */
138
+ for (i = 0; i < 2 * r; i++) {
139
+ /* 3: X <-- H(X \xor B_i) */
140
+ blkxor(X, &B[i * 64], 64);
141
+ salsa20_8(X);
142
+
143
+ /* 4: Y_i <-- X */
144
+ blkcpy(&Y[i * 64], X, 64);
145
+ }
146
+
147
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
148
+ for (i = 0; i < r; i++)
149
+ blkcpy(&B[i * 64], &Y[(i * 2) * 64], 64);
150
+ for (i = 0; i < r; i++)
151
+ blkcpy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64);
152
+ }
153
+
154
+ /**
155
+ * integerify(B, r):
156
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
157
+ */
158
+ static uint64_t
159
+ integerify(uint8_t * B, size_t r)
160
+ {
161
+ uint8_t * X = &B[(2 * r - 1) * 64];
162
+
163
+ return (le64dec(X));
164
+ }
165
+
166
+ /**
167
+ * smix(B, r, N, V, XY):
168
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; the
169
+ * temporary storage V must be 128rN bytes in length; the temporary storage
170
+ * XY must be 256r bytes in length. The value N must be a power of 2.
171
+ */
172
+ static void
173
+ smix(uint8_t * B, size_t r, uint64_t N, uint8_t * V, uint8_t * XY)
174
+ {
175
+ uint8_t * X = XY;
176
+ uint8_t * Y = &XY[128 * r];
177
+ uint64_t i;
178
+ uint64_t j;
179
+
180
+ /* 1: X <-- B */
181
+ blkcpy(X, B, 128 * r);
182
+
183
+ /* 2: for i = 0 to N - 1 do */
184
+ for (i = 0; i < N; i++) {
185
+ /* 3: V_i <-- X */
186
+ blkcpy(&V[i * (128 * r)], X, 128 * r);
187
+
188
+ /* 4: X <-- H(X) */
189
+ blockmix_salsa8(X, Y, r);
190
+ }
191
+
192
+ /* 6: for i = 0 to N - 1 do */
193
+ for (i = 0; i < N; i++) {
194
+ /* 7: j <-- Integerify(X) mod N */
195
+ j = integerify(X, r) & (N - 1);
196
+
197
+ /* 8: X <-- H(X \xor V_j) */
198
+ blkxor(X, &V[j * (128 * r)], 128 * r);
199
+ blockmix_salsa8(X, Y, r);
200
+ }
201
+
202
+ /* 10: B' <-- X */
203
+ blkcpy(B, X, 128 * r);
204
+ }
205
+
206
+ /**
207
+ * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
208
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
209
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
210
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
211
+ * must be a power of 2.
212
+ *
213
+ * Return 0 on success; or -1 on error.
214
+ */
215
+ int
216
+ crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
217
+ const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
218
+ uint8_t * buf, size_t buflen)
219
+ {
220
+ uint8_t * B;
221
+ uint8_t * V;
222
+ uint8_t * XY;
223
+ uint32_t i;
224
+
225
+ /* Sanity-check parameters. */
226
+ #if SIZE_MAX > UINT32_MAX
227
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
228
+ errno = EFBIG;
229
+ goto err0;
230
+ }
231
+ #endif
232
+ if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
233
+ errno = EFBIG;
234
+ goto err0;
235
+ }
236
+ if (((N & (N - 1)) != 0) || (N == 0)) {
237
+ errno = EINVAL;
238
+ goto err0;
239
+ }
240
+ if ((r > SIZE_MAX / 128 / p) ||
241
+ #if SIZE_MAX / 256 <= UINT32_MAX
242
+ (r > SIZE_MAX / 256) ||
243
+ #endif
244
+ (N > SIZE_MAX / 128 / r)) {
245
+ errno = ENOMEM;
246
+ goto err0;
247
+ }
248
+
249
+ /* Allocate memory. */
250
+ if ((B = malloc(128 * r * p)) == NULL)
251
+ goto err0;
252
+ if ((XY = malloc(256 * r)) == NULL)
253
+ goto err1;
254
+ if ((V = malloc(128 * r * N)) == NULL)
255
+ goto err2;
256
+
257
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
258
+ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
259
+
260
+ /* 2: for i = 0 to p - 1 do */
261
+ for (i = 0; i < p; i++) {
262
+ /* 3: B_i <-- MF(B_i, N) */
263
+ smix(&B[i * 128 * r], r, N, V, XY);
264
+ }
265
+
266
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
267
+ PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
268
+
269
+ /* Free memory. */
270
+ free(V);
271
+ free(XY);
272
+ free(B);
273
+
274
+ /* Success! */
275
+ return (0);
276
+
277
+ err2:
278
+ free(XY);
279
+ err1:
280
+ free(B);
281
+ err0:
282
+ /* Failure! */
283
+ return (-1);
284
+ }