From 4c5849faed2c23033fa32fa6c8f15503f1e57f8f Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Fri, 5 Aug 2016 13:47:38 +1000
Subject: [PATCH 2/2] Ticket 397 - Implement scrypt hashing mechanism for DS

Bug Description:  We should support strong cryptographically secure hashes
to prevent offline and online attacks against passwords

Fix Description:  Add an implementation of scrypt as a password hashing module
to 389-ds.

https://fedorahosted.org/389/ticket/397

Author: wibrown

Review by: ???
---
 Makefile.am                                  |  13 ++-
 Makefile.in                                  |  45 ++++++---
 config.h.in                                  |   3 +
 configure                                    |  44 ++++++++
 configure.ac                                 |  18 ++++
 dirsrvtests/tests/tickets/ticket397_test.py  |   2 +-
 ldap/ldif/template-dse.ldif.in               |   9 ++
 ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c |   3 -
 ldap/servers/plugins/pwdstorage/pwd_init.c   |  22 ++++
 ldap/servers/plugins/pwdstorage/pwdstorage.h |  10 +-
 ldap/servers/plugins/pwdstorage/scrypt_pwd.c | 144 +++++++++++++++++++++++++++
 m4/scrypt.m4                                 |  63 ++++++++++++
 rpm/389-ds-base.spec.in                      |   5 +
 13 files changed, 358 insertions(+), 23 deletions(-)
 create mode 100644 ldap/servers/plugins/pwdstorage/scrypt_pwd.c
 create mode 100644 m4/scrypt.m4

diff --git a/Makefile.am b/Makefile.am
index 3744df7..3fa520b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,6 +32,12 @@ else
 ASAN_ON = 0
 endif
 
+if enable_scrypt
+SCRYPT_INCLUDES = $(scrypt_inc)
+SCRYPT_LINK = $(scrypt_lib) -lscrypt
+else
+endif
+
 # these paths are dependent on the settings of prefix and exec_prefix which may be specified
 # at make time.  So we cannot use AC_DEFINE in the configure.ac because that would set the
 # values prior to their being defined.  Defining them here ensures that they are properly
@@ -1400,10 +1406,11 @@ libpwdstorage_plugin_la_SOURCES = ldap/servers/plugins/pwdstorage/clear_pwd.c \
 	ldap/servers/plugins/pwdstorage/sha_pwd.c \
 	ldap/servers/plugins/pwdstorage/smd5_pwd.c \
 	ldap/servers/plugins/pwdstorage/ssha_pwd.c \
-	ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
+	ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c \
+	ldap/servers/plugins/pwdstorage/scrypt_pwd.c
 
-libpwdstorage_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
-libpwdstorage_plugin_la_LIBADD = libslapd.la $(NSS_LINK) $(NSPR_LINK) $(LIBCRYPT)
+libpwdstorage_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) $(SCRYPT_INCLUDES)
+libpwdstorage_plugin_la_LIBADD = libslapd.la $(NSS_LINK) $(NSPR_LINK) $(LIBCRYPT) $(SCRYPT_LINK)
 libpwdstorage_plugin_la_LDFLAGS = -avoid-version
 
 #------------------------
diff --git a/Makefile.in b/Makefile.in
index 735135c..7d5a7f9 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -580,9 +580,10 @@ libpresence_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(LDFLAGS) -o $@
 @enable_presence_TRUE@am_libpresence_plugin_la_rpath = -rpath \
 @enable_presence_TRUE@	$(serverplugindir)
+@enable_scrypt_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
 libpwdstorage_plugin_la_DEPENDENCIES = libslapd.la \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1)
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
 am_libpwdstorage_plugin_la_OBJECTS = ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-clear_pwd.lo \
 	ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-crypt_pwd.lo \
 	ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-md5_pwd.lo \
@@ -593,7 +594,8 @@ am_libpwdstorage_plugin_la_OBJECTS = ldap/servers/plugins/pwdstorage/libpwdstora
 	ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-sha_pwd.lo \
 	ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-smd5_pwd.lo \
 	ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-ssha_pwd.lo \
-	ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-pbkdf2_pwd.lo
+	ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-pbkdf2_pwd.lo \
+	ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-scrypt_pwd.lo
 libpwdstorage_plugin_la_OBJECTS =  \
 	$(am_libpwdstorage_plugin_la_OBJECTS)
 libpwdstorage_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
@@ -715,12 +717,12 @@ libschemareload_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(AM_CFLAGS) $(CFLAGS) $(libschemareload_plugin_la_LDFLAGS) \
 	$(LDFLAGS) -o $@
-@enable_nunc_stans_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
-am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+@enable_nunc_stans_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
 libslapd_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_3) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_4) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__libslapd_la_SOURCES_DIST = ldap/servers/slapd/add.c \
 	ldap/servers/slapd/agtmmap.c ldap/servers/slapd/apibroker.c \
@@ -963,8 +965,8 @@ am_ldap_agent_bin_OBJECTS =  \
 	ldap/servers/snmp/ldap_agent_bin-ldap-agent.$(OBJEXT) \
 	ldap/servers/slapd/ldap_agent_bin-agtmmap.$(OBJEXT)
 ldap_agent_bin_OBJECTS = $(am_ldap_agent_bin_OBJECTS)
-@OPENLDAP_FALSE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
-ldap_agent_bin_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+@OPENLDAP_FALSE@am__DEPENDENCIES_5 = $(am__DEPENDENCIES_1)
+ldap_agent_bin_DEPENDENCIES = $(am__DEPENDENCIES_5) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
@@ -1005,7 +1007,7 @@ am_ldif_bin_OBJECTS =  \
 	ldap/servers/slapd/tools/ldif_bin-ldif.$(OBJEXT)
 ldif_bin_OBJECTS = $(am_ldif_bin_OBJECTS)
 ldif_bin_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_4) $(am__DEPENDENCIES_1)
+	$(am__DEPENDENCIES_5) $(am__DEPENDENCIES_1)
 am_makstrdb_OBJECTS = lib/libsi18n/makstrdb-makstrdb.$(OBJEXT)
 makstrdb_OBJECTS = $(am_makstrdb_OBJECTS)
 makstrdb_LDADD = $(LDADD)
@@ -1019,7 +1021,7 @@ am_mmldif_bin_OBJECTS =  \
 mmldif_bin_OBJECTS = $(am_mmldif_bin_OBJECTS)
 mmldif_bin_DEPENDENCIES = libslapd.la $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_4) $(am__DEPENDENCIES_1)
+	$(am__DEPENDENCIES_5) $(am__DEPENDENCIES_1)
 am__ns_slapd_SOURCES_DIST = ldap/servers/slapd/abandon.c \
 	ldap/servers/slapd/auth.c ldap/servers/slapd/bind.c \
 	ldap/servers/slapd/compare.c ldap/servers/slapd/config.c \
@@ -1486,6 +1488,9 @@ sasl_path = @sasl_path@
 sbindir = @sbindir@
 schemadir = $(sysconfdir)@schemadir@
 scripttemplatedir = @scripttemplatedir@
+scrypt_inc = @scrypt_inc@
+scrypt_lib = @scrypt_lib@
+scrypt_libdir = @scrypt_libdir@
 serverdir = $(libdir)@serverdir@
 serverincdir = $(includedir)@serverincdir@
 serverplugindir = $(libdir)@serverplugindir@
@@ -1538,6 +1543,8 @@ DS_DEFINES = -DBUILD_NUM=$(BUILDNUM) -DVENDOR="\"$(vendor)\"" -DBRAND="\"$(brand
 DS_INCLUDES = -I$(srcdir)/ldap/include -I$(srcdir)/ldap/servers/slapd -I$(srcdir)/include -I. $(NUNC_STANS_INCLUDES)
 @enable_asan_FALSE@ASAN_ON = 0
 @enable_asan_TRUE@ASAN_ON = 1
+@enable_scrypt_TRUE@SCRYPT_INCLUDES = $(scrypt_inc)
+@enable_scrypt_TRUE@SCRYPT_LINK = $(scrypt_lib) -lscrypt
 
 # these paths are dependent on the settings of prefix and exec_prefix which may be specified
 # at make time.  So we cannot use AC_DEFINE in the configure.ac because that would set the
@@ -2756,10 +2763,11 @@ libpwdstorage_plugin_la_SOURCES = ldap/servers/plugins/pwdstorage/clear_pwd.c \
 	ldap/servers/plugins/pwdstorage/sha_pwd.c \
 	ldap/servers/plugins/pwdstorage/smd5_pwd.c \
 	ldap/servers/plugins/pwdstorage/ssha_pwd.c \
-	ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
+	ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c \
+	ldap/servers/plugins/pwdstorage/scrypt_pwd.c
 
-libpwdstorage_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
-libpwdstorage_plugin_la_LIBADD = libslapd.la $(NSS_LINK) $(NSPR_LINK) $(LIBCRYPT)
+libpwdstorage_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) $(SCRYPT_INCLUDES)
+libpwdstorage_plugin_la_LIBADD = libslapd.la $(NSS_LINK) $(NSPR_LINK) $(LIBCRYPT) $(SCRYPT_LINK)
 libpwdstorage_plugin_la_LDFLAGS = -avoid-version
 
 #------------------------
@@ -4247,6 +4255,9 @@ ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-ssha_pwd.lo:  \
 ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-pbkdf2_pwd.lo:  \
 	ldap/servers/plugins/pwdstorage/$(am__dirstamp) \
 	ldap/servers/plugins/pwdstorage/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-scrypt_pwd.lo:  \
+	ldap/servers/plugins/pwdstorage/$(am__dirstamp) \
+	ldap/servers/plugins/pwdstorage/$(DEPDIR)/$(am__dirstamp)
 
 libpwdstorage-plugin.la: $(libpwdstorage_plugin_la_OBJECTS) $(libpwdstorage_plugin_la_DEPENDENCIES) $(EXTRA_libpwdstorage_plugin_la_DEPENDENCIES) 
 	$(AM_V_CCLD)$(libpwdstorage_plugin_la_LINK) -rpath $(serverplugindir) $(libpwdstorage_plugin_la_OBJECTS) $(libpwdstorage_plugin_la_LIBADD) $(LIBS)
@@ -5654,6 +5665,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/pwdstorage/$(DEPDIR)/libpwdstorage_plugin_la-pbkdf2_pwd.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/pwdstorage/$(DEPDIR)/libpwdstorage_plugin_la-pwd_init.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/pwdstorage/$(DEPDIR)/libpwdstorage_plugin_la-pwd_util.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/pwdstorage/$(DEPDIR)/libpwdstorage_plugin_la-scrypt_pwd.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/pwdstorage/$(DEPDIR)/libpwdstorage_plugin_la-sha_pwd.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/pwdstorage/$(DEPDIR)/libpwdstorage_plugin_la-smd5_pwd.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/pwdstorage/$(DEPDIR)/libpwdstorage_plugin_la-ssha_pwd.Plo@am__quote@
@@ -7382,6 +7394,13 @@ ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-pbkdf2_pwd.lo: ldap/serv
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpwdstorage_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-pbkdf2_pwd.lo `test -f 'ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c' || echo '$(srcdir)/'`ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
 
+ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-scrypt_pwd.lo: ldap/servers/plugins/pwdstorage/scrypt_pwd.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpwdstorage_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-scrypt_pwd.lo -MD -MP -MF ldap/servers/plugins/pwdstorage/$(DEPDIR)/libpwdstorage_plugin_la-scrypt_pwd.Tpo -c -o ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-scrypt_pwd.lo `test -f 'ldap/servers/plugins/pwdstorage/scrypt_pwd.c' || echo '$(srcdir)/'`ldap/servers/plugins/pwdstorage/scrypt_pwd.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ldap/servers/plugins/pwdstorage/$(DEPDIR)/libpwdstorage_plugin_la-scrypt_pwd.Tpo ldap/servers/plugins/pwdstorage/$(DEPDIR)/libpwdstorage_plugin_la-scrypt_pwd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ldap/servers/plugins/pwdstorage/scrypt_pwd.c' object='ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-scrypt_pwd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpwdstorage_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/pwdstorage/libpwdstorage_plugin_la-scrypt_pwd.lo `test -f 'ldap/servers/plugins/pwdstorage/scrypt_pwd.c' || echo '$(srcdir)/'`ldap/servers/plugins/pwdstorage/scrypt_pwd.c
+
 ldap/servers/plugins/referint/libreferint_plugin_la-referint.lo: ldap/servers/plugins/referint/referint.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libreferint_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/referint/libreferint_plugin_la-referint.lo -MD -MP -MF ldap/servers/plugins/referint/$(DEPDIR)/libreferint_plugin_la-referint.Tpo -c -o ldap/servers/plugins/referint/libreferint_plugin_la-referint.lo `test -f 'ldap/servers/plugins/referint/referint.c' || echo '$(srcdir)/'`ldap/servers/plugins/referint/referint.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ldap/servers/plugins/referint/$(DEPDIR)/libreferint_plugin_la-referint.Tpo ldap/servers/plugins/referint/$(DEPDIR)/libreferint_plugin_la-referint.Plo
diff --git a/config.h.in b/config.h.in
index 1b549f7..8afde72 100644
--- a/config.h.in
+++ b/config.h.in
@@ -66,6 +66,9 @@
 /* enable the presence plugin */
 #undef ENABLE_PRESENCE
 
+/* enable support for scrypt password hashing algorithm. Requires libscrypt */
+#undef ENABLE_SCRYPT
+
 /* have 64-bit atomic bool compare and swap function provided by gcc */
 #undef HAVE_64BIT_ATOMIC_CAS_FUNC
 
diff --git a/configure b/configure
index 3f26631..097e346 100755
--- a/configure
+++ b/configure
@@ -643,6 +643,9 @@ systemd_defs
 systemd_lib
 systemd_inc
 localrundir
+scrypt_libdir
+scrypt_lib
+scrypt_inc
 nunc_stans_libdir
 nunc_stans_lib
 nunc_stans_inc
@@ -747,6 +750,8 @@ sampledatadir
 configdir
 with_tmpfiles_d
 with_fhs_opt
+enable_scrypt_FALSE
+enable_scrypt_TRUE
 enable_nunc_stans_FALSE
 enable_nunc_stans_TRUE
 enable_posix_winsync_FALSE
@@ -934,6 +939,7 @@ enable_presence
 enable_acctpolicy
 enable_posix_winsync
 enable_nunc_stans
+enable_scrypt
 with_fhs
 with_fhs_opt
 with_tmpfiles_d
@@ -1654,6 +1660,8 @@ Optional Features:
                           winsync (default: yes)
   --enable-nunc-stans     enable support for nunc-stans event framework
                           (default: no)
+  --enable-scrypt         enable support for scrypt password hashing
+                          algorithm. Requires libscrypt (default: yes)
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -18068,6 +18076,35 @@ else
 fi
 
 
+if test -z "$enable_scrypt" ; then
+   enable_scrypt=yes # if not set on cmdline, set default
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-scrypt" >&5
+$as_echo_n "checking for --enable-scrypt... " >&6; }
+# Check whether --enable-scrypt was given.
+if test "${enable_scrypt+set}" = set; then :
+  enableval=$enable_scrypt;
+fi
+
+if test "$enable_scrypt" = yes ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define ENABLE_SCRYPT 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+ if test "$enable_scrypt" = "yes"; then
+  enable_scrypt_TRUE=
+  enable_scrypt_FALSE='#'
+else
+  enable_scrypt_TRUE='#'
+  enable_scrypt_FALSE=
+fi
+
+
 # the default prefix - override with --prefix or --with-fhs
 
 
@@ -21463,6 +21500,9 @@ fi
 
 
 
+
+
+
 # AC_DEFINE([USE_OLD_UNHASHED], [], [Use old unhashed code])
 
 $as_echo "#define LDAP_DEBUG 1" >>confdefs.h
@@ -21693,6 +21733,10 @@ if test -z "${enable_nunc_stans_TRUE}" && test -z "${enable_nunc_stans_FALSE}";
   as_fn_error $? "conditional \"enable_nunc_stans\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${enable_scrypt_TRUE}" && test -z "${enable_scrypt_FALSE}"; then
+  as_fn_error $? "conditional \"enable_scrypt\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${WINNT_TRUE}" && test -z "${WINNT_FALSE}"; then
   as_fn_error $? "conditional \"WINNT\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/configure.ac b/configure.ac
index a7f0bbf..5189f70 100644
--- a/configure.ac
+++ b/configure.ac
@@ -269,6 +269,21 @@ else
 fi
 AM_CONDITIONAL(enable_nunc_stans,test "$enable_nunc_stans" = "yes")
 
+if test -z "$enable_scrypt" ; then
+   enable_scrypt=yes # if not set on cmdline, set default
+fi
+AC_MSG_CHECKING(for --enable-scrypt)
+AC_ARG_ENABLE(scrypt,
+        AS_HELP_STRING([--enable-scrypt],
+                       [enable support for scrypt password hashing algorithm. Requires libscrypt (default: yes)]))
+if test "$enable_scrypt" = yes ; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE([ENABLE_SCRYPT], [1], [enable support for scrypt password hashing algorithm. Requires libscrypt])
+else
+  AC_MSG_RESULT(no)
+fi
+AM_CONDITIONAL(enable_scrypt,test "$enable_scrypt" = "yes")
+
 # the default prefix - override with --prefix or --with-fhs
 AC_PREFIX_DEFAULT([/opt/$PACKAGE_NAME])
 
@@ -724,6 +739,9 @@ AC_SUBST(pcre_libdir)
 AC_SUBST(nunc_stans_inc)
 AC_SUBST(nunc_stans_lib)
 AC_SUBST(nunc_stans_libdir)
+AC_SUBST(scrypt_inc)
+AC_SUBST(scrypt_lib)
+AC_SUBST(scrypt_libdir)
 AC_SUBST(localrundir)
 AC_SUBST(systemd_inc)
 AC_SUBST(systemd_lib)
diff --git a/dirsrvtests/tests/tickets/ticket397_test.py b/dirsrvtests/tests/tickets/ticket397_test.py
index b282d93..8e4603d 100644
--- a/dirsrvtests/tests/tickets/ticket397_test.py
+++ b/dirsrvtests/tests/tickets/ticket397_test.py
@@ -134,7 +134,7 @@ def test_397(topology):
 
     # Merge this to the password suite in the future
 
-    for algo in ('PBKDF2_SHA256', ):
+    for algo in ('PBKDF2_SHA256', 'SCRYPT'):
         _test_algo(topology.standalone, algo)
 
     log.info('Test PASSED')
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index 80c31f9..c7faa51 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -219,6 +219,15 @@ nsslapd-plugininitfunc: pbkdf2_sha256_pwd_storage_scheme_init
 nsslapd-plugintype: pwdstoragescheme
 nsslapd-pluginenabled: on
 
+dn: cn=SCRYPT,cn=Password Storage Schemes,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+cn: SCRYPT
+nsslapd-pluginpath: libpwdstorage-plugin
+nsslapd-plugininitfunc: scrypt_pwd_storage_scheme_init
+nsslapd-plugintype: pwdstoragescheme
+nsslapd-pluginenabled: on
+
 dn: cn=AES,cn=Password Storage Schemes,cn=plugins,cn=config
 objectclass: top
 objectclass: nsSlapdPlugin
diff --git a/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c b/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
index 6e6adc9..86fa530 100644
--- a/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
@@ -53,7 +53,6 @@ pbkdf2_sha256_extract(char *hash_in, SECItem *salt, unsigned int *iterations)
      * Enough space should be avaliable in these for the values to fit into.
      */
 
-    memset(salt->data, 0, PBKDF2_SALT_LENGTH);
     memset(iterations, 0, PBKDF2_ITERATIONS_LENGTH);
 
     memcpy(iterations, hash_in, PBKDF2_ITERATIONS_LENGTH);
@@ -152,8 +151,6 @@ pbkdf2_sha256_pw_enc(const char *pwd)
     (void)PL_Base64Encode( hash, PBKDF2_TOTAL_LENGTH, enc + 2 + schemeNameLength);
     PR_ASSERT(enc[encsize - 1] == '\0');
 
-    slapi_log_error(SLAPI_LOG_TRACE, (char *)schemeName, "Generated hash %s\n", enc);
-
     return enc;
 }
 
diff --git a/ldap/servers/plugins/pwdstorage/pwd_init.c b/ldap/servers/plugins/pwdstorage/pwd_init.c
index 593078a..c00a857 100644
--- a/ldap/servers/plugins/pwdstorage/pwd_init.c
+++ b/ldap/servers/plugins/pwdstorage/pwd_init.c
@@ -46,6 +46,10 @@ static Slapi_PluginDesc smd5_pdesc = { "smd5-password-storage-scheme", VENDOR, D
 
 static Slapi_PluginDesc pbkdf2_sha256_pdesc = { "pbkdf2-sha256-password-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "Salted PBKDF2 SHA256 hash algorithm (PBKDF2_SHA256)" };
 
+#ifdef ENABLE_SCRYPT
+static Slapi_PluginDesc scrypt_pdesc = { "scrypt-password-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "Salted SCRYPT hash algorithm (SCRYPT)" };
+#endif
+
 static char *plugin_name = "NSPwdStoragePlugin";
 
 int
@@ -356,3 +360,21 @@ pbkdf2_sha256_pwd_storage_scheme_init(Slapi_PBlock *pb)
     return rc;
 }
 
+#ifdef ENABLE_SCRYPT
+int
+scrypt_pwd_storage_scheme_init(Slapi_PBlock *pb)
+{
+    int rc;
+
+    slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "=> scrypt_pwd_storage_scheme_init\n");
+
+    rc = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, (void *) SLAPI_PLUGIN_VERSION_01);
+    rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&scrypt_pdesc);
+    rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_ENC_FN, (void *)scrypt_pw_enc);
+    rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_CMP_FN, (void *)scrypt_pw_cmp);
+    rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_NAME, SCRYPT_SCHEME_NAME);
+
+    slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "<= scrypt_pwd_storage_scheme_init %d\n", rc);
+    return rc;
+}
+#endif
diff --git a/ldap/servers/plugins/pwdstorage/pwdstorage.h b/ldap/servers/plugins/pwdstorage/pwdstorage.h
index d59c621..a80ffb4 100644
--- a/ldap/servers/plugins/pwdstorage/pwdstorage.h
+++ b/ldap/servers/plugins/pwdstorage/pwdstorage.h
@@ -56,9 +56,6 @@
 #define PBKDF2_SHA256_SCHEME_NAME "PBKDF2_SHA256"
 #define PBKDF2_SHA256_NAME_LEN 13
 
-#define SLAPI_LOG_TRACE 0
-#define SLAPI_LOG_PLUGIN 0
-
 
 SECStatus sha_salted_hash(char *hash_out, const char *pwd, struct berval *salt, unsigned int secOID);
 int sha_pw_cmp( const char *userpwd, const char *dbpwd, unsigned int shaLen );
@@ -91,6 +88,13 @@ SECStatus pbkdf2_sha256_hash(char *hash_out, SECItem *pwd, SECItem *salt, unsign
 char * pbkdf2_sha256_pw_enc(const char *pwd);
 int pbkdf2_sha256_pw_cmp(const char *userpwd, const char *dbpwd);
 
+#ifdef ENABLE_SCRYPT
+#define SCRYPT_SCHEME_NAME "SCRYPT"
+#define SCRYPT_NAME_LEN 6;
+int scrypt_hash(char *hash_out, SECItem *pwd, SECItem *salt, unsigned int wfactor);
+char *scrypt_pw_enc(const char *pwd);
+int scrypt_pw_cmp(const char *userpwd, const char *dbpwd);
+#endif // ENABLE_SCRYPT
 /* Utility functions */
 PRUint32 pwdstorage_base64_decode_len(const char *encval, PRUint32 enclen);
 
diff --git a/ldap/servers/plugins/pwdstorage/scrypt_pwd.c b/ldap/servers/plugins/pwdstorage/scrypt_pwd.c
new file mode 100644
index 0000000..7c8abd3
--- /dev/null
+++ b/ldap/servers/plugins/pwdstorage/scrypt_pwd.c
@@ -0,0 +1,144 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright (C) 2016 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * License: GPL (version 3 or any later version).
+ * See LICENSE for details.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#ifdef ENABLE_SCRYPT
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "pwdstorage.h"
+
+/* For scrypt itself */
+#include <libscrypt.h>
+/* Scrypt sets errno */
+#include <errno.h>
+/* Need this for htonl and ntohl */
+#include <arpa/inet.h>
+
+/*
+ * slapi hashed password routings for scrypt
+ */
+
+#define SCRYPT_SALT_LENGTH 8
+#define SCRYPT_WORK_LENGTH 4
+#define SCRYPT_HASH_LENGTH 512
+#define SCRYPT_TOTAL_LENGTH SCRYPT_SALT_LENGTH + SCRYPT_WORK_LENGTH + SCRYPT_HASH_LENGTH
+
+/*
+ * WB - We keep this private as administrators won't ever set it correctly.
+ * we can continue to advance it as computing power and security recommendations
+ * change.
+ * It's CRITICAL this value is a power of 2
+ */
+#define SCRYPT_WORK_FACTOR 2 << 13
+
+static const char *schemeName = SCRYPT_SCHEME_NAME;
+static const unsigned int schemeNameLength = SCRYPT_NAME_LEN;
+
+void
+scrypt_extract(char *hash_in, SECItem *salt, unsigned int *wfactor)
+{
+    memset(wfactor, 0, SCRYPT_WORK_LENGTH);
+
+    memcpy(wfactor, hash_in, SCRYPT_WORK_LENGTH);
+
+    *wfactor = ntohl(*wfactor);
+
+    salt->data = hash_in + SCRYPT_WORK_LENGTH;
+    salt->len = SCRYPT_SALT_LENGTH;
+}
+
+int
+scrypt_hash(char *hash_out, SECItem *pwd, SECItem *salt, unsigned int wfactor)
+{
+    if (libscrypt_scrypt(pwd->data, pwd->len, salt->data, salt->len, wfactor, SCRYPT_r, SCRYPT_p, hash_out, SCRYPT_HASH_LENGTH) != 0) {
+        int err = errno;
+        slapi_log_error(SLAPI_LOG_FATAL, (char *)schemeName, "libscrypt_scrypt returned error %d\n", err);
+        return 1;
+    }
+    return 0;
+}
+
+char *
+scrypt_pw_enc(const char *pwd)
+{
+    char hash[ SCRYPT_TOTAL_LENGTH ];
+    size_t encsize = 3 + schemeNameLength + LDIF_BASE64_LEN(SCRYPT_TOTAL_LENGTH);
+    char *enc = slapi_ch_calloc(encsize, sizeof(char));
+    unsigned int wfactor = SCRYPT_WORK_FACTOR;
+
+    SECItem saltItem;
+    SECItem passItem;
+
+    memset(hash, 0, SCRYPT_TOTAL_LENGTH);
+    saltItem.data = (unsigned char *)hash + SCRYPT_WORK_LENGTH;
+    saltItem.len = SCRYPT_SALT_LENGTH;
+    passItem.data = (unsigned char *)pwd;
+    passItem.len = strlen(pwd);
+
+    slapi_rand_array(hash + SCRYPT_WORK_LENGTH, SCRYPT_SALT_LENGTH);
+
+    wfactor = htonl(wfactor);
+    memcpy(hash, &wfactor, SCRYPT_WORK_LENGTH);
+    if ( scrypt_hash(hash + SCRYPT_WORK_LENGTH + SCRYPT_SALT_LENGTH, &passItem, &saltItem, SCRYPT_WORK_FACTOR) != 0) {
+        /* Error was already reported to the log, just pass it up. */
+        return NULL;
+    }
+    sprintf(enc, "%c%s%c", PWD_HASH_PREFIX_START, schemeName, PWD_HASH_PREFIX_END);
+    (void)PL_Base64Encode(hash, SCRYPT_TOTAL_LENGTH, enc + 2 + schemeNameLength);
+
+    PR_ASSERT(enc[encsize - 1] == '\0');
+
+    return enc;
+}
+
+int
+scrypt_pw_cmp(const char *userpwd, const char *dbpwd)
+{
+    int result = 1; /* Default to fail */
+    char dbhash[ SCRYPT_TOTAL_LENGTH ];
+    unsigned char userhash[ SCRYPT_HASH_LENGTH ];
+    PRUint32 dbpwd_len = strlen(dbpwd);
+    SECItem saltItem;
+    SECItem passItem;
+    unsigned int wfactor = 0;
+
+    char *hash = dbhash + SCRYPT_WORK_LENGTH + SCRYPT_SALT_LENGTH;
+
+    slapi_log_error(SLAPI_LOG_TRACE, (char *)schemeName, "Comparing password\n");
+
+    memset(dbhash, 0, SCRYPT_TOTAL_LENGTH);
+
+    passItem.data = (unsigned char *)userpwd;
+    passItem.len = strlen(userpwd);
+
+    /* Decode the b64 so we can extract fields. */
+
+    if (PL_Base64Decode( dbpwd, dbpwd_len, dbhash) == NULL) {
+        slapi_log_error(SLAPI_LOG_FATAL, (char *)schemeName, "Unable to base64 decode dbpwd value\n");
+        return result;
+    }
+
+    scrypt_extract(dbhash, &saltItem, &wfactor);
+
+    if ( scrypt_hash(userhash, &passItem, &saltItem, wfactor) != SECSuccess) {
+        return result;
+    }
+
+    result = memcmp(userhash, hash, SCRYPT_HASH_LENGTH);
+
+    return result;
+}
+
+#endif /* ENABLE_SCRYPT */
+
diff --git a/m4/scrypt.m4 b/m4/scrypt.m4
new file mode 100644
index 0000000..2c23e80
--- /dev/null
+++ b/m4/scrypt.m4
@@ -0,0 +1,63 @@
+# BEGIN COPYRIGHT BLOCK
+# License: GPL (version 3 or any later version).
+# See LICENSE for details. 
+# END COPYRIGHT BLOCK
+
+AC_CHECKING(for scrypt)
+
+dnl  - check for --with-scrypt
+AC_MSG_CHECKING(for --with-scrypt)
+AC_ARG_WITH(scrypt, AS_HELP_STRING([--with-scrypt@<:@=PATH@:>@],[scrypt directory]),
+[
+  if test "$withval" = "yes"; then
+    AC_MSG_RESULT(yes)
+  elif test "$withval" = "no"; then
+    AC_MSG_RESULT(no)
+  elif test -d "$withval"; then
+    AC_MSG_RESULT([using $withval])
+    dnl - check the user provided location
+    scrypt_lib="-L$withval/lib"
+    scrypt_libdir="$withval/lib"
+    scrypt_incdir="$withval/include"
+    if ! test -e "$scrypt_incdir/scrypt.h" ; then
+      AC_MSG_ERROR([$withval include dir not found])
+    fi
+    scrypt_inc="-I$scrypt_incdir"
+  else
+    echo
+    AC_MSG_ERROR([$withval not found])
+  fi
+],
+AC_MSG_RESULT(no))
+
+# check for --with-scrypt-inc
+AC_MSG_CHECKING(for --with-scrypt-inc)
+AC_ARG_WITH(scrypt-inc, AS_HELP_STRING([--with-scrypt-inc=PATH],[scrypt include file directory]),
+[
+  if test -e "$withval"/scrypt.h
+  then
+    AC_MSG_RESULT([using $withval])
+    scrypt_incdir="$withval"
+    scrypt_inc="-I$withval"
+  else
+    echo
+    AC_MSG_ERROR([$withval not found])
+  fi
+],
+AC_MSG_RESULT(no))
+
+# check for --with-scrypt-lib
+AC_MSG_CHECKING(for --with-scrypt-lib)
+AC_ARG_WITH(scrypt-lib, AS_HELP_STRING([--with-scrypt-lib=PATH],[scrypt library directory]),
+[
+  if test -d "$withval"
+  then
+    AC_MSG_RESULT([using $withval])
+    scrypt_lib="-L$withval"
+    scrypt_libdir="$withval"
+  else
+    echo
+    AC_MSG_ERROR([$withval not found])
+  fi
+],
+AC_MSG_RESULT(no))
diff --git a/rpm/389-ds-base.spec.in b/rpm/389-ds-base.spec.in
index 33bf470..c998426 100644
--- a/rpm/389-ds-base.spec.in
+++ b/rpm/389-ds-base.spec.in
@@ -81,6 +81,8 @@ BuildRequires:    openssl-devel
 BuildRequires:    tcp_wrappers
 # the following is for the pam passthru auth plug-in
 BuildRequires:    pam-devel
+# For scrypt support
+BuildRequires:    libscrypt-devel
 BuildRequires:    systemd-units
 BuildRequires:    systemd-devel
 %if %{use_asan}
@@ -135,6 +137,9 @@ Requires:         perl-Socket
 Requires:         perl-NetAddr-IP
 Requires:         systemd-libs
 
+# For scrypt support
+Requires:    libscrypt
+
 %if %{use_asan}
 Requires:    libasan
 Requires:    llvm
-- 
1.8.3.1

