scrypt 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }